@rangojs/router 0.0.0-experimental.d20dd405 → 0.0.0-experimental.d68257e5
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 +314 -882
- package/dist/bin/rango.js +927 -273
- package/dist/testing/vitest.js +82 -0
- package/dist/types/__internal.d.ts +127 -0
- package/dist/types/bin/rango.d.ts +1 -0
- package/dist/types/browser/action-coordinator.d.ts +57 -0
- package/dist/types/browser/action-fence.d.ts +33 -0
- package/dist/types/browser/app-shell.d.ts +34 -0
- package/dist/types/browser/app-version.d.ts +6 -0
- package/dist/types/browser/connection-warmup.d.ts +31 -0
- package/dist/types/browser/cookie-name.d.ts +66 -0
- package/dist/types/browser/dev-discovery.d.ts +11 -0
- package/dist/types/browser/event-controller.d.ts +231 -0
- package/dist/types/browser/history-state.d.ts +26 -0
- package/dist/types/browser/index.d.ts +1 -0
- package/dist/types/browser/intercept-utils.d.ts +30 -0
- package/dist/types/browser/invalidate-client-cache.d.ts +17 -0
- package/dist/types/browser/link-interceptor.d.ts +53 -0
- package/dist/types/browser/logging.d.ts +33 -0
- package/dist/types/browser/merge-segment-loaders.d.ts +38 -0
- package/dist/types/browser/navigation-bridge.d.ts +39 -0
- package/dist/types/browser/navigation-client.d.ts +17 -0
- package/dist/types/browser/navigation-store-handle.d.ts +25 -0
- package/dist/types/browser/navigation-store.d.ts +85 -0
- package/dist/types/browser/navigation-transaction.d.ts +75 -0
- package/dist/types/browser/network-error-handler.d.ts +35 -0
- package/dist/types/browser/notify-listeners.d.ts +2 -0
- package/dist/types/browser/partial-update.d.ts +61 -0
- package/dist/types/browser/prefetch/cache.d.ts +224 -0
- package/dist/types/browser/prefetch/default-strategy.d.ts +31 -0
- package/dist/types/browser/prefetch/fetch.d.ts +52 -0
- package/dist/types/browser/prefetch/invalidation.d.ts +6 -0
- package/dist/types/browser/prefetch/loader.d.ts +12 -0
- package/dist/types/browser/prefetch/observer.d.ts +24 -0
- package/dist/types/browser/prefetch/policy.d.ts +13 -0
- package/dist/types/browser/prefetch/queue.d.ts +48 -0
- package/dist/types/browser/prefetch/resource-ready.d.ts +28 -0
- package/dist/types/browser/prefetch/runtime.d.ts +2 -0
- package/dist/types/browser/rango-state.d.ts +56 -0
- package/dist/types/browser/react/Link.d.ts +132 -0
- package/dist/types/browser/react/NavigationProvider.d.ts +88 -0
- package/dist/types/browser/react/ScrollRestoration.d.ts +78 -0
- package/dist/types/browser/react/context.d.ts +57 -0
- package/dist/types/browser/react/filter-segment-order.d.ts +35 -0
- package/dist/types/browser/react/index.d.ts +1 -0
- package/dist/types/browser/react/location-state-shared.d.ts +162 -0
- package/dist/types/browser/react/location-state.d.ts +29 -0
- package/dist/types/browser/react/mount-context.d.ts +23 -0
- package/dist/types/browser/react/nonce-context.d.ts +14 -0
- package/dist/types/browser/react/shallow-equal.d.ts +5 -0
- package/dist/types/browser/react/use-action.d.ts +61 -0
- package/dist/types/browser/react/use-handle.d.ts +21 -0
- package/dist/types/browser/react/use-href.d.ts +32 -0
- package/dist/types/browser/react/use-link-status.d.ts +36 -0
- package/dist/types/browser/react/use-mount.d.ts +24 -0
- package/dist/types/browser/react/use-navigation.d.ts +15 -0
- package/dist/types/browser/react/use-params.d.ts +21 -0
- package/dist/types/browser/react/use-pathname.d.ts +13 -0
- package/dist/types/browser/react/use-reverse.d.ts +40 -0
- package/dist/types/browser/react/use-router.d.ts +30 -0
- package/dist/types/browser/react/use-search-params.d.ts +66 -0
- package/dist/types/browser/react/use-segments.d.ts +29 -0
- package/dist/types/browser/response-adapter.d.ts +58 -0
- package/dist/types/browser/rsc-router.d.ts +146 -0
- package/dist/types/browser/scroll-restoration.d.ts +103 -0
- package/dist/types/browser/segment-reconciler.d.ts +74 -0
- package/dist/types/browser/segment-structure-assert.d.ts +16 -0
- package/dist/types/browser/server-action-bridge.d.ts +29 -0
- package/dist/types/browser/types.d.ts +546 -0
- package/dist/types/browser/validate-redirect-origin.d.ts +28 -0
- package/dist/types/build/collect-fallback-refs.d.ts +5 -0
- package/dist/types/build/generate-manifest.d.ts +106 -0
- package/dist/types/build/generate-route-types.d.ts +8 -0
- package/dist/types/build/index.d.ts +21 -0
- package/dist/types/build/merge-full-manifests.d.ts +3 -0
- package/dist/types/build/prefix-tree-utils.d.ts +56 -0
- package/dist/types/build/route-trie.d.ts +20 -0
- package/dist/types/build/route-types/ast-helpers.d.ts +3 -0
- package/dist/types/build/route-types/ast-route-extraction.d.ts +13 -0
- package/dist/types/build/route-types/codegen.d.ts +16 -0
- package/dist/types/build/route-types/include-resolution.d.ts +74 -0
- package/dist/types/build/route-types/param-extraction.d.ts +13 -0
- package/dist/types/build/route-types/per-module-writer.d.ts +20 -0
- package/dist/types/build/route-types/router-processing.d.ts +81 -0
- package/dist/types/build/route-types/scan-filter.d.ts +17 -0
- package/dist/types/build/route-types/source-scan.d.ts +13 -0
- package/dist/types/build/runtime-discovery.d.ts +24 -0
- package/dist/types/cache/background-task.d.ts +21 -0
- package/dist/types/cache/cache-error.d.ts +71 -0
- package/dist/types/cache/cache-exec-scope.d.ts +31 -0
- package/dist/types/cache/cache-key-utils.d.ts +43 -0
- package/dist/types/cache/cache-policy.d.ts +59 -0
- package/dist/types/cache/cache-runtime.d.ts +51 -0
- package/dist/types/cache/cache-scope.d.ts +215 -0
- package/dist/types/cache/cache-tag.d.ts +79 -0
- package/dist/types/cache/cf/cf-base64.d.ts +4 -0
- package/dist/types/cache/cf/cf-cache-constants.d.ts +112 -0
- package/dist/types/cache/cf/cf-cache-store.d.ts +630 -0
- package/dist/types/cache/cf/cf-cache-types.d.ts +365 -0
- package/dist/types/cache/cf/cf-kv-utils.d.ts +43 -0
- package/dist/types/cache/cf/cf-tag-marker-memo.d.ts +15 -0
- package/dist/types/cache/cf/cf-zone-purge.d.ts +31 -0
- package/dist/types/cache/cf/index.d.ts +4 -0
- package/dist/types/cache/document-cache.d.ts +71 -0
- package/dist/types/cache/handle-capture.d.ts +23 -0
- package/dist/types/cache/handle-snapshot.d.ts +39 -0
- package/dist/types/cache/index.d.ts +9 -0
- package/dist/types/cache/memory-segment-store.d.ts +163 -0
- package/dist/types/cache/profile-registry.d.ts +40 -0
- package/dist/types/cache/read-through-swr.d.ts +61 -0
- package/dist/types/cache/search-params-filter.d.ts +64 -0
- package/dist/types/cache/segment-codec.d.ts +78 -0
- package/dist/types/cache/shell-snapshot.d.ts +186 -0
- package/dist/types/cache/tag-invalidation.d.ts +74 -0
- package/dist/types/cache/taint.d.ts +77 -0
- package/dist/types/cache/types.d.ts +522 -0
- package/dist/types/cache/vercel/index.d.ts +1 -0
- package/dist/types/cache/vercel/vercel-cache-store.d.ts +268 -0
- package/dist/types/client-urls/client-root.d.ts +38 -0
- package/dist/types/client-urls/client-urls.d.ts +5 -0
- package/dist/types/client-urls/navigation.d.ts +38 -0
- package/dist/types/client-urls/revalidation-protocol.d.ts +25 -0
- package/dist/types/client-urls/server-projection.d.ts +71 -0
- package/dist/types/client-urls/types.d.ts +148 -0
- package/dist/types/client.d.ts +192 -0
- package/dist/types/client.rsc.d.ts +42 -0
- package/dist/types/cloudflare/index.d.ts +7 -0
- package/dist/types/cloudflare/tracing.d.ts +57 -0
- package/dist/types/component-utils.d.ts +46 -0
- package/dist/types/components/DefaultDocument.d.ts +13 -0
- package/dist/types/context-var.d.ts +84 -0
- package/dist/types/debug.d.ts +57 -0
- package/dist/types/decode-loader-results.d.ts +42 -0
- package/dist/types/default-error-boundary.d.ts +10 -0
- package/dist/types/defer.d.ts +89 -0
- package/dist/types/deps/browser.d.ts +1 -0
- package/dist/types/deps/html-stream-client.d.ts +1 -0
- package/dist/types/deps/html-stream-server.d.ts +1 -0
- package/dist/types/deps/rsc.d.ts +1 -0
- package/dist/types/deps/ssr.d.ts +1 -0
- package/dist/types/dev-discovery-protocol.d.ts +5 -0
- package/dist/types/encode-kv.d.ts +35 -0
- package/dist/types/errors.d.ts +227 -0
- package/dist/types/escape-script.d.ts +44 -0
- package/dist/types/handle.d.ts +93 -0
- package/dist/types/handles/MetaTags.d.ts +17 -0
- package/dist/types/handles/Scripts.d.ts +38 -0
- package/dist/types/handles/breadcrumbs.d.ts +43 -0
- package/dist/types/handles/deferred-resolution.d.ts +53 -0
- package/dist/types/handles/is-thenable.d.ts +10 -0
- package/dist/types/handles/meta.d.ts +43 -0
- package/dist/types/handles/script.d.ts +139 -0
- package/dist/types/host/cookie-handler.d.ts +8 -0
- package/dist/types/host/errors.d.ts +40 -0
- package/dist/types/host/index.d.ts +33 -0
- package/dist/types/host/pattern-matcher.d.ts +30 -0
- package/dist/types/host/router.d.ts +12 -0
- package/dist/types/host/testing.d.ts +41 -0
- package/dist/types/host/types.d.ts +148 -0
- package/dist/types/host/utils.d.ts +20 -0
- package/dist/types/href-client.d.ts +214 -0
- package/dist/types/index.d.ts +113 -0
- package/dist/types/index.rsc.d.ts +52 -0
- package/dist/types/internal-debug.d.ts +1 -0
- package/dist/types/loader-redirect.d.ts +27 -0
- package/dist/types/loader-store.d.ts +193 -0
- package/dist/types/loader.d.ts +18 -0
- package/dist/types/loader.rsc.d.ts +18 -0
- package/dist/types/missing-id-error.d.ts +1 -0
- package/dist/types/outlet-context.d.ts +32 -0
- package/dist/types/outlet-provider.d.ts +15 -0
- package/dist/types/prerender/build-shell-capture.d.ts +104 -0
- package/dist/types/prerender/param-hash.d.ts +6 -0
- package/dist/types/prerender/shell-manifest-key.d.ts +18 -0
- package/dist/types/prerender/store.d.ts +63 -0
- package/dist/types/prerender.d.ts +292 -0
- package/dist/types/redirect-origin.d.ts +71 -0
- package/dist/types/regex-escape.d.ts +6 -0
- package/dist/types/render-error-thrower.d.ts +13 -0
- package/dist/types/response-utils.d.ts +35 -0
- package/dist/types/reverse.d.ts +206 -0
- package/dist/types/root-error-boundary.d.ts +32 -0
- package/dist/types/route-content-wrapper.d.ts +84 -0
- package/dist/types/route-definition/dsl-helpers.d.ts +130 -0
- package/dist/types/route-definition/helper-factories.d.ts +22 -0
- package/dist/types/route-definition/helpers-types.d.ts +405 -0
- package/dist/types/route-definition/index.d.ts +7 -0
- package/dist/types/route-definition/redirect.d.ts +48 -0
- package/dist/types/route-definition/resolve-handler-use.d.ts +19 -0
- package/dist/types/route-definition/use-item-types.d.ts +1 -0
- package/dist/types/route-definition.d.ts +1 -0
- package/dist/types/route-map-builder.d.ts +102 -0
- package/dist/types/route-name.d.ts +27 -0
- package/dist/types/route-types.d.ts +172 -0
- package/dist/types/router/basename.d.ts +10 -0
- package/dist/types/router/content-negotiation.d.ts +91 -0
- package/dist/types/router/debug-manifest.d.ts +7 -0
- package/dist/types/router/error-handling.d.ts +110 -0
- package/dist/types/router/find-match.d.ts +19 -0
- package/dist/types/router/handler-context.d.ts +41 -0
- package/dist/types/router/instrument.d.ts +191 -0
- package/dist/types/router/intercept-resolution.d.ts +91 -0
- package/dist/types/router/lazy-includes.d.ts +26 -0
- package/dist/types/router/loader-resolution.d.ts +85 -0
- package/dist/types/router/logging.d.ts +41 -0
- package/dist/types/router/manifest.d.ts +8 -0
- package/dist/types/router/match-api.d.ts +19 -0
- package/dist/types/router/match-context.d.ts +184 -0
- package/dist/types/router/match-handlers.d.ts +48 -0
- package/dist/types/router/match-middleware/background-revalidation.d.ts +113 -0
- package/dist/types/router/match-middleware/cache-lookup.d.ts +126 -0
- package/dist/types/router/match-middleware/cache-store.d.ts +112 -0
- package/dist/types/router/match-middleware/index.d.ts +80 -0
- package/dist/types/router/match-middleware/intercept-resolution.d.ts +116 -0
- package/dist/types/router/match-middleware/segment-resolution.d.ts +94 -0
- package/dist/types/router/match-pipelines.d.ts +103 -0
- package/dist/types/router/match-result.d.ts +114 -0
- package/dist/types/router/metrics.d.ts +6 -0
- package/dist/types/router/middleware-types.d.ts +74 -0
- package/dist/types/router/middleware.d.ts +116 -0
- package/dist/types/router/navigation-snapshot.d.ts +51 -0
- package/dist/types/router/params-util.d.ts +8 -0
- package/dist/types/router/parse-pattern.d.ts +38 -0
- package/dist/types/router/pattern-matching.d.ts +169 -0
- package/dist/types/router/prefetch-cache-ttl.d.ts +27 -0
- package/dist/types/router/prefetch-default.d.ts +28 -0
- package/dist/types/router/prefetch-limits.d.ts +20 -0
- package/dist/types/router/prerender-match.d.ts +53 -0
- package/dist/types/router/preview-match.d.ts +22 -0
- package/dist/types/router/request-classification.d.ts +104 -0
- package/dist/types/router/revalidation.d.ts +64 -0
- package/dist/types/router/route-snapshot.d.ts +112 -0
- package/dist/types/router/route-trie-builder.d.ts +77 -0
- package/dist/types/router/router-context.d.ts +137 -0
- package/dist/types/router/router-interfaces.d.ts +461 -0
- package/dist/types/router/router-options.d.ts +792 -0
- package/dist/types/router/router-registry.d.ts +15 -0
- package/dist/types/router/segment-resolution/fresh.d.ts +55 -0
- package/dist/types/router/segment-resolution/helpers.d.ts +93 -0
- package/dist/types/router/segment-resolution/loader-cache.d.ts +33 -0
- package/dist/types/router/segment-resolution/loader-mask.d.ts +44 -0
- package/dist/types/router/segment-resolution/loader-snapshot.d.ts +90 -0
- package/dist/types/router/segment-resolution/mask-nested.d.ts +53 -0
- package/dist/types/router/segment-resolution/revalidation.d.ts +85 -0
- package/dist/types/router/segment-resolution/static-store.d.ts +17 -0
- package/dist/types/router/segment-resolution/streamed-handler-telemetry.d.ts +16 -0
- package/dist/types/router/segment-resolution/view-transition-default.d.ts +27 -0
- package/dist/types/router/segment-resolution.d.ts +3 -0
- package/dist/types/router/segment-wrappers.d.ts +53 -0
- package/dist/types/router/state-cookie-name.d.ts +1 -0
- package/dist/types/router/substitute-pattern-params.d.ts +23 -0
- package/dist/types/router/telemetry-otel.d.ts +113 -0
- package/dist/types/router/telemetry.d.ts +216 -0
- package/dist/types/router/timeout.d.ts +107 -0
- package/dist/types/router/tracing.d.ts +139 -0
- package/dist/types/router/transition-when.d.ts +13 -0
- package/dist/types/router/trie-matching.d.ts +32 -0
- package/dist/types/router/types.d.ts +98 -0
- package/dist/types/router/url-params.d.ts +26 -0
- package/dist/types/router.d.ts +7 -0
- package/dist/types/rsc/capture-queue.d.ts +49 -0
- package/dist/types/rsc/full-payload.d.ts +22 -0
- package/dist/types/rsc/handler-context.d.ts +32 -0
- package/dist/types/rsc/handler.d.ts +9 -0
- package/dist/types/rsc/helpers.d.ts +127 -0
- package/dist/types/rsc/index.d.ts +17 -0
- package/dist/types/rsc/json-route-result.d.ts +20 -0
- package/dist/types/rsc/loader-fetch.d.ts +14 -0
- package/dist/types/rsc/manifest-init.d.ts +18 -0
- package/dist/types/rsc/nonce.d.ts +38 -0
- package/dist/types/rsc/origin-guard.d.ts +50 -0
- package/dist/types/rsc/progressive-enhancement.d.ts +19 -0
- package/dist/types/rsc/redirect-guard.d.ts +37 -0
- package/dist/types/rsc/render-pipeline.d.ts +148 -0
- package/dist/types/rsc/response-cache-serve.d.ts +46 -0
- package/dist/types/rsc/response-error.d.ts +19 -0
- package/dist/types/rsc/response-route-handler.d.ts +29 -0
- package/dist/types/rsc/routine-plan.d.ts +124 -0
- package/dist/types/rsc/rsc-rendering.d.ts +18 -0
- package/dist/types/rsc/runtime-warnings.d.ts +22 -0
- package/dist/types/rsc/server-action.d.ts +68 -0
- package/dist/types/rsc/shell-build-manifest.d.ts +90 -0
- package/dist/types/rsc/shell-capture-constants.d.ts +44 -0
- package/dist/types/rsc/shell-capture.d.ts +425 -0
- package/dist/types/rsc/shell-serve.d.ts +200 -0
- package/dist/types/rsc/ssr-setup.d.ts +73 -0
- package/dist/types/rsc/stream-idle.d.ts +60 -0
- package/dist/types/rsc/transition-gate.d.ts +23 -0
- package/dist/types/rsc/types.d.ts +353 -0
- package/dist/types/runtime-env.d.ts +1 -0
- package/dist/types/search-params.d.ts +125 -0
- package/dist/types/segment-content-promise.d.ts +13 -0
- package/dist/types/segment-fragments.d.ts +79 -0
- package/dist/types/segment-loader-promise.d.ts +22 -0
- package/dist/types/segment-system.d.ts +86 -0
- package/dist/types/serialize.d.ts +164 -0
- package/dist/types/server/context.d.ts +520 -0
- package/dist/types/server/cookie-parse.d.ts +10 -0
- package/dist/types/server/cookie-store.d.ts +107 -0
- package/dist/types/server/fetchable-loader-store.d.ts +20 -0
- package/dist/types/server/handle-store.d.ts +131 -0
- package/dist/types/server/loader-registry.d.ts +32 -0
- package/dist/types/server/request-context.d.ts +717 -0
- package/dist/types/server/root-layout.d.ts +3 -0
- package/dist/types/server.d.ts +16 -0
- package/dist/types/ssr/index.d.ts +289 -0
- package/dist/types/ssr/inject-rsc-eager.d.ts +3 -0
- package/dist/types/ssr/preinit-client-references.d.ts +71 -0
- package/dist/types/ssr/ssr-root.d.ts +100 -0
- package/dist/types/ssr-suspension-warning.d.ts +19 -0
- package/dist/types/static-handler.d.ts +71 -0
- package/dist/types/testing/cache-status.d.ts +63 -0
- package/dist/types/testing/collect-handle.d.ts +20 -0
- package/dist/types/testing/dispatch.d.ts +127 -0
- package/dist/types/testing/dom.entry.d.ts +15 -0
- package/dist/types/testing/e2e/fixture.d.ts +37 -0
- package/dist/types/testing/e2e/index.d.ts +31 -0
- package/dist/types/testing/e2e/matchers.d.ts +17 -0
- package/dist/types/testing/e2e/page-helpers.d.ts +86 -0
- package/dist/types/testing/e2e/parity.d.ts +111 -0
- package/dist/types/testing/e2e/server.d.ts +35 -0
- package/dist/types/testing/flight-matchers.d.ts +55 -0
- package/dist/types/testing/flight-normalize.d.ts +1 -0
- package/dist/types/testing/flight-tree.d.ts +192 -0
- package/dist/types/testing/flight.d.ts +115 -0
- package/dist/types/testing/flight.entry.d.ts +27 -0
- package/dist/types/testing/generated-routes.d.ts +66 -0
- package/dist/types/testing/index.d.ts +54 -0
- package/dist/types/testing/internal/context.d.ts +225 -0
- package/dist/types/testing/internal/flight-client-globals.d.ts +1 -0
- package/dist/types/testing/internal/seed-vars.d.ts +30 -0
- package/dist/types/testing/render-handler.d.ts +160 -0
- package/dist/types/testing/render-route.d.ts +265 -0
- package/dist/types/testing/run-loader.d.ts +195 -0
- package/dist/types/testing/run-middleware.d.ts +132 -0
- package/dist/types/testing/run-transition-when.d.ts +78 -0
- package/dist/types/testing/shell-status.d.ts +81 -0
- package/dist/types/testing/vitest-stubs/cloudflare-email.d.ts +6 -0
- package/dist/types/testing/vitest-stubs/cloudflare-workers.d.ts +13 -0
- package/dist/types/testing/vitest-stubs/plugin-rsc.d.ts +7 -0
- package/dist/types/testing/vitest-stubs/version.d.ts +1 -0
- package/dist/types/testing/vitest.d.ts +205 -0
- package/dist/types/theme/ThemeProvider.d.ts +13 -0
- package/dist/types/theme/ThemeScript.d.ts +45 -0
- package/dist/types/theme/constants.d.ts +39 -0
- package/dist/types/theme/index.d.ts +29 -0
- package/dist/types/theme/theme-context.d.ts +21 -0
- package/dist/types/theme/theme-script.d.ts +26 -0
- package/dist/types/theme/types.d.ts +162 -0
- package/dist/types/theme/use-theme.d.ts +8 -0
- package/dist/types/types/boundaries.d.ts +115 -0
- package/dist/types/types/cache-types.d.ts +191 -0
- package/dist/types/types/error-types.d.ts +114 -0
- package/dist/types/types/global-namespace.d.ts +90 -0
- package/dist/types/types/handler-context.d.ts +658 -0
- package/dist/types/types/index.d.ts +11 -0
- package/dist/types/types/loader-types.d.ts +240 -0
- package/dist/types/types/request-scope.d.ts +93 -0
- package/dist/types/types/route-config.d.ts +105 -0
- package/dist/types/types/route-entry.d.ts +98 -0
- package/dist/types/types/segments.d.ts +254 -0
- package/dist/types/types.d.ts +1 -0
- package/dist/types/urls/include-helper.d.ts +17 -0
- package/dist/types/urls/include-provider.d.ts +27 -0
- package/dist/types/urls/index.d.ts +6 -0
- package/dist/types/urls/path-helper-types.d.ts +207 -0
- package/dist/types/urls/path-helper.d.ts +12 -0
- package/dist/types/urls/pattern-types.d.ts +166 -0
- package/dist/types/urls/response-types.d.ts +67 -0
- package/dist/types/urls/type-extraction.d.ts +157 -0
- package/dist/types/urls/urls-function.d.ts +24 -0
- package/dist/types/urls.d.ts +1 -0
- package/dist/types/use-loader.d.ts +150 -0
- package/dist/types/vercel/index.d.ts +10 -0
- package/dist/types/vercel/tracing.d.ts +71 -0
- package/dist/types/vite/debug.d.ts +80 -0
- package/dist/types/vite/discovery/bundle-postprocess.d.ts +12 -0
- package/dist/types/vite/discovery/client-urls-projection.d.ts +53 -0
- package/dist/types/vite/discovery/dev-prerender-cache.d.ts +65 -0
- package/dist/types/vite/discovery/discover-routers.d.ts +17 -0
- package/dist/types/vite/discovery/discovery-errors.d.ts +113 -0
- package/dist/types/vite/discovery/gate-state.d.ts +79 -0
- package/dist/types/vite/discovery/prerender-collection.d.ts +24 -0
- package/dist/types/vite/discovery/route-types-writer.d.ts +32 -0
- package/dist/types/vite/discovery/self-gen-tracking.d.ts +22 -0
- package/dist/types/vite/discovery/shell-prerender-phase.d.ts +40 -0
- package/dist/types/vite/discovery/state.d.ts +176 -0
- package/dist/types/vite/discovery/virtual-module-codegen.d.ts +15 -0
- package/dist/types/vite/encryption-key.d.ts +2 -0
- package/dist/types/vite/index.d.ts +11 -0
- package/dist/types/vite/inject-client-debug.d.ts +56 -0
- package/dist/types/vite/plugin-types.d.ts +325 -0
- package/dist/types/vite/plugins/cjs-to-esm.d.ts +6 -0
- package/dist/types/vite/plugins/client-ref-dedup.d.ts +29 -0
- package/dist/types/vite/plugins/client-ref-hashing.d.ts +35 -0
- package/dist/types/vite/plugins/cloudflare-protocol-stub.d.ts +64 -0
- package/dist/types/vite/plugins/expose-action-id.d.ts +18 -0
- package/dist/types/vite/plugins/expose-id-utils.d.ts +37 -0
- package/dist/types/vite/plugins/expose-ids/export-analysis.d.ts +19 -0
- package/dist/types/vite/plugins/expose-ids/handler-transform.d.ts +10 -0
- package/dist/types/vite/plugins/expose-ids/loader-transform.d.ts +8 -0
- package/dist/types/vite/plugins/expose-ids/router-transform.d.ts +13 -0
- package/dist/types/vite/plugins/expose-ids/types.d.ts +29 -0
- package/dist/types/vite/plugins/expose-internal-ids.d.ts +16 -0
- package/dist/types/vite/plugins/performance-tracks.d.ts +25 -0
- package/dist/types/vite/plugins/refresh-cmd.d.ts +20 -0
- package/dist/types/vite/plugins/server-ref-hashing.d.ts +24 -0
- package/dist/types/vite/plugins/server-reference-pattern.d.ts +1 -0
- package/dist/types/vite/plugins/use-cache-transform.d.ts +20 -0
- package/dist/types/vite/plugins/vercel-output.d.ts +85 -0
- package/dist/types/vite/plugins/version-injector.d.ts +21 -0
- package/dist/types/vite/plugins/version-plugin.d.ts +19 -0
- package/dist/types/vite/plugins/virtual-entries.d.ts +36 -0
- package/dist/types/vite/plugins/virtual-stub-plugin.d.ts +7 -0
- package/dist/types/vite/rango.d.ts +29 -0
- package/dist/types/vite/router-discovery.d.ts +23 -0
- package/dist/types/vite/utils/ast-handler-extract.d.ts +64 -0
- package/dist/types/vite/utils/banner.d.ts +2 -0
- package/dist/types/vite/utils/bundle-analysis.d.ts +28 -0
- package/dist/types/vite/utils/client-chunks.d.ts +55 -0
- package/dist/types/vite/utils/directive-prologue.d.ts +16 -0
- package/dist/types/vite/utils/forward-user-plugins.d.ts +37 -0
- package/dist/types/vite/utils/manifest-utils.d.ts +7 -0
- package/dist/types/vite/utils/package-resolution.d.ts +6 -0
- package/dist/types/vite/utils/prerender-utils.d.ts +32 -0
- package/dist/types/vite/utils/shared-utils.d.ts +68 -0
- package/dist/vite/index.js +10195 -4376
- package/package.json +119 -38
- package/skills/api-client/SKILL.md +211 -0
- package/skills/breadcrumbs/SKILL.md +114 -7
- package/skills/bundle-analysis/SKILL.md +159 -0
- package/skills/cache-guide/SKILL.md +232 -34
- package/skills/caching/SKILL.md +375 -19
- package/skills/catalog.json +289 -0
- package/skills/client-urls/SKILL.md +339 -0
- package/skills/cloudflare/SKILL.md +153 -0
- package/skills/cloudflare/agents/openai.yaml +4 -0
- package/skills/cloudflare/references/d1-and-local-dev.md +131 -0
- package/skills/cloudflare/references/streaming-and-deploy.md +107 -0
- package/skills/cloudflare/references/webhooks-and-crypto.md +147 -0
- package/skills/comparison/SKILL.md +50 -0
- package/skills/comparison/agents/openai.yaml +4 -0
- package/skills/comparison/references/framework-comparison.md +858 -0
- package/skills/composability/SKILL.md +124 -4
- package/skills/css/SKILL.md +76 -0
- package/skills/debug-manifest/SKILL.md +5 -11
- package/skills/defer-hydration/SKILL.md +235 -0
- package/skills/deployment-caching/SKILL.md +176 -0
- package/skills/document-cache/SKILL.md +116 -58
- package/skills/fonts/SKILL.md +1 -1
- package/skills/handler-use/SKILL.md +10 -10
- package/skills/hooks/SKILL.md +73 -725
- package/skills/hooks/data.md +282 -0
- package/skills/hooks/handle-and-actions.md +110 -0
- package/skills/hooks/navigation.md +110 -0
- package/skills/hooks/outlets.md +62 -0
- package/skills/hooks/state.md +228 -0
- package/skills/hooks/urls.md +172 -0
- package/skills/host-router/SKILL.md +129 -27
- package/skills/i18n/SKILL.md +1 -1
- package/skills/intercept/SKILL.md +50 -19
- package/skills/layout/SKILL.md +38 -19
- package/skills/links/SKILL.md +59 -11
- package/skills/loader/SKILL.md +324 -25
- package/skills/middleware/SKILL.md +56 -13
- package/skills/migrate-nextjs/SKILL.md +334 -42
- package/skills/migrate-nextjs/backend-host-swap.md +120 -0
- package/skills/migrate-react-router/SKILL.md +95 -675
- package/skills/migrate-react-router/component-migration.md +201 -0
- package/skills/migrate-react-router/data-and-actions.md +236 -0
- package/skills/migrate-react-router/route-mapping.md +284 -0
- package/skills/mime-routes/SKILL.md +55 -18
- package/skills/observability/SKILL.md +231 -0
- package/skills/parallel/SKILL.md +63 -11
- package/skills/ppr/SKILL.md +918 -0
- package/skills/prerender/SKILL.md +137 -71
- package/skills/rango/SKILL.md +325 -28
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +172 -52
- package/skills/route/SKILL.md +102 -9
- package/skills/router-setup/SKILL.md +69 -11
- package/skills/scripts/SKILL.md +189 -0
- package/skills/server-actions/SKILL.md +81 -44
- package/skills/shell-manifest/SKILL.md +194 -0
- package/skills/streams-and-websockets/SKILL.md +1 -1
- package/skills/tailwind/SKILL.md +28 -4
- package/skills/testing/SKILL.md +131 -0
- package/skills/testing/bindings.md +103 -0
- package/skills/testing/cache-prerender.md +172 -0
- package/skills/testing/client-components.md +131 -0
- package/skills/testing/e2e-parity.md +125 -0
- package/skills/testing/flight.md +91 -0
- package/skills/testing/handles.md +153 -0
- package/skills/testing/loader.md +130 -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 +9 -6
- package/skills/typesafety/SKILL.md +45 -634
- package/skills/typesafety/env-and-bindings.md +254 -0
- package/skills/typesafety/generated-files-and-cli.md +342 -0
- package/skills/typesafety/params-and-search.md +153 -0
- package/skills/typesafety/route-types.md +213 -0
- package/skills/use-cache/SKILL.md +121 -15
- package/skills/vercel/SKILL.md +149 -0
- package/skills/view-transitions/SKILL.md +133 -4
- 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/bin/rango.ts +7 -3
- package/src/browser/action-coordinator.ts +53 -36
- package/src/browser/action-fence.ts +47 -0
- package/src/browser/app-shell.ts +14 -27
- package/src/browser/connection-warmup.ts +134 -0
- package/src/browser/cookie-name.ts +140 -0
- package/src/browser/dev-discovery.ts +66 -0
- package/src/browser/event-controller.ts +359 -167
- package/src/browser/history-state.ts +21 -0
- package/src/browser/index.ts +3 -3
- package/src/browser/invalidate-client-cache.ts +52 -0
- package/src/browser/link-interceptor.ts +469 -20
- package/src/browser/logging.ts +28 -0
- package/src/browser/merge-segment-loaders.ts +6 -4
- package/src/browser/navigation-bridge.ts +159 -129
- package/src/browser/navigation-client.ts +199 -96
- package/src/browser/navigation-store-handle.ts +38 -0
- package/src/browser/navigation-store.ts +165 -345
- package/src/browser/navigation-transaction.ts +9 -59
- package/src/browser/network-error-handler.ts +34 -7
- package/src/browser/notify-listeners.ts +22 -0
- package/src/browser/partial-update.ts +226 -161
- package/src/browser/prefetch/cache.ts +240 -97
- package/src/browser/prefetch/default-strategy.ts +74 -0
- package/src/browser/prefetch/fetch.ts +317 -51
- package/src/browser/prefetch/invalidation.ts +30 -0
- package/src/browser/prefetch/loader.ts +111 -0
- package/src/browser/prefetch/observer.ts +50 -22
- package/src/browser/prefetch/queue.ts +25 -7
- package/src/browser/prefetch/runtime.ts +6 -0
- package/src/browser/rango-state.ts +177 -114
- package/src/browser/react/Link.tsx +142 -79
- package/src/browser/react/NavigationProvider.tsx +202 -163
- package/src/browser/react/ScrollRestoration.tsx +10 -6
- package/src/browser/react/context.ts +4 -0
- package/src/browser/react/filter-segment-order.ts +17 -2
- package/src/browser/react/index.ts +0 -51
- 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 +10 -5
- package/src/browser/react/use-params.ts +3 -6
- package/src/browser/react/use-reverse.ts +19 -12
- package/src/browser/react/use-router.ts +61 -17
- package/src/browser/react/use-search-params.ts +140 -22
- package/src/browser/react/use-segments.ts +0 -13
- package/src/browser/response-adapter.ts +99 -8
- package/src/browser/rsc-router.tsx +230 -42
- package/src/browser/scroll-restoration.ts +45 -33
- package/src/browser/segment-reconciler.ts +31 -21
- package/src/browser/segment-structure-assert.ts +2 -2
- package/src/browser/server-action-bridge.ts +262 -65
- package/src/browser/types.ts +126 -47
- package/src/browser/validate-redirect-origin.ts +43 -16
- package/src/build/collect-fallback-refs.ts +107 -0
- package/src/build/generate-manifest.ts +213 -184
- package/src/build/generate-route-types.ts +3 -1
- package/src/build/index.ts +11 -3
- package/src/build/merge-full-manifests.ts +161 -0
- package/src/build/prefix-tree-utils.ts +123 -0
- package/src/build/route-trie.ts +43 -281
- 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 +513 -64
- package/src/build/route-types/param-extraction.ts +6 -3
- package/src/build/route-types/per-module-writer.ts +33 -12
- package/src/build/route-types/router-processing.ts +312 -204
- 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 +32 -29
- package/src/cache/cache-error.ts +104 -0
- package/src/cache/cache-exec-scope.ts +47 -0
- package/src/cache/cache-key-utils.ts +73 -15
- package/src/cache/cache-policy.ts +108 -34
- package/src/cache/cache-runtime.ts +566 -121
- package/src/cache/cache-scope.ts +383 -105
- 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 +134 -0
- package/src/cache/cf/cf-cache-store.ts +3084 -391
- package/src/cache/cf/cf-cache-types.ts +417 -0
- package/src/cache/cf/cf-kv-utils.ts +84 -0
- package/src/cache/cf/cf-tag-marker-memo.ts +108 -0
- package/src/cache/cf/cf-zone-purge.ts +101 -0
- package/src/cache/cf/index.ts +11 -16
- package/src/cache/document-cache.ts +184 -53
- package/src/cache/handle-snapshot.ts +92 -1
- package/src/cache/index.ts +32 -20
- package/src/cache/memory-segment-store.ts +286 -37
- package/src/cache/profile-registry.ts +46 -31
- package/src/cache/read-through-swr.ts +66 -16
- package/src/cache/search-params-filter.ts +118 -0
- package/src/cache/segment-codec.ts +80 -25
- package/src/cache/shell-snapshot.ts +516 -0
- package/src/cache/tag-invalidation.ts +230 -0
- package/src/cache/taint.ts +28 -9
- package/src/cache/types.ts +343 -100
- package/src/cache/vercel/index.ts +11 -0
- package/src/cache/vercel/vercel-cache-store.ts +1264 -0
- package/src/client-urls/client-root.tsx +168 -0
- package/src/client-urls/client-urls.ts +779 -0
- package/src/client-urls/navigation.ts +237 -0
- package/src/client-urls/revalidation-protocol.ts +56 -0
- package/src/client-urls/server-projection.ts +670 -0
- package/src/client-urls/types.ts +202 -0
- package/src/client.rsc.tsx +51 -22
- package/src/client.tsx +79 -68
- package/src/cloudflare/index.ts +11 -0
- package/src/cloudflare/tracing.ts +112 -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 +165 -0
- package/src/defer.ts +185 -0
- package/src/deps/ssr.ts +4 -2
- package/src/dev-discovery-protocol.ts +11 -0
- package/src/encode-kv.ts +49 -0
- package/src/errors.ts +44 -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 +134 -0
- package/src/handles/is-thenable.ts +16 -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 +136 -24
- package/src/index.rsc.ts +105 -12
- package/src/index.ts +103 -14
- package/src/internal-debug.ts +11 -10
- package/src/loader-redirect.tsx +64 -0
- 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 +20 -0
- package/src/outlet-provider.tsx +20 -6
- package/src/prerender/build-shell-capture.ts +453 -0
- package/src/prerender/param-hash.ts +16 -16
- package/src/prerender/shell-manifest-key.ts +20 -0
- package/src/prerender/store.ts +47 -38
- package/src/prerender.ts +81 -13
- package/src/redirect-origin.ts +172 -0
- package/src/regex-escape.ts +8 -0
- package/src/render-error-thrower.tsx +20 -0
- package/src/response-utils.ts +34 -0
- package/src/reverse.ts +16 -13
- package/src/root-error-boundary.tsx +1 -19
- package/src/route-content-wrapper.tsx +120 -78
- package/src/route-definition/dsl-helpers.ts +331 -315
- package/src/route-definition/helper-factories.ts +28 -140
- package/src/route-definition/helpers-types.ts +100 -61
- package/src/route-definition/index.ts +1 -2
- package/src/route-definition/redirect.ts +60 -28
- package/src/route-definition/resolve-handler-use.ts +6 -1
- package/src/route-definition/use-item-types.ts +29 -0
- package/src/route-map-builder.ts +102 -74
- package/src/route-types.ts +19 -46
- package/src/router/basename.ts +14 -0
- package/src/router/content-negotiation.ts +120 -30
- package/src/router/error-handling.ts +110 -29
- package/src/router/find-match.ts +129 -30
- package/src/router/handler-context.ts +37 -16
- package/src/router/instrument.ts +401 -0
- package/src/router/intercept-resolution.ts +98 -21
- package/src/router/lazy-includes.ts +82 -58
- package/src/router/loader-resolution.ts +426 -85
- package/src/router/logging.ts +0 -6
- package/src/router/manifest.ts +74 -40
- package/src/router/match-api.ts +90 -55
- package/src/router/match-context.ts +0 -22
- package/src/router/match-handlers.ts +267 -171
- package/src/router/match-middleware/background-revalidation.ts +40 -24
- package/src/router/match-middleware/cache-lookup.ts +316 -302
- package/src/router/match-middleware/cache-store.ts +134 -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 +72 -94
- package/src/router/metrics.ts +17 -36
- package/src/router/middleware-types.ts +15 -114
- package/src/router/middleware.ts +276 -193
- package/src/router/navigation-snapshot.ts +51 -60
- package/src/router/params-util.ts +23 -0
- package/src/router/parse-pattern.ts +115 -0
- package/src/router/pattern-matching.ts +99 -152
- package/src/router/prefetch-cache-ttl.ts +51 -0
- package/src/router/prefetch-default.ts +59 -0
- package/src/router/prefetch-limits.ts +37 -0
- package/src/router/prerender-match.ts +159 -69
- package/src/router/preview-match.ts +6 -2
- package/src/router/request-classification.ts +50 -69
- package/src/router/revalidation.ts +134 -85
- package/src/router/route-snapshot.ts +14 -3
- package/src/router/route-trie-builder.ts +334 -0
- package/src/router/router-context.ts +6 -29
- package/src/router/router-interfaces.ts +168 -38
- package/src/router/router-options.ts +235 -11
- package/src/router/router-registry.ts +2 -5
- package/src/router/segment-resolution/fresh.ts +211 -88
- package/src/router/segment-resolution/helpers.ts +96 -18
- package/src/router/segment-resolution/loader-cache.ts +208 -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 +99 -0
- package/src/router/segment-resolution/revalidation.ts +277 -308
- package/src/router/segment-resolution/static-store.ts +55 -15
- package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
- package/src/router/segment-resolution/view-transition-default.ts +60 -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 +54 -35
- package/src/router/telemetry-otel.ts +171 -200
- package/src/router/telemetry.ts +106 -20
- package/src/router/timeout.ts +53 -22
- package/src/router/tracing.ts +235 -0
- package/src/router/transition-when.ts +76 -0
- package/src/router/trie-matching.ts +171 -64
- package/src/router/types.ts +9 -63
- package/src/router/url-params.ts +13 -5
- package/src/router.ts +248 -77
- package/src/rsc/capture-queue.ts +218 -0
- package/src/rsc/full-payload.ts +77 -0
- package/src/rsc/handler-context.ts +4 -2
- package/src/rsc/handler.ts +566 -288
- package/src/rsc/helpers.ts +179 -9
- package/src/rsc/index.ts +2 -5
- package/src/rsc/json-route-result.ts +38 -0
- package/src/rsc/loader-fetch.ts +116 -40
- package/src/rsc/manifest-init.ts +55 -56
- package/src/rsc/nonce.ts +26 -1
- package/src/rsc/origin-guard.ts +39 -25
- package/src/rsc/progressive-enhancement.ts +376 -85
- package/src/rsc/redirect-guard.ts +102 -0
- package/src/rsc/render-pipeline.ts +611 -0
- package/src/rsc/response-cache-serve.ts +259 -0
- package/src/rsc/response-error.ts +79 -12
- package/src/rsc/response-route-handler.ts +73 -212
- package/src/rsc/routine-plan.ts +359 -0
- package/src/rsc/rsc-rendering.ts +1645 -172
- package/src/rsc/runtime-warnings.ts +23 -10
- package/src/rsc/server-action.ts +419 -140
- package/src/rsc/shell-build-manifest.ts +343 -0
- package/src/rsc/shell-capture-constants.ts +45 -0
- package/src/rsc/shell-capture.ts +2135 -0
- package/src/rsc/shell-serve.ts +350 -0
- package/src/rsc/ssr-setup.ts +124 -16
- package/src/rsc/stream-idle.ts +137 -0
- package/src/rsc/transition-gate.ts +86 -0
- package/src/rsc/types.ts +119 -7
- package/src/runtime-env.ts +18 -0
- package/src/search-params.ts +35 -30
- package/src/segment-fragments.ts +165 -0
- package/src/segment-loader-promise.ts +49 -4
- package/src/segment-system.tsx +405 -146
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +426 -55
- package/src/server/cookie-parse.ts +32 -0
- package/src/server/cookie-store.ts +162 -15
- package/src/server/handle-store.ts +190 -70
- package/src/server/loader-registry.ts +33 -42
- package/src/server/request-context.ts +818 -177
- package/src/server.ts +7 -2
- package/src/ssr/index.tsx +737 -187
- package/src/ssr/inject-rsc-eager.ts +167 -0
- package/src/ssr/preinit-client-references.ts +106 -0
- package/src/ssr/ssr-root.tsx +332 -0
- package/src/ssr-suspension-warning.ts +67 -0
- package/src/static-handler.ts +28 -15
- package/src/testing/cache-status.ts +162 -0
- package/src/testing/collect-handle.ts +46 -0
- package/src/testing/dispatch.ts +951 -0
- package/src/testing/dom.entry.ts +22 -0
- package/src/testing/e2e/fixture.ts +188 -0
- package/src/testing/e2e/index.ts +147 -0
- package/src/testing/e2e/matchers.ts +35 -0
- package/src/testing/e2e/page-helpers.ts +319 -0
- package/src/testing/e2e/parity.ts +400 -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 +121 -0
- package/src/testing/internal/context.ts +380 -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 +371 -0
- package/src/testing/render-route.tsx +667 -0
- package/src/testing/run-loader.ts +423 -0
- package/src/testing/run-middleware.ts +219 -0
- package/src/testing/run-transition-when.ts +197 -0
- package/src/testing/shell-status.ts +206 -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 +19 -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 +111 -25
- package/src/types/index.ts +4 -10
- package/src/types/loader-types.ts +71 -7
- package/src/types/request-scope.ts +8 -22
- package/src/types/route-config.ts +20 -52
- package/src/types/route-entry.ts +3 -6
- package/src/types/segments.ts +138 -14
- package/src/urls/include-helper.ts +38 -64
- package/src/urls/include-provider.ts +71 -0
- package/src/urls/index.ts +2 -11
- package/src/urls/path-helper-types.ts +88 -25
- package/src/urls/path-helper.ts +30 -110
- package/src/urls/pattern-types.ts +101 -19
- package/src/urls/response-types.ts +20 -19
- package/src/urls/type-extraction.ts +98 -154
- package/src/urls/urls-function.ts +1 -19
- package/src/use-loader.tsx +379 -110
- package/src/vercel/index.ts +11 -0
- package/src/vercel/tracing.ts +89 -0
- package/src/vite/debug.ts +1 -0
- package/src/vite/discovery/bundle-postprocess.ts +18 -14
- package/src/vite/discovery/client-urls-projection.ts +322 -0
- package/src/vite/discovery/dev-prerender-cache.ts +117 -0
- package/src/vite/discovery/discover-routers.ts +152 -153
- package/src/vite/discovery/discovery-errors.ts +255 -0
- package/src/vite/discovery/prerender-collection.ts +77 -69
- package/src/vite/discovery/route-types-writer.ts +40 -84
- package/src/vite/discovery/shell-prerender-phase.ts +402 -0
- package/src/vite/discovery/state.ts +110 -6
- package/src/vite/discovery/virtual-module-codegen.ts +226 -87
- package/src/vite/encryption-key.ts +29 -0
- package/src/vite/index.ts +12 -0
- package/src/vite/inject-client-debug.ts +88 -0
- package/src/vite/plugin-types.ts +271 -10
- package/src/vite/plugins/cjs-to-esm.ts +11 -19
- package/src/vite/plugins/client-ref-dedup.ts +281 -30
- package/src/vite/plugins/client-ref-hashing.ts +12 -11
- package/src/vite/plugins/cloudflare-protocol-stub.ts +1 -21
- package/src/vite/plugins/expose-action-id.ts +51 -100
- 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 +98 -26
- package/src/vite/plugins/expose-internal-ids.ts +103 -68
- package/src/vite/plugins/performance-tracks.ts +9 -16
- package/src/vite/plugins/refresh-cmd.ts +1 -1
- package/src/vite/plugins/server-ref-hashing.ts +74 -0
- package/src/vite/plugins/server-reference-pattern.ts +10 -0
- package/src/vite/plugins/use-cache-transform.ts +26 -49
- package/src/vite/plugins/vercel-output.ts +384 -0
- package/src/vite/plugins/version-injector.ts +24 -40
- package/src/vite/plugins/version-plugin.ts +45 -40
- package/src/vite/plugins/virtual-entries.ts +202 -30
- package/src/vite/rango.ts +241 -126
- package/src/vite/router-discovery.ts +1123 -143
- package/src/vite/utils/ast-handler-extract.ts +26 -35
- 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 +1 -59
- package/src/vite/utils/package-resolution.ts +2 -73
- package/src/vite/utils/prerender-utils.ts +96 -50
- package/src/vite/utils/shared-utils.ts +162 -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/rsc/handler.ts
CHANGED
|
@@ -7,13 +7,11 @@
|
|
|
7
7
|
* and progressive enhancement (no-JS form submissions).
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import {
|
|
11
|
-
import { RouteNotFoundError } from "../errors.js";
|
|
10
|
+
import { isRouteNotFoundError } from "../errors.js";
|
|
12
11
|
import { matchMiddleware, executeMiddleware } from "../router/middleware.js";
|
|
13
12
|
import {
|
|
14
13
|
runWithRequestContext,
|
|
15
14
|
setRequestContextParams,
|
|
16
|
-
requireRequestContext,
|
|
17
15
|
getRequestContext,
|
|
18
16
|
_getRequestContext,
|
|
19
17
|
createRequestContext,
|
|
@@ -31,32 +29,47 @@ import {
|
|
|
31
29
|
interceptRedirectForPartial,
|
|
32
30
|
buildRouteMiddlewareEntries,
|
|
33
31
|
} from "./helpers.js";
|
|
34
|
-
import {
|
|
32
|
+
import { renderRscFlightStage, renderRscResponse } from "./render-pipeline.js";
|
|
33
|
+
import { guardOutgoingRedirect } from "./redirect-guard.js";
|
|
34
|
+
import {
|
|
35
|
+
resolveSoftRedirectUrl,
|
|
36
|
+
resolveExternalRedirect,
|
|
37
|
+
safeSameOriginLanding,
|
|
38
|
+
} from "../redirect-origin.js";
|
|
39
|
+
import { resolvedHandleStream } from "../handles/deferred-resolution.js";
|
|
40
|
+
import {
|
|
41
|
+
isWebSocketUpgradeResponse,
|
|
42
|
+
appendVaryAccept,
|
|
43
|
+
} from "../response-utils.js";
|
|
35
44
|
import {
|
|
36
45
|
handleResponseRoute,
|
|
37
46
|
type ResponseRouteMatch,
|
|
38
47
|
} from "./response-route-handler.js";
|
|
39
|
-
import {
|
|
48
|
+
import { nonce as nonceToken, resolveProviderNonce } from "./nonce.js";
|
|
40
49
|
import { VERSION } from "@rangojs/router:version";
|
|
41
50
|
import type { ErrorPhase } from "../types.js";
|
|
42
51
|
import type { RouterRequestInput } from "../router/router-interfaces.js";
|
|
43
|
-
import {
|
|
52
|
+
import {
|
|
53
|
+
invokeOnError,
|
|
54
|
+
resolveDefaultNotFound,
|
|
55
|
+
} from "../router/error-handling.js";
|
|
44
56
|
import {
|
|
45
57
|
createReverseFunction,
|
|
46
58
|
stripInternalParams,
|
|
47
59
|
} from "../router/handler-context.js";
|
|
48
|
-
import { getRouterContext } from "../router/router-context.js";
|
|
49
|
-
import { resolveSink, safeEmit } from "../router/telemetry.js";
|
|
50
60
|
import { contextSet } from "../context-var.js";
|
|
51
61
|
import {
|
|
52
62
|
hasCachedManifest,
|
|
53
|
-
getRouteTrie,
|
|
54
|
-
getPrecomputedEntries,
|
|
55
63
|
waitForManifestReady,
|
|
56
64
|
getRouterManifest,
|
|
57
65
|
getRouterTrie,
|
|
58
66
|
} from "../route-map-builder.js";
|
|
59
67
|
import type { HandlerContext } from "./handler-context.js";
|
|
68
|
+
import type { CacheErrorCategory } from "../cache/cache-error.js";
|
|
69
|
+
import {
|
|
70
|
+
compileSearchParamsFilter,
|
|
71
|
+
type SearchParamsFilter,
|
|
72
|
+
} from "../cache/search-params-filter.js";
|
|
60
73
|
import type { SegmentCacheStore } from "../cache/types.js";
|
|
61
74
|
import { buildRouterTrieFromUrlpatterns } from "./manifest-init.js";
|
|
62
75
|
import { handleProgressiveEnhancement } from "./progressive-enhancement.js";
|
|
@@ -66,23 +79,32 @@ import {
|
|
|
66
79
|
type ActionContinuation,
|
|
67
80
|
} from "./server-action.js";
|
|
68
81
|
import { handleLoaderFetch } from "./loader-fetch.js";
|
|
69
|
-
import {
|
|
82
|
+
import { applyStreamIdleTimeout } from "./stream-idle.js";
|
|
83
|
+
import {
|
|
84
|
+
checkRequestOrigin,
|
|
85
|
+
ORIGIN_CHECK_PHASE_BY_MODE,
|
|
86
|
+
} from "./origin-guard.js";
|
|
70
87
|
import { handleRscRendering } from "./rsc-rendering.js";
|
|
71
88
|
import {
|
|
72
89
|
withTimeout,
|
|
90
|
+
isTimeoutEnabled,
|
|
73
91
|
RouterTimeoutError,
|
|
74
92
|
createDefaultTimeoutResponse,
|
|
75
93
|
type TimeoutPhase,
|
|
94
|
+
type RenderTimeoutContext,
|
|
76
95
|
} from "../router/timeout.js";
|
|
77
96
|
import {
|
|
78
97
|
createMetricsStore,
|
|
79
98
|
appendMetric,
|
|
80
99
|
buildMetricsTiming,
|
|
81
100
|
} from "../router/metrics.js";
|
|
101
|
+
import { observePhase, PHASES } from "../router/instrument.js";
|
|
102
|
+
import { safeEmit, resolveSink, getRequestId } from "../router/telemetry.js";
|
|
82
103
|
import {
|
|
83
104
|
startSSRSetup,
|
|
84
|
-
|
|
105
|
+
createSsrHtmlStage,
|
|
85
106
|
mayNeedSSR,
|
|
107
|
+
isRscRequest,
|
|
86
108
|
SSR_SETUP_VAR,
|
|
87
109
|
} from "./ssr-setup.js";
|
|
88
110
|
import {
|
|
@@ -90,6 +112,7 @@ import {
|
|
|
90
112
|
type RequestPlan,
|
|
91
113
|
type ExecutableRequestPlan,
|
|
92
114
|
} from "../router/request-classification.js";
|
|
115
|
+
import { INTERNAL_RANGO_DEBUG } from "../internal-debug.js";
|
|
93
116
|
|
|
94
117
|
/**
|
|
95
118
|
* Create an RSC request handler.
|
|
@@ -124,12 +147,35 @@ import {
|
|
|
124
147
|
* });
|
|
125
148
|
* ```
|
|
126
149
|
*/
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Response that tells the client to do a full document navigation. Shared by
|
|
153
|
+
* the terminal reload plans (version-mismatch and app-switch): an empty 200
|
|
154
|
+
* carrying X-RSC-Reload, which the client turns into window.location.href.
|
|
155
|
+
*/
|
|
156
|
+
function createReloadResponse(reloadUrl: string) {
|
|
157
|
+
return createResponseWithMergedHeaders(null, {
|
|
158
|
+
status: 200,
|
|
159
|
+
headers: {
|
|
160
|
+
"X-RSC-Reload": reloadUrl,
|
|
161
|
+
"content-type": "text/x-component;charset=utf-8",
|
|
162
|
+
},
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
|
|
127
166
|
export function createRSCHandler<
|
|
128
167
|
TEnv = unknown,
|
|
129
168
|
TRoutes extends Record<string, string> = Record<string, string>,
|
|
130
169
|
>(options: CreateRSCHandlerOptions<TEnv, TRoutes>) {
|
|
131
170
|
const { router, version = VERSION, nonce: nonceProvider } = options;
|
|
132
171
|
|
|
172
|
+
// Handler-owned registry of explicit per-scope stores from cache({ store }).
|
|
173
|
+
// Lives in the closure so it is scoped per handler (multi-router deployments
|
|
174
|
+
// get separate registries) and accumulates every explicit store this handler
|
|
175
|
+
// resolves across requests. updateTag()/revalidateTag() iterate it to reach
|
|
176
|
+
// stores not covered by the app-level ctx._cacheStore.
|
|
177
|
+
const explicitTaggedStores = new Set<SegmentCacheStore>();
|
|
178
|
+
|
|
133
179
|
// Use provided deps or default to @vitejs/plugin-rsc/rsc exports
|
|
134
180
|
const deps = options.deps ?? rscDeps;
|
|
135
181
|
const {
|
|
@@ -204,7 +250,44 @@ export function createRSCHandler<
|
|
|
204
250
|
actionId?: string,
|
|
205
251
|
): Promise<Response> {
|
|
206
252
|
const timeoutError = new RouterTimeoutError(phase, durationMs);
|
|
253
|
+
const requestContext = _getRequestContext<TEnv>();
|
|
254
|
+
const cursor = requestContext?._renderForeground;
|
|
255
|
+
const render: RenderTimeoutContext | undefined =
|
|
256
|
+
phase === "render-start" && cursor
|
|
257
|
+
? {
|
|
258
|
+
mode: cursor.mode,
|
|
259
|
+
phase: cursor.phase,
|
|
260
|
+
state: cursor.state,
|
|
261
|
+
completed: cursor.completed,
|
|
262
|
+
total: cursor.total,
|
|
263
|
+
...(cursor.phaseStartedAt !== undefined && {
|
|
264
|
+
phaseDurationMs: performance.now() - cursor.phaseStartedAt,
|
|
265
|
+
}),
|
|
266
|
+
}
|
|
267
|
+
: undefined;
|
|
268
|
+
const trace =
|
|
269
|
+
phase === "render-start" ? requestContext?._activeRoutine : undefined;
|
|
270
|
+
const activeEntries = trace?.active() ?? [];
|
|
271
|
+
const activeStep = activeEntries.at(-1);
|
|
272
|
+
const activeAt = performance.now();
|
|
273
|
+
const routineSnapshot =
|
|
274
|
+
trace && activeStep
|
|
275
|
+
? {
|
|
276
|
+
name: trace.name,
|
|
277
|
+
path: activeEntries.map((entry) => entry.name),
|
|
278
|
+
durationMs: activeAt - activeStep.startedAt,
|
|
279
|
+
}
|
|
280
|
+
: undefined;
|
|
281
|
+
|
|
282
|
+
if (INTERNAL_RANGO_DEBUG && trace && activeStep) {
|
|
283
|
+
console.log(
|
|
284
|
+
`[routine] TIMEOUT ${request.method} ${url.pathname} (${trace.name})\n${trace.formatActive(activeEntries, activeAt)}`,
|
|
285
|
+
);
|
|
286
|
+
}
|
|
207
287
|
|
|
288
|
+
// Each surface gets its OWN shallow render snapshot. A consumer that mutates
|
|
289
|
+
// its copy must not corrupt what the other two observe. The internal-debug
|
|
290
|
+
// routine snapshot is bounded metadata sent only to onError.
|
|
208
291
|
callOnError(timeoutError, phase === "action" ? "action" : "handler", {
|
|
209
292
|
request,
|
|
210
293
|
url,
|
|
@@ -212,26 +295,28 @@ export function createRSCHandler<
|
|
|
212
295
|
routeKey,
|
|
213
296
|
actionId,
|
|
214
297
|
handledByBoundary: false,
|
|
215
|
-
metadata: {
|
|
298
|
+
metadata: {
|
|
299
|
+
timeout: true,
|
|
300
|
+
phase,
|
|
301
|
+
durationMs,
|
|
302
|
+
...(render && { render: { ...render } }),
|
|
303
|
+
...(routineSnapshot && { routine: routineSnapshot }),
|
|
304
|
+
},
|
|
216
305
|
});
|
|
217
306
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
});
|
|
232
|
-
}
|
|
233
|
-
} catch {
|
|
234
|
-
// Router context may not be available
|
|
307
|
+
if (router.telemetry) {
|
|
308
|
+
safeEmit(resolveSink(router.telemetry), {
|
|
309
|
+
type: "request.timeout",
|
|
310
|
+
timestamp: performance.now(),
|
|
311
|
+
requestId: getRequestId(request),
|
|
312
|
+
phase,
|
|
313
|
+
pathname: url.pathname,
|
|
314
|
+
routeKey,
|
|
315
|
+
actionId,
|
|
316
|
+
durationMs,
|
|
317
|
+
customHandler: !!router.onTimeout,
|
|
318
|
+
...(render && { render: { ...render } }),
|
|
319
|
+
});
|
|
235
320
|
}
|
|
236
321
|
|
|
237
322
|
if (router.onTimeout) {
|
|
@@ -244,6 +329,7 @@ export function createRSCHandler<
|
|
|
244
329
|
routeKey,
|
|
245
330
|
actionId,
|
|
246
331
|
durationMs,
|
|
332
|
+
...(render && { render: { ...render } }),
|
|
247
333
|
});
|
|
248
334
|
} catch (e) {
|
|
249
335
|
if (process.env.NODE_ENV !== "production") {
|
|
@@ -260,20 +346,66 @@ export function createRSCHandler<
|
|
|
260
346
|
* Build a 200 Flight response that carries a redirect URL and optional state.
|
|
261
347
|
* Used when a partial/action request results in a redirect -- fetch
|
|
262
348
|
* auto-follows 3xx so we send the redirect as payload metadata instead.
|
|
349
|
+
*
|
|
350
|
+
* The redirect URL is resolved with {@link resolveSoftRedirectUrl} against
|
|
351
|
+
* the current request origin so an unsafe target never leaves as Flight
|
|
352
|
+
* metadata (client validators remain defense-in-depth).
|
|
263
353
|
*/
|
|
264
354
|
function createRedirectFlightResponse(
|
|
265
355
|
redirectUrl: string,
|
|
266
356
|
locationState?: Record<string, unknown>,
|
|
357
|
+
external?: boolean,
|
|
267
358
|
): Response {
|
|
359
|
+
const reqCtx = _getRequestContext<TEnv>();
|
|
360
|
+
const requestOrigin =
|
|
361
|
+
reqCtx?.url.origin ?? new URL("http://localhost").origin;
|
|
362
|
+
// Resolve with the same policy as 3xx guardOutgoingRedirect. Keep
|
|
363
|
+
// external:true only when the external scheme check passed; a neutralized
|
|
364
|
+
// landing (javascript:/blocked) must not advertise external.
|
|
365
|
+
let resolvedUrl: string;
|
|
366
|
+
let resolvedExternal = false;
|
|
367
|
+
if (external) {
|
|
368
|
+
const ext = resolveExternalRedirect(redirectUrl, requestOrigin);
|
|
369
|
+
if (ext !== null) {
|
|
370
|
+
resolvedUrl = ext;
|
|
371
|
+
resolvedExternal = true;
|
|
372
|
+
} else {
|
|
373
|
+
resolvedUrl = safeSameOriginLanding(router.basename);
|
|
374
|
+
}
|
|
375
|
+
} else {
|
|
376
|
+
resolvedUrl = resolveSoftRedirectUrl(
|
|
377
|
+
redirectUrl,
|
|
378
|
+
requestOrigin,
|
|
379
|
+
router.basename,
|
|
380
|
+
false,
|
|
381
|
+
);
|
|
382
|
+
}
|
|
268
383
|
const redirectPayload: RscPayload = {
|
|
269
384
|
metadata: {
|
|
270
|
-
pathname:
|
|
385
|
+
pathname: resolvedUrl,
|
|
271
386
|
segments: [],
|
|
272
|
-
redirect: {
|
|
387
|
+
redirect: {
|
|
388
|
+
url: resolvedUrl,
|
|
389
|
+
...(resolvedExternal && { external: true }),
|
|
390
|
+
},
|
|
273
391
|
...(locationState && { locationState }),
|
|
274
392
|
},
|
|
275
393
|
};
|
|
276
|
-
const rscStream =
|
|
394
|
+
const rscStream = reqCtx
|
|
395
|
+
? renderRscFlightStage({
|
|
396
|
+
ctx: { renderToReadableStream, callOnError },
|
|
397
|
+
request: reqCtx.request,
|
|
398
|
+
url: reqCtx.url,
|
|
399
|
+
env: reqCtx.env,
|
|
400
|
+
payload: redirectPayload,
|
|
401
|
+
tracking: {
|
|
402
|
+
mode: reqCtx.url.searchParams.has("_rsc_action")
|
|
403
|
+
? "action-revalidation"
|
|
404
|
+
: "partial",
|
|
405
|
+
routeKey: reqCtx._routeName,
|
|
406
|
+
},
|
|
407
|
+
}).stream
|
|
408
|
+
: renderToReadableStream<RscPayload>(redirectPayload);
|
|
277
409
|
return createResponseWithMergedHeaders(rscStream, {
|
|
278
410
|
status: 200,
|
|
279
411
|
headers: { "content-type": "text/x-component;charset=utf-8" },
|
|
@@ -285,6 +417,7 @@ export function createRSCHandler<
|
|
|
285
417
|
const handlerCtx: HandlerContext<TEnv> = {
|
|
286
418
|
router,
|
|
287
419
|
version,
|
|
420
|
+
devDiscoveryEpoch: router.__devDiscoveryEpoch,
|
|
288
421
|
renderToReadableStream,
|
|
289
422
|
decodeReply,
|
|
290
423
|
createTemporaryReferenceSet,
|
|
@@ -323,12 +456,12 @@ export function createRSCHandler<
|
|
|
323
456
|
}
|
|
324
457
|
}
|
|
325
458
|
|
|
326
|
-
// Resolve nonce if provider is set
|
|
459
|
+
// Resolve nonce if provider is set. false/"" normalize to undefined —
|
|
460
|
+
// the per-request opt-out (resolveProviderNonce).
|
|
327
461
|
const nonceStart = performance.now();
|
|
328
462
|
let nonce: string | undefined;
|
|
329
463
|
if (nonceProvider) {
|
|
330
|
-
|
|
331
|
-
nonce = result === true ? generateNonce() : result;
|
|
464
|
+
nonce = resolveProviderNonce(await nonceProvider(request, env));
|
|
332
465
|
}
|
|
333
466
|
const nonceDur = performance.now() - nonceStart;
|
|
334
467
|
|
|
@@ -355,6 +488,7 @@ export function createRSCHandler<
|
|
|
355
488
|
// Priority: options.cache (handler override) > router.cache (router default)
|
|
356
489
|
// Store is enabled only if: config provided, enabled, and no ?__no_cache query param
|
|
357
490
|
let cacheStore: SegmentCacheStore | undefined;
|
|
491
|
+
let searchParamsFilter: SearchParamsFilter | undefined;
|
|
358
492
|
const cacheOption = options.cache ?? router.cache;
|
|
359
493
|
if (cacheOption && !url.searchParams.has("__no_cache")) {
|
|
360
494
|
const cacheConfig =
|
|
@@ -364,6 +498,9 @@ export function createRSCHandler<
|
|
|
364
498
|
|
|
365
499
|
if (cacheConfig.enabled !== false) {
|
|
366
500
|
cacheStore = cacheConfig.store;
|
|
501
|
+
searchParamsFilter = compileSearchParamsFilter(
|
|
502
|
+
cacheConfig.searchParams,
|
|
503
|
+
);
|
|
367
504
|
}
|
|
368
505
|
}
|
|
369
506
|
|
|
@@ -421,10 +558,25 @@ export function createRSCHandler<
|
|
|
421
558
|
url,
|
|
422
559
|
variables,
|
|
423
560
|
cacheStore,
|
|
561
|
+
searchParamsFilter,
|
|
562
|
+
explicitTaggedStores,
|
|
424
563
|
cacheProfiles: router.cacheProfiles,
|
|
425
564
|
executionContext: executionCtx,
|
|
426
565
|
themeConfig: router.themeConfig,
|
|
566
|
+
stateCookieName: router.resolvedStateCookieName,
|
|
567
|
+
version,
|
|
427
568
|
});
|
|
569
|
+
// Gate on the SAME enabled-semantics withTimeout uses (isTimeoutEnabled):
|
|
570
|
+
// a `renderStartMs: 0` / negative opt-out disables the timeout, so the
|
|
571
|
+
// driver's cursor bookkeeping (which only the timeout reads) must be off too.
|
|
572
|
+
requestContext._renderDiagnosticsEnabled = isTimeoutEnabled(
|
|
573
|
+
router.timeouts.renderStartMs,
|
|
574
|
+
);
|
|
575
|
+
// Thread the true request entry timestamp onto the context so a metrics
|
|
576
|
+
// store created MID-request (ctx.debugPerformance() / getMetricsStore) anchors
|
|
577
|
+
// to the real start, not the opt-in moment — phases that began earlier then
|
|
578
|
+
// report non-negative offsets. Set unconditionally: debug may be enabled later.
|
|
579
|
+
requestContext._handlerStart = handlerStart;
|
|
428
580
|
if (earlyMetricsStore) {
|
|
429
581
|
requestContext._debugPerformance = true;
|
|
430
582
|
requestContext._metricsStore = earlyMetricsStore;
|
|
@@ -433,7 +585,7 @@ export function createRSCHandler<
|
|
|
433
585
|
// can surface non-fatal errors through the router's onError callback.
|
|
434
586
|
requestContext._reportBackgroundError = (
|
|
435
587
|
error: unknown,
|
|
436
|
-
category:
|
|
588
|
+
category: CacheErrorCategory,
|
|
437
589
|
) => {
|
|
438
590
|
callOnError(error, "cache", {
|
|
439
591
|
request,
|
|
@@ -465,82 +617,206 @@ export function createRSCHandler<
|
|
|
465
617
|
// - Streaming
|
|
466
618
|
// Store basename on request context (scoped per-request via existing ALS)
|
|
467
619
|
requestContext._basename = router.basename;
|
|
620
|
+
requestContext._routerId = router.id;
|
|
621
|
+
|
|
622
|
+
// Resolved span tracing for this request (read at each traced phase).
|
|
623
|
+
requestContext._tracing = router.tracing;
|
|
624
|
+
|
|
625
|
+
// The "rango.request" span is opened inside the request context so the
|
|
626
|
+
// Cloudflare runner can read executionContext.tracing, and so every nested
|
|
627
|
+
// phase span (and the platform's automatic KV/D1/fetch spans) nests under
|
|
628
|
+
// it. Construction-bound: the span ends when the Response is built, never
|
|
629
|
+
// wrapping the streamed body. metric:false — handler:total is metered
|
|
630
|
+
// directly below (a grand total incl. the pre-context bootstrap timings).
|
|
631
|
+
// When tracing is off this is a direct pass-through.
|
|
632
|
+
return runWithRequestContext(requestContext, () =>
|
|
633
|
+
observePhase(PHASES.request, async (span) => {
|
|
634
|
+
span.setAttribute("http.method", request.method);
|
|
635
|
+
// The matched route template is not known until match() runs later, so
|
|
636
|
+
// emit the concrete path as url.path (low-level), NOT http.route — the
|
|
637
|
+
// latter is reserved for the low-cardinality template (OTel convention).
|
|
638
|
+
span.setAttribute("url.path", url.pathname);
|
|
639
|
+
|
|
640
|
+
// Core handler logic (wrapped by middleware)
|
|
641
|
+
const coreHandler = async (): Promise<Response> => {
|
|
642
|
+
return coreRequestHandler(request, env, url, variables, nonce);
|
|
643
|
+
};
|
|
468
644
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
645
|
+
// Execute middleware chain if any, otherwise call core handler
|
|
646
|
+
// directly; the response is finalized below, inside the response span.
|
|
647
|
+
const hasMiddleware = matchedMiddleware.length > 0;
|
|
648
|
+
const downstream = hasMiddleware
|
|
649
|
+
? await executeMiddleware(
|
|
650
|
+
matchedMiddleware,
|
|
651
|
+
request,
|
|
652
|
+
env,
|
|
653
|
+
variables,
|
|
654
|
+
coreHandler,
|
|
655
|
+
createReverseFunction(getRequiredRouteMap()),
|
|
656
|
+
)
|
|
657
|
+
: await coreHandler();
|
|
658
|
+
|
|
659
|
+
// Final response construction + host handoff, wrapped in rango.response
|
|
660
|
+
// — the explicit stream-handoff marker. The callback is synchronous, so
|
|
661
|
+
// the span ends immediately before the handler returns the response to
|
|
662
|
+
// the host; it never reads or wraps response.body. A downstream throw
|
|
663
|
+
// skips it entirely (no response exists to hand off).
|
|
664
|
+
return observePhase(PHASES.response, (responseSpan) => {
|
|
665
|
+
let response: Response;
|
|
666
|
+
if (hasMiddleware) {
|
|
667
|
+
if (
|
|
668
|
+
url.searchParams.has("_rsc_partial") ||
|
|
669
|
+
url.searchParams.has("_rsc_action")
|
|
670
|
+
) {
|
|
671
|
+
const intercepted = interceptRedirectForPartial(
|
|
672
|
+
downstream,
|
|
673
|
+
createRedirectFlightResponse,
|
|
674
|
+
{ requestOrigin: url.origin, basename: router.basename },
|
|
675
|
+
);
|
|
676
|
+
response = intercepted ?? finalizeResponse(downstream);
|
|
677
|
+
} else {
|
|
678
|
+
response = finalizeResponse(downstream);
|
|
679
|
+
}
|
|
680
|
+
} else {
|
|
681
|
+
response = downstream;
|
|
682
|
+
}
|
|
474
683
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
684
|
+
// Finalize metrics after all middleware (including post-next work)
|
|
685
|
+
// has completed so :post spans are captured in the timeline.
|
|
686
|
+
// Handler timing parts are always emitted (even without debug metrics)
|
|
687
|
+
// so non-debug requests still get bootstrap Server-Timing entries.
|
|
688
|
+
const handlerTimingArr: string[] = variables.__handlerTiming || [];
|
|
689
|
+
// Preserve any existing Server-Timing set by response routes or middleware
|
|
690
|
+
const existingTiming = response.headers.get("Server-Timing");
|
|
691
|
+
const timingParts = existingTiming
|
|
692
|
+
? [existingTiming, ...handlerTimingArr]
|
|
693
|
+
: [...handlerTimingArr];
|
|
694
|
+
|
|
695
|
+
const metricsStore = requestContext._metricsStore;
|
|
696
|
+
if (metricsStore) {
|
|
697
|
+
// When the store was created at handler start (earlyMetricsStore),
|
|
698
|
+
// handler:total covers the full request. When ctx.debugPerformance()
|
|
699
|
+
// created the store mid-request its requestStart is now the threaded
|
|
700
|
+
// _handlerStart (== handlerStart), so both branches yield the true
|
|
701
|
+
// request entry; reading the store's own anchor keeps this correct even
|
|
702
|
+
// if a store ever lands without the threading (falls back to its start).
|
|
703
|
+
const totalStart = earlyMetricsStore
|
|
704
|
+
? handlerStart
|
|
705
|
+
: metricsStore.requestStart;
|
|
706
|
+
appendMetric(
|
|
707
|
+
metricsStore,
|
|
708
|
+
"handler:total",
|
|
709
|
+
totalStart,
|
|
710
|
+
performance.now() - totalStart,
|
|
711
|
+
);
|
|
712
|
+
const metricsTiming = buildMetricsTiming(
|
|
713
|
+
request.method,
|
|
714
|
+
url.pathname,
|
|
715
|
+
metricsStore,
|
|
716
|
+
);
|
|
717
|
+
if (metricsTiming) timingParts.push(metricsTiming);
|
|
718
|
+
}
|
|
486
719
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
response = finalizeResponse(mwResponse);
|
|
498
|
-
}
|
|
499
|
-
} else {
|
|
500
|
-
response = await coreHandler();
|
|
501
|
-
}
|
|
720
|
+
const fullTiming = timingParts.join(", ");
|
|
721
|
+
if (fullTiming && !isWebSocketUpgradeResponse(response)) {
|
|
722
|
+
try {
|
|
723
|
+
response.headers.set("Server-Timing", fullTiming);
|
|
724
|
+
} catch {
|
|
725
|
+
// Immutable headers (e.g. a passed-through platform Response) — drop
|
|
726
|
+
// the timing header, never the response. Instrumentation must not
|
|
727
|
+
// 500 a request.
|
|
728
|
+
}
|
|
729
|
+
}
|
|
502
730
|
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
const metricsStore = requestContext._metricsStore;
|
|
515
|
-
if (metricsStore) {
|
|
516
|
-
// When the store was created at handler start (earlyMetricsStore),
|
|
517
|
-
// handler:total covers the full request. When ctx.debugPerformance()
|
|
518
|
-
// created the store mid-request, use its requestStart to avoid a
|
|
519
|
-
// negative startTime offset.
|
|
520
|
-
const totalStart = earlyMetricsStore
|
|
521
|
-
? handlerStart
|
|
522
|
-
: metricsStore.requestStart;
|
|
523
|
-
appendMetric(
|
|
524
|
-
metricsStore,
|
|
525
|
-
"handler:total",
|
|
526
|
-
totalStart,
|
|
527
|
-
performance.now() - totalStart,
|
|
528
|
-
);
|
|
529
|
-
const metricsTiming = buildMetricsTiming(
|
|
530
|
-
request.method,
|
|
531
|
-
url.pathname,
|
|
532
|
-
metricsStore,
|
|
533
|
-
);
|
|
534
|
-
if (metricsTiming) timingParts.push(metricsTiming);
|
|
535
|
-
}
|
|
731
|
+
// Single open-redirect chokepoint: every response (PE, full-page,
|
|
732
|
+
// middleware short-circuit, response-route) funnels through here, so
|
|
733
|
+
// guarding browser-followed (3xx) redirects once covers them all and any
|
|
734
|
+
// future redirect exit. Soft SPA/Flight redirects are 200/204 and pass
|
|
735
|
+
// through untouched (validated client-side instead).
|
|
736
|
+
const guarded = guardOutgoingRedirect(
|
|
737
|
+
response,
|
|
738
|
+
url.origin,
|
|
739
|
+
router.basename,
|
|
740
|
+
);
|
|
536
741
|
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
742
|
+
// Stream-idle watchdog (opt-in via timeouts.streamIdleMs): bounds
|
|
743
|
+
// end-to-end idle flow on the streamed body — see rsc/stream-idle.ts
|
|
744
|
+
// for the semantics. Applied at this finalization chokepoint so every
|
|
745
|
+
// streaming exit is covered; websocket upgrades must never be
|
|
746
|
+
// reconstructed and bodiless responses have nothing to bound. The
|
|
747
|
+
// trip fires POST-handoff (the request ALS may be gone), so it
|
|
748
|
+
// reports via the eagerly captured surfaces — callOnError +
|
|
749
|
+
// router.telemetry directly — mirroring handleStore.onError.
|
|
750
|
+
// onTimeout does NOT apply: the response already left the handler,
|
|
751
|
+
// so no replacement Response can be served mid-stream.
|
|
752
|
+
let finalResponse = guarded;
|
|
753
|
+
const streamIdleMs = router.timeouts.streamIdleMs;
|
|
754
|
+
// Websocket check FIRST: a workerd upgrade response must never have
|
|
755
|
+
// its body getter poked (same invariant as the body_kind attribute
|
|
756
|
+
// below).
|
|
757
|
+
if (
|
|
758
|
+
isTimeoutEnabled(streamIdleMs) &&
|
|
759
|
+
!isWebSocketUpgradeResponse(guarded) &&
|
|
760
|
+
guarded.body
|
|
761
|
+
) {
|
|
762
|
+
const routeKey = requestContext._routeName;
|
|
763
|
+
finalResponse = applyStreamIdleTimeout(
|
|
764
|
+
guarded,
|
|
765
|
+
streamIdleMs!,
|
|
766
|
+
(tripInfo) => {
|
|
767
|
+
callOnError(tripInfo.error, "handler", {
|
|
768
|
+
request,
|
|
769
|
+
url,
|
|
770
|
+
env,
|
|
771
|
+
routeKey,
|
|
772
|
+
handledByBoundary: false,
|
|
773
|
+
metadata: {
|
|
774
|
+
timeout: true,
|
|
775
|
+
phase: "stream-idle",
|
|
776
|
+
durationMs: tripInfo.totalMs,
|
|
777
|
+
},
|
|
778
|
+
});
|
|
779
|
+
if (router.telemetry) {
|
|
780
|
+
safeEmit(resolveSink(router.telemetry), {
|
|
781
|
+
type: "request.timeout",
|
|
782
|
+
timestamp: performance.now(),
|
|
783
|
+
requestId: getRequestId(request),
|
|
784
|
+
phase: "stream-idle",
|
|
785
|
+
pathname: url.pathname,
|
|
786
|
+
routeKey,
|
|
787
|
+
durationMs: tripInfo.totalMs,
|
|
788
|
+
customHandler: false,
|
|
789
|
+
});
|
|
790
|
+
}
|
|
791
|
+
},
|
|
792
|
+
);
|
|
793
|
+
}
|
|
541
794
|
|
|
542
|
-
|
|
543
|
-
|
|
795
|
+
// Attributes describe the response actually handed to the host (after
|
|
796
|
+
// unsafe-redirect replacement), low-cardinality only. body_kind checks
|
|
797
|
+
// the websocket marker before the body getter so a workerd upgrade
|
|
798
|
+
// Response is never poked; `.body` is a getter access, not a read of
|
|
799
|
+
// the stream.
|
|
800
|
+
responseSpan.setAttribute(
|
|
801
|
+
"http.response.status_code",
|
|
802
|
+
finalResponse.status,
|
|
803
|
+
);
|
|
804
|
+
responseSpan.setAttribute(
|
|
805
|
+
"rango.response.mode",
|
|
806
|
+
requestContext._requestMode ?? "middleware-short-circuit",
|
|
807
|
+
);
|
|
808
|
+
responseSpan.setAttribute(
|
|
809
|
+
"rango.response.body_kind",
|
|
810
|
+
isWebSocketUpgradeResponse(finalResponse)
|
|
811
|
+
? "websocket"
|
|
812
|
+
: finalResponse.body === null
|
|
813
|
+
? "empty"
|
|
814
|
+
: "stream",
|
|
815
|
+
);
|
|
816
|
+
return finalResponse;
|
|
817
|
+
});
|
|
818
|
+
}),
|
|
819
|
+
);
|
|
544
820
|
};
|
|
545
821
|
|
|
546
822
|
// Core request handling logic (separated for middleware wrapping).
|
|
@@ -555,35 +831,6 @@ export function createRSCHandler<
|
|
|
555
831
|
): Promise<Response> {
|
|
556
832
|
const handlerTiming: string[] = variables.__handlerTiming || [];
|
|
557
833
|
|
|
558
|
-
// Debug manifest endpoint: handled before classification since it
|
|
559
|
-
// doesn't need a route match and needs trie access from the closure.
|
|
560
|
-
const isDev = process.env.NODE_ENV !== "production";
|
|
561
|
-
if (
|
|
562
|
-
url.searchParams.has("__debug_manifest") &&
|
|
563
|
-
(isDev || router.allowDebugManifest)
|
|
564
|
-
) {
|
|
565
|
-
const trie = getRouterTrie(router.id) ?? getRouteTrie();
|
|
566
|
-
const routeManifest = getRequiredRouteMap();
|
|
567
|
-
const { extractAncestryFromTrie } =
|
|
568
|
-
await import("../build/route-trie.js");
|
|
569
|
-
return new Response(
|
|
570
|
-
JSON.stringify(
|
|
571
|
-
{
|
|
572
|
-
routerId: router.id,
|
|
573
|
-
routeManifest,
|
|
574
|
-
routeAncestry: trie ? extractAncestryFromTrie(trie) : {},
|
|
575
|
-
routeTrie: trie,
|
|
576
|
-
precomputedEntries: getPrecomputedEntries(),
|
|
577
|
-
},
|
|
578
|
-
null,
|
|
579
|
-
2,
|
|
580
|
-
),
|
|
581
|
-
{
|
|
582
|
-
headers: { "Content-Type": "application/json" },
|
|
583
|
-
},
|
|
584
|
-
);
|
|
585
|
-
}
|
|
586
|
-
|
|
587
834
|
// ---- 1. Classify ----
|
|
588
835
|
// classifyRequest may throw RouteNotFoundError for unknown routes.
|
|
589
836
|
// In that case, fall through to a full-render plan so the pipeline
|
|
@@ -597,10 +844,7 @@ export function createRSCHandler<
|
|
|
597
844
|
routerId: router.id,
|
|
598
845
|
});
|
|
599
846
|
} catch (error) {
|
|
600
|
-
if (
|
|
601
|
-
error instanceof RouteNotFoundError ||
|
|
602
|
-
(error instanceof Error && error.name === "RouteNotFoundError")
|
|
603
|
-
) {
|
|
847
|
+
if (isRouteNotFoundError(error)) {
|
|
604
848
|
// Let the render path handle 404 — match()/matchPartial() will
|
|
605
849
|
// re-throw RouteNotFoundError and the catch block in
|
|
606
850
|
// executeRenderWithMiddleware renders the not-found page.
|
|
@@ -626,6 +870,12 @@ export function createRSCHandler<
|
|
|
626
870
|
const classifyDur = performance.now() - classifyStart;
|
|
627
871
|
handlerTiming.push(`handler-classify;dur=${classifyDur.toFixed(2)}`);
|
|
628
872
|
|
|
873
|
+
// Stash the classified mode for the rango.response span (rango.response.mode)
|
|
874
|
+
// — the outer handler tail cannot see the plan. Stays unset when middleware
|
|
875
|
+
// short-circuits before core execution runs (reported as
|
|
876
|
+
// "middleware-short-circuit").
|
|
877
|
+
getRequestContext()._requestMode = plan.mode;
|
|
878
|
+
|
|
629
879
|
// ---- 2. Terminal plans (no execution needed) ----
|
|
630
880
|
if (plan.mode === "redirect") {
|
|
631
881
|
// Redirects are handled by the pipeline (match/matchPartial),
|
|
@@ -641,24 +891,18 @@ export function createRSCHandler<
|
|
|
641
891
|
console.log(
|
|
642
892
|
`[RSC] Version mismatch: client=${url.searchParams.get("_rsc_v")}, server=${version}. Forcing reload.`,
|
|
643
893
|
);
|
|
644
|
-
return
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
894
|
+
return createReloadResponse(plan.reloadUrl);
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
if (plan.mode === "app-switch") {
|
|
898
|
+
// Cross-app SPA navigation crossed a host-router app boundary. Force a
|
|
899
|
+
// real document navigation so the target app's document is re-established
|
|
900
|
+
// (stylesheets, theme, warmup, prefetch-TTL). See request-classification.
|
|
901
|
+
return createReloadResponse(plan.reloadUrl);
|
|
651
902
|
}
|
|
652
903
|
|
|
653
904
|
// ---- 3. Origin guard (gate for action/loader/PE modes) ----
|
|
654
|
-
const originPhase
|
|
655
|
-
plan.mode === "action"
|
|
656
|
-
? "action"
|
|
657
|
-
: plan.mode === "loader"
|
|
658
|
-
? "loader"
|
|
659
|
-
: plan.mode === "pe-render"
|
|
660
|
-
? "pe-form"
|
|
661
|
-
: null;
|
|
905
|
+
const originPhase = ORIGIN_CHECK_PHASE_BY_MODE[plan.mode];
|
|
662
906
|
if (originPhase) {
|
|
663
907
|
const originResult = await checkRequestOrigin(
|
|
664
908
|
request,
|
|
@@ -686,22 +930,17 @@ export function createRSCHandler<
|
|
|
686
930
|
},
|
|
687
931
|
});
|
|
688
932
|
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
host: request.headers.get("host"),
|
|
701
|
-
});
|
|
702
|
-
}
|
|
703
|
-
} catch {
|
|
704
|
-
// Router context may not be available
|
|
933
|
+
if (router.telemetry) {
|
|
934
|
+
safeEmit(resolveSink(router.telemetry), {
|
|
935
|
+
type: "request.origin-rejected",
|
|
936
|
+
timestamp: performance.now(),
|
|
937
|
+
requestId: getRequestId(request),
|
|
938
|
+
method: request.method,
|
|
939
|
+
pathname: url.pathname,
|
|
940
|
+
phase: originPhase,
|
|
941
|
+
origin: request.headers.get("origin"),
|
|
942
|
+
host: request.headers.get("host"),
|
|
943
|
+
});
|
|
705
944
|
}
|
|
706
945
|
|
|
707
946
|
return originResult;
|
|
@@ -732,11 +971,11 @@ export function createRSCHandler<
|
|
|
732
971
|
nonce: string | undefined,
|
|
733
972
|
): Promise<Response> {
|
|
734
973
|
// Common setup
|
|
735
|
-
const handleStore =
|
|
974
|
+
const handleStore = getRequestContext()._handleStore;
|
|
736
975
|
|
|
737
976
|
// Wire up error reporting for late streaming-handle failures
|
|
738
977
|
handleStore.onError = (error: Error) => {
|
|
739
|
-
const reqCtx =
|
|
978
|
+
const reqCtx = getRequestContext();
|
|
740
979
|
callOnError(error, "handler", {
|
|
741
980
|
request,
|
|
742
981
|
url,
|
|
@@ -744,22 +983,17 @@ export function createRSCHandler<
|
|
|
744
983
|
params: reqCtx.params as Record<string, string>,
|
|
745
984
|
handledByBoundary: true,
|
|
746
985
|
});
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
params: reqCtx.params as Record<string, string>,
|
|
759
|
-
});
|
|
760
|
-
}
|
|
761
|
-
} catch {
|
|
762
|
-
// Router context may not be available (e.g. prerender path)
|
|
986
|
+
if (router.telemetry) {
|
|
987
|
+
safeEmit(resolveSink(router.telemetry), {
|
|
988
|
+
type: "handler.error",
|
|
989
|
+
timestamp: performance.now(),
|
|
990
|
+
requestId: getRequestId(request),
|
|
991
|
+
error,
|
|
992
|
+
handledByBoundary: true,
|
|
993
|
+
pathname: url.pathname,
|
|
994
|
+
routeKey: reqCtx._routeName,
|
|
995
|
+
params: reqCtx.params as Record<string, string>,
|
|
996
|
+
});
|
|
763
997
|
}
|
|
764
998
|
};
|
|
765
999
|
|
|
@@ -768,7 +1002,7 @@ export function createRSCHandler<
|
|
|
768
1002
|
// instead of calling resolveRoute again.
|
|
769
1003
|
if (plan.mode !== "redirect") {
|
|
770
1004
|
setRequestContextParams(plan.route.params, plan.route.routeKey);
|
|
771
|
-
|
|
1005
|
+
getRequestContext()._classifiedRoute = plan.route;
|
|
772
1006
|
}
|
|
773
1007
|
|
|
774
1008
|
const routeReverse = createReverseFunction(getRequiredRouteMap());
|
|
@@ -809,7 +1043,9 @@ export function createRSCHandler<
|
|
|
809
1043
|
}
|
|
810
1044
|
const response = responseOutcome.result;
|
|
811
1045
|
if (plan.negotiated && !isWebSocketUpgradeResponse(response)) {
|
|
812
|
-
|
|
1046
|
+
// handleResponseRoute (callHandlerWithVary) already appends Vary: Accept
|
|
1047
|
+
// for negotiated responses; dedup so we don't emit Vary: Accept, Accept.
|
|
1048
|
+
appendVaryAccept(response);
|
|
813
1049
|
}
|
|
814
1050
|
return response;
|
|
815
1051
|
}
|
|
@@ -817,16 +1053,41 @@ export function createRSCHandler<
|
|
|
817
1053
|
// SSR setup: kick off in parallel for modes that need HTML rendering.
|
|
818
1054
|
// Placed after response-route short-circuit so response/mime routes
|
|
819
1055
|
// never pay for SSR work.
|
|
820
|
-
|
|
821
|
-
|
|
1056
|
+
//
|
|
1057
|
+
// Only kick off when the request will actually render HTML, so the
|
|
1058
|
+
// eager loadSSRModule() + user resolveStreaming() are not started (and
|
|
1059
|
+
// never consumed) for a request that returns an RSC stream — that wasted
|
|
1060
|
+
// work also leaves an orphaned Promise.all that can reject (D7). PE form
|
|
1061
|
+
// submissions always render HTML (handleProgressiveEnhancement renders via
|
|
1062
|
+
// getSSRSetup regardless of Accept). For full/partial-render and action,
|
|
1063
|
+
// the render-time HTML decision is exactly !isRscRequest — mayNeedSSR is
|
|
1064
|
+
// the coarse transport pre-filter, isRscRequest adds the partial/__rsc
|
|
1065
|
+
// flags; both share the same Accept rule (acceptsFlightExplicitly in
|
|
1066
|
+
// ssr-setup.ts), so the Accept call cannot drift between them. Both must
|
|
1067
|
+
// pass.
|
|
1068
|
+
const willRenderHtml =
|
|
1069
|
+
plan.mode === "pe-render" ||
|
|
1070
|
+
(mayNeedSSR(request, url) &&
|
|
1071
|
+
!isRscRequest(request, url, plan.mode === "partial-render"));
|
|
1072
|
+
if (plan.mode !== "loader" && willRenderHtml) {
|
|
1073
|
+
const ssrSetup = startSSRSetup(
|
|
822
1074
|
handlerCtx,
|
|
823
1075
|
request,
|
|
824
1076
|
env,
|
|
825
1077
|
url,
|
|
826
1078
|
router.debugPerformance
|
|
827
|
-
? () =>
|
|
1079
|
+
? () => getRequestContext()._metricsStore
|
|
828
1080
|
: undefined,
|
|
829
1081
|
);
|
|
1082
|
+
variables[SSR_SETUP_VAR] = ssrSetup;
|
|
1083
|
+
|
|
1084
|
+
// A handler can short-circuit before HTML rendering consumes this promise
|
|
1085
|
+
// (for example, by returning a redirect). Workerd cancels untracked dynamic
|
|
1086
|
+
// imports at the request boundary; retaining that cancelled promise in the
|
|
1087
|
+
// production SSR module memo makes every later document request hang.
|
|
1088
|
+
// Extending the request lifetime lets the shared setup settle without
|
|
1089
|
+
// delaying the short-circuit response.
|
|
1090
|
+
getRequestContext().executionContext?.waitUntil(ssrSetup);
|
|
830
1091
|
}
|
|
831
1092
|
|
|
832
1093
|
// ---- Loader fetch ----
|
|
@@ -865,14 +1126,20 @@ export function createRSCHandler<
|
|
|
865
1126
|
if (plan.mode === "action") {
|
|
866
1127
|
let actionContinuation: ActionContinuation | undefined;
|
|
867
1128
|
try {
|
|
1129
|
+
// Instrument the action execution as its own phase (action:<actionId> +
|
|
1130
|
+
// rango.action), so a POST shows the mutation time AND which action ran,
|
|
1131
|
+
// not just the downstream revalidation render. The action's own
|
|
1132
|
+
// loaders/fetches nest under rango.action.
|
|
868
1133
|
const actionOutcome = await withTimeout(
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
1134
|
+
observePhase(PHASES.action(plan.actionId), () =>
|
|
1135
|
+
executeServerAction(
|
|
1136
|
+
handlerCtx,
|
|
1137
|
+
request,
|
|
1138
|
+
env,
|
|
1139
|
+
url,
|
|
1140
|
+
plan.actionId,
|
|
1141
|
+
handleStore,
|
|
1142
|
+
),
|
|
876
1143
|
),
|
|
877
1144
|
router.timeouts.actionMs,
|
|
878
1145
|
"action",
|
|
@@ -925,47 +1192,17 @@ export function createRSCHandler<
|
|
|
925
1192
|
);
|
|
926
1193
|
}
|
|
927
1194
|
|
|
928
|
-
//
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
plan.
|
|
935
|
-
|
|
936
|
-
request,
|
|
937
|
-
env,
|
|
938
|
-
url,
|
|
939
|
-
variables,
|
|
940
|
-
nonce,
|
|
941
|
-
handleStore,
|
|
942
|
-
isPartial,
|
|
943
|
-
);
|
|
944
|
-
}
|
|
945
|
-
|
|
946
|
-
// PE that fell through (handleProgressiveEnhancement returned null)
|
|
947
|
-
// falls back to full render
|
|
948
|
-
if (plan.mode === "pe-render") {
|
|
949
|
-
return executeRenderWithMiddleware(
|
|
950
|
-
plan.route.routeMiddleware,
|
|
951
|
-
false,
|
|
952
|
-
plan.route.routeKey,
|
|
953
|
-
routeReverse,
|
|
954
|
-
request,
|
|
955
|
-
env,
|
|
956
|
-
url,
|
|
957
|
-
variables,
|
|
958
|
-
nonce,
|
|
959
|
-
handleStore,
|
|
960
|
-
false,
|
|
961
|
-
);
|
|
962
|
-
}
|
|
963
|
-
|
|
964
|
-
// Redirect plan that wasn't handled above (full-page redirect — let
|
|
965
|
-
// the pipeline handle it via match() which returns { redirect: url })
|
|
1195
|
+
// Full render, partial render, fallen-through PE, and full-page redirect all
|
|
1196
|
+
// render through the same middleware-wrapped path. Only full/partial-render
|
|
1197
|
+
// carry negotiation + the partial flag; pe/redirect render plainly.
|
|
1198
|
+
const isPartial = plan.mode === "partial-render";
|
|
1199
|
+
const negotiated =
|
|
1200
|
+
plan.mode === "full-render" || plan.mode === "partial-render"
|
|
1201
|
+
? plan.negotiated
|
|
1202
|
+
: false;
|
|
966
1203
|
return executeRenderWithMiddleware(
|
|
967
1204
|
plan.route.routeMiddleware,
|
|
968
|
-
|
|
1205
|
+
negotiated,
|
|
969
1206
|
plan.route.routeKey,
|
|
970
1207
|
routeReverse,
|
|
971
1208
|
request,
|
|
@@ -974,7 +1211,7 @@ export function createRSCHandler<
|
|
|
974
1211
|
variables,
|
|
975
1212
|
nonce,
|
|
976
1213
|
handleStore,
|
|
977
|
-
|
|
1214
|
+
isPartial,
|
|
978
1215
|
);
|
|
979
1216
|
}
|
|
980
1217
|
|
|
@@ -991,7 +1228,7 @@ export function createRSCHandler<
|
|
|
991
1228
|
url: URL,
|
|
992
1229
|
variables: Record<string, any>,
|
|
993
1230
|
nonce: string | undefined,
|
|
994
|
-
handleStore: ReturnType<typeof
|
|
1231
|
+
handleStore: ReturnType<typeof getRequestContext>["_handleStore"],
|
|
995
1232
|
isPartial: boolean,
|
|
996
1233
|
actionContinuation?: ActionContinuation,
|
|
997
1234
|
): Promise<Response> {
|
|
@@ -1019,16 +1256,27 @@ export function createRSCHandler<
|
|
|
1019
1256
|
);
|
|
1020
1257
|
}
|
|
1021
1258
|
if (negotiated && !isWebSocketUpgradeResponse(response)) {
|
|
1022
|
-
response
|
|
1259
|
+
// handleRscRendering bakes `accept` into the RSC response's Vary list;
|
|
1260
|
+
// dedup so the negotiated append does not list accept twice.
|
|
1261
|
+
appendVaryAccept(response);
|
|
1023
1262
|
}
|
|
1024
1263
|
return response;
|
|
1025
1264
|
} catch (error) {
|
|
1026
1265
|
// Check if middleware/handler returned Response
|
|
1027
1266
|
if (error instanceof Response) {
|
|
1267
|
+
// An action revalidation render is delivered to the client over the
|
|
1268
|
+
// same Flight-parsing path as a partial navigation, so a Response
|
|
1269
|
+
// thrown during it must be converted exactly like a partial one
|
|
1270
|
+
// (raw 200 -> hard-nav hint, 3xx -> Flight redirect). Without this,
|
|
1271
|
+
// the no-middleware path returns the raw Response (the with-middleware
|
|
1272
|
+
// path is already covered by the isPartial || actionContinuation
|
|
1273
|
+
// guard below).
|
|
1274
|
+
const treatAsPartial = isPartial || actionContinuation != null;
|
|
1275
|
+
|
|
1028
1276
|
// During partial (client-side navigation), a 200 Response from a handler
|
|
1029
1277
|
// means the route serves raw content (JSON, text, etc.), not JSX.
|
|
1030
1278
|
// Signal the browser to hard-navigate so it renders the raw response.
|
|
1031
|
-
if (
|
|
1279
|
+
if (treatAsPartial && error.status === 200) {
|
|
1032
1280
|
console.warn(
|
|
1033
1281
|
`[RSC] Route handler at ${url.pathname} returned a Response during client-side navigation. ` +
|
|
1034
1282
|
`Falling back to hard navigation. Use data-external on the <Link> to avoid the extra round-trip.`,
|
|
@@ -1042,10 +1290,11 @@ export function createRSCHandler<
|
|
|
1042
1290
|
});
|
|
1043
1291
|
}
|
|
1044
1292
|
|
|
1045
|
-
if (
|
|
1293
|
+
if (treatAsPartial) {
|
|
1046
1294
|
const intercepted = interceptRedirectForPartial(
|
|
1047
1295
|
error,
|
|
1048
1296
|
createRedirectFlightResponse,
|
|
1297
|
+
{ requestOrigin: url.origin, basename: router.basename },
|
|
1049
1298
|
);
|
|
1050
1299
|
if (intercepted) return intercepted;
|
|
1051
1300
|
}
|
|
@@ -1054,10 +1303,7 @@ export function createRSCHandler<
|
|
|
1054
1303
|
}
|
|
1055
1304
|
|
|
1056
1305
|
// Render 404 page for unmatched routes
|
|
1057
|
-
|
|
1058
|
-
error instanceof RouteNotFoundError ||
|
|
1059
|
-
(error instanceof Error && error.name === "RouteNotFoundError");
|
|
1060
|
-
if (isRouteNotFound) {
|
|
1306
|
+
if (isRouteNotFoundError(error)) {
|
|
1061
1307
|
callOnError(error, "routing", {
|
|
1062
1308
|
request,
|
|
1063
1309
|
url,
|
|
@@ -1065,11 +1311,12 @@ export function createRSCHandler<
|
|
|
1065
1311
|
handledByBoundary: true,
|
|
1066
1312
|
});
|
|
1067
1313
|
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1314
|
+
// No boundary to consult: an unmatched route has no entry chain, so
|
|
1315
|
+
// this always lands on the router option or the shared default.
|
|
1316
|
+
const notFoundComponent = resolveDefaultNotFound(
|
|
1317
|
+
router.notFound,
|
|
1318
|
+
url.pathname,
|
|
1319
|
+
);
|
|
1073
1320
|
|
|
1074
1321
|
const notFoundSegment = {
|
|
1075
1322
|
id: "notFound",
|
|
@@ -1088,51 +1335,81 @@ export function createRSCHandler<
|
|
|
1088
1335
|
segments: [notFoundSegment],
|
|
1089
1336
|
matched: [],
|
|
1090
1337
|
diff: [],
|
|
1338
|
+
// Shape parity with buildFullPayload (rsc-rendering.ts): the 404
|
|
1339
|
+
// payload carries params/resolvedIds/prefetchCacheTTL the same way a
|
|
1340
|
+
// matched full render does. resolvedIds mirrors the rendered segment
|
|
1341
|
+
// list (the single notFound segment) like the error-boundary path
|
|
1342
|
+
// (match-api.ts) does for its boundary segment.
|
|
1343
|
+
resolvedIds: [notFoundSegment.id],
|
|
1344
|
+
params: {},
|
|
1091
1345
|
isPartial: false,
|
|
1092
1346
|
rootLayout: router.rootLayout,
|
|
1093
|
-
|
|
1347
|
+
// Full (404) render: resolve deferred handle values server-side.
|
|
1348
|
+
handles: resolvedHandleStream(handleStore),
|
|
1094
1349
|
version,
|
|
1350
|
+
prefetchCacheTTL: router.prefetchCacheTTL,
|
|
1351
|
+
prefetchCacheSize: router.prefetchCacheSize,
|
|
1352
|
+
prefetchConcurrency: router.prefetchConcurrency,
|
|
1353
|
+
defaultPrefetch: router.defaultPrefetch,
|
|
1354
|
+
stateCookieName: router.resolvedStateCookieName,
|
|
1095
1355
|
themeConfig: router.themeConfig,
|
|
1096
1356
|
warmupEnabled: router.warmupEnabled,
|
|
1097
|
-
|
|
1357
|
+
strictMode: router.strictMode,
|
|
1358
|
+
initialTheme: getRequestContext().theme,
|
|
1098
1359
|
},
|
|
1099
1360
|
};
|
|
1100
1361
|
|
|
1101
|
-
const
|
|
1102
|
-
onError: (error: unknown) => {
|
|
1103
|
-
callOnError(error, "rendering", { request, url, env });
|
|
1104
|
-
},
|
|
1105
|
-
});
|
|
1106
|
-
|
|
1107
|
-
const isRscRequest =
|
|
1108
|
-
isPartial ||
|
|
1109
|
-
(!request.headers.get("accept")?.includes("text/html") &&
|
|
1110
|
-
!url.searchParams.has("__html")) ||
|
|
1111
|
-
url.searchParams.has("__rsc");
|
|
1112
|
-
|
|
1113
|
-
if (isRscRequest) {
|
|
1114
|
-
return createResponseWithMergedHeaders(rscStream, {
|
|
1115
|
-
status: 404,
|
|
1116
|
-
headers: { "content-type": "text/x-component;charset=utf-8" },
|
|
1117
|
-
});
|
|
1118
|
-
}
|
|
1119
|
-
|
|
1120
|
-
const [ssrModule, streamMode] = await getSSRSetup(
|
|
1121
|
-
handlerCtx,
|
|
1362
|
+
const isNotFoundFlightResponse = isRscRequest(
|
|
1122
1363
|
request,
|
|
1123
|
-
env,
|
|
1124
1364
|
url,
|
|
1125
|
-
|
|
1365
|
+
isPartial,
|
|
1366
|
+
);
|
|
1367
|
+
const notFoundStageTracking = {
|
|
1368
|
+
mode: isPartial ? ("partial" as const) : ("full" as const),
|
|
1369
|
+
routeKey,
|
|
1370
|
+
};
|
|
1371
|
+
return renderRscResponse(
|
|
1372
|
+
{
|
|
1373
|
+
ctx: handlerCtx,
|
|
1374
|
+
request,
|
|
1375
|
+
url,
|
|
1376
|
+
env,
|
|
1377
|
+
payload,
|
|
1378
|
+
// The 404 path historically records no rsc-serialize metric (it
|
|
1379
|
+
// used the standalone Flight constructor, whose gate was opt-in);
|
|
1380
|
+
// opt out explicitly since renderRscResponse defaults the gate on.
|
|
1381
|
+
recordSerializeMetric: false,
|
|
1382
|
+
init: isNotFoundFlightResponse
|
|
1383
|
+
? {
|
|
1384
|
+
status: 404,
|
|
1385
|
+
headers: {
|
|
1386
|
+
"content-type": "text/x-component;charset=utf-8",
|
|
1387
|
+
// Router identity for the client's pre-decode integrity
|
|
1388
|
+
// check; a same-app 404 applies in place.
|
|
1389
|
+
"X-RSC-Router-Id": router.id,
|
|
1390
|
+
},
|
|
1391
|
+
}
|
|
1392
|
+
: {
|
|
1393
|
+
status: 404,
|
|
1394
|
+
headers: {
|
|
1395
|
+
"content-type": "text/html;charset=utf-8",
|
|
1396
|
+
},
|
|
1397
|
+
},
|
|
1398
|
+
tracking: notFoundStageTracking,
|
|
1399
|
+
},
|
|
1400
|
+
isNotFoundFlightResponse
|
|
1401
|
+
? undefined
|
|
1402
|
+
: {
|
|
1403
|
+
html: createSsrHtmlStage({
|
|
1404
|
+
ctx: handlerCtx,
|
|
1405
|
+
request,
|
|
1406
|
+
env,
|
|
1407
|
+
url,
|
|
1408
|
+
metricsStore: getRequestContext()._metricsStore,
|
|
1409
|
+
render: { nonce },
|
|
1410
|
+
}),
|
|
1411
|
+
},
|
|
1126
1412
|
);
|
|
1127
|
-
const htmlStream = await ssrModule.renderHTML(rscStream, {
|
|
1128
|
-
nonce,
|
|
1129
|
-
streamMode,
|
|
1130
|
-
});
|
|
1131
|
-
|
|
1132
|
-
return createResponseWithMergedHeaders(htmlStream, {
|
|
1133
|
-
status: 404,
|
|
1134
|
-
headers: { "content-type": "text/html;charset=utf-8" },
|
|
1135
|
-
});
|
|
1136
1413
|
}
|
|
1137
1414
|
|
|
1138
1415
|
// Report unhandled errors
|
|
@@ -1163,6 +1440,7 @@ export function createRSCHandler<
|
|
|
1163
1440
|
const intercepted = interceptRedirectForPartial(
|
|
1164
1441
|
mwResponse,
|
|
1165
1442
|
createRedirectFlightResponse,
|
|
1443
|
+
{ requestOrigin: url.origin, basename: router.basename },
|
|
1166
1444
|
);
|
|
1167
1445
|
if (intercepted) return intercepted;
|
|
1168
1446
|
}
|