@rangojs/router 0.4.3 → 0.5.1
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/dist/types/browser/prefetch/cache.d.ts +31 -2
- package/dist/types/cache/cf/cf-cache-store.d.ts +2 -0
- package/dist/types/cache/types.d.ts +39 -6
- package/dist/types/route-definition/helpers-types.d.ts +5 -4
- package/dist/types/rsc/capture-queue.d.ts +19 -3
- package/dist/types/rsc/shell-build-manifest.d.ts +2 -2
- package/dist/types/rsc/shell-capture.d.ts +22 -2
- package/dist/types/rsc/shell-serve.d.ts +18 -12
- package/dist/types/static-handler.d.ts +15 -1
- package/dist/types/urls/path-helper-types.d.ts +6 -7
- package/dist/types.backup/__internal.d.ts +127 -0
- package/dist/types.backup/bin/rango.d.ts +1 -0
- package/dist/types.backup/browser/action-coordinator.d.ts +57 -0
- package/dist/types.backup/browser/action-fence.d.ts +33 -0
- package/dist/types.backup/browser/app-shell.d.ts +34 -0
- package/dist/types.backup/browser/app-version.d.ts +6 -0
- package/dist/types.backup/browser/connection-warmup.d.ts +31 -0
- package/dist/types.backup/browser/cookie-name.d.ts +66 -0
- package/dist/types.backup/browser/event-controller.d.ts +221 -0
- package/dist/types.backup/browser/history-state.d.ts +26 -0
- package/dist/types.backup/browser/index.d.ts +1 -0
- package/dist/types.backup/browser/intercept-utils.d.ts +30 -0
- package/dist/types.backup/browser/invalidate-client-cache.d.ts +17 -0
- package/dist/types.backup/browser/link-interceptor.d.ts +43 -0
- package/dist/types.backup/browser/logging.d.ts +33 -0
- package/dist/types.backup/browser/merge-segment-loaders.d.ts +38 -0
- package/dist/types.backup/browser/navigation-bridge.d.ts +27 -0
- package/dist/types.backup/browser/navigation-client.d.ts +17 -0
- package/dist/types.backup/browser/navigation-store-handle.d.ts +25 -0
- package/dist/types.backup/browser/navigation-store.d.ts +95 -0
- package/dist/types.backup/browser/navigation-transaction.d.ts +75 -0
- package/dist/types.backup/browser/network-error-handler.d.ts +35 -0
- package/dist/types.backup/browser/partial-update.d.ts +61 -0
- package/dist/types.backup/browser/prefetch/cache.d.ts +183 -0
- package/dist/types.backup/browser/prefetch/fetch.d.ts +52 -0
- package/dist/types.backup/browser/prefetch/observer.d.ts +27 -0
- package/dist/types.backup/browser/prefetch/policy.d.ts +13 -0
- package/dist/types.backup/browser/prefetch/queue.d.ts +48 -0
- package/dist/types.backup/browser/prefetch/resource-ready.d.ts +28 -0
- package/dist/types.backup/browser/rango-state.d.ts +52 -0
- package/dist/types.backup/browser/react/Link.d.ts +140 -0
- package/dist/types.backup/browser/react/NavigationProvider.d.ts +88 -0
- package/dist/types.backup/browser/react/ScrollRestoration.d.ts +78 -0
- package/dist/types.backup/browser/react/context.d.ts +54 -0
- package/dist/types.backup/browser/react/filter-segment-order.d.ts +35 -0
- package/dist/types.backup/browser/react/index.d.ts +1 -0
- package/dist/types.backup/browser/react/location-state-shared.d.ts +162 -0
- package/dist/types.backup/browser/react/location-state.d.ts +29 -0
- package/dist/types.backup/browser/react/mount-context.d.ts +23 -0
- package/dist/types.backup/browser/react/nonce-context.d.ts +14 -0
- package/dist/types.backup/browser/react/shallow-equal.d.ts +5 -0
- package/dist/types.backup/browser/react/use-action.d.ts +61 -0
- package/dist/types.backup/browser/react/use-handle.d.ts +21 -0
- package/dist/types.backup/browser/react/use-href.d.ts +32 -0
- package/dist/types.backup/browser/react/use-link-status.d.ts +36 -0
- package/dist/types.backup/browser/react/use-mount.d.ts +24 -0
- package/dist/types.backup/browser/react/use-navigation.d.ts +15 -0
- package/dist/types.backup/browser/react/use-params.d.ts +21 -0
- package/dist/types.backup/browser/react/use-pathname.d.ts +13 -0
- package/dist/types.backup/browser/react/use-reverse.d.ts +40 -0
- package/dist/types.backup/browser/react/use-router.d.ts +23 -0
- package/dist/types.backup/browser/react/use-search-params.d.ts +19 -0
- package/dist/types.backup/browser/react/use-segments.d.ts +29 -0
- package/dist/types.backup/browser/response-adapter.d.ts +58 -0
- package/dist/types.backup/browser/rsc-router.d.ts +141 -0
- package/dist/types.backup/browser/scroll-restoration.d.ts +103 -0
- package/dist/types.backup/browser/segment-reconciler.d.ts +74 -0
- package/dist/types.backup/browser/segment-structure-assert.d.ts +16 -0
- package/dist/types.backup/browser/server-action-bridge.d.ts +29 -0
- package/dist/types.backup/browser/types.d.ts +530 -0
- package/dist/types.backup/browser/validate-redirect-origin.d.ts +28 -0
- package/dist/types.backup/build/collect-fallback-refs.d.ts +5 -0
- package/dist/types.backup/build/generate-manifest.d.ts +100 -0
- package/dist/types.backup/build/generate-route-types.d.ts +8 -0
- package/dist/types.backup/build/index.d.ts +21 -0
- package/dist/types.backup/build/prefix-tree-utils.d.ts +56 -0
- package/dist/types.backup/build/route-trie.d.ts +89 -0
- package/dist/types.backup/build/route-types/ast-helpers.d.ts +3 -0
- package/dist/types.backup/build/route-types/ast-route-extraction.d.ts +13 -0
- package/dist/types.backup/build/route-types/codegen.d.ts +16 -0
- package/dist/types.backup/build/route-types/include-resolution.d.ts +74 -0
- package/dist/types.backup/build/route-types/param-extraction.d.ts +13 -0
- package/dist/types.backup/build/route-types/per-module-writer.d.ts +18 -0
- package/dist/types.backup/build/route-types/router-processing.d.ts +82 -0
- package/dist/types.backup/build/route-types/scan-filter.d.ts +17 -0
- package/dist/types.backup/build/route-types/source-scan.d.ts +13 -0
- package/dist/types.backup/build/runtime-discovery.d.ts +24 -0
- package/dist/types.backup/cache/background-task.d.ts +21 -0
- package/dist/types.backup/cache/cache-error.d.ts +71 -0
- package/dist/types.backup/cache/cache-key-utils.d.ts +35 -0
- package/dist/types.backup/cache/cache-policy.d.ts +59 -0
- package/dist/types.backup/cache/cache-runtime.d.ts +51 -0
- package/dist/types.backup/cache/cache-scope.d.ts +134 -0
- package/dist/types.backup/cache/cache-tag.d.ts +79 -0
- package/dist/types.backup/cache/cf/cf-base64.d.ts +4 -0
- package/dist/types.backup/cache/cf/cf-cache-constants.d.ts +105 -0
- package/dist/types.backup/cache/cf/cf-cache-store.d.ts +481 -0
- package/dist/types.backup/cache/cf/cf-cache-types.d.ts +300 -0
- package/dist/types.backup/cache/cf/cf-kv-utils.d.ts +22 -0
- package/dist/types.backup/cache/cf/cf-tag-marker-memo.d.ts +15 -0
- package/dist/types.backup/cache/cf/index.d.ts +3 -0
- package/dist/types.backup/cache/document-cache.d.ts +69 -0
- package/dist/types.backup/cache/handle-capture.d.ts +23 -0
- package/dist/types.backup/cache/handle-snapshot.d.ts +39 -0
- package/dist/types.backup/cache/index.d.ts +7 -0
- package/dist/types.backup/cache/memory-segment-store.d.ts +163 -0
- package/dist/types.backup/cache/profile-registry.d.ts +40 -0
- package/dist/types.backup/cache/read-through-swr.d.ts +60 -0
- package/dist/types.backup/cache/segment-codec.d.ts +78 -0
- package/dist/types.backup/cache/shell-snapshot.d.ts +162 -0
- package/dist/types.backup/cache/tag-invalidation.d.ts +74 -0
- package/dist/types.backup/cache/taint.d.ts +71 -0
- package/dist/types.backup/cache/types.d.ts +407 -0
- package/dist/types.backup/cache/vercel/index.d.ts +1 -0
- package/dist/types.backup/cache/vercel/vercel-cache-store.d.ts +267 -0
- package/dist/types.backup/client.d.ts +184 -0
- package/dist/types.backup/client.rsc.d.ts +39 -0
- package/dist/types.backup/cloudflare/index.d.ts +7 -0
- package/dist/types.backup/cloudflare/tracing.d.ts +53 -0
- package/dist/types.backup/component-utils.d.ts +46 -0
- package/dist/types.backup/components/DefaultDocument.d.ts +13 -0
- package/dist/types.backup/context-var.d.ts +84 -0
- package/dist/types.backup/debug.d.ts +57 -0
- package/dist/types.backup/decode-loader-results.d.ts +5 -0
- package/dist/types.backup/default-error-boundary.d.ts +10 -0
- package/dist/types.backup/defer.d.ts +89 -0
- package/dist/types.backup/deps/browser.d.ts +1 -0
- package/dist/types.backup/deps/html-stream-client.d.ts +1 -0
- package/dist/types.backup/deps/html-stream-server.d.ts +1 -0
- package/dist/types.backup/deps/rsc.d.ts +1 -0
- package/dist/types.backup/deps/ssr.d.ts +1 -0
- package/dist/types.backup/encode-kv.d.ts +35 -0
- package/dist/types.backup/errors.d.ts +226 -0
- package/dist/types.backup/escape-script.d.ts +44 -0
- package/dist/types.backup/handle.d.ts +93 -0
- package/dist/types.backup/handles/MetaTags.d.ts +17 -0
- package/dist/types.backup/handles/Scripts.d.ts +38 -0
- package/dist/types.backup/handles/breadcrumbs.d.ts +43 -0
- package/dist/types.backup/handles/deferred-resolution.d.ts +53 -0
- package/dist/types.backup/handles/is-thenable.d.ts +12 -0
- package/dist/types.backup/handles/meta.d.ts +43 -0
- package/dist/types.backup/handles/script.d.ts +139 -0
- package/dist/types.backup/host/cookie-handler.d.ts +8 -0
- package/dist/types.backup/host/errors.d.ts +40 -0
- package/dist/types.backup/host/index.d.ts +33 -0
- package/dist/types.backup/host/pattern-matcher.d.ts +30 -0
- package/dist/types.backup/host/router.d.ts +12 -0
- package/dist/types.backup/host/testing.d.ts +41 -0
- package/dist/types.backup/host/types.d.ts +148 -0
- package/dist/types.backup/host/utils.d.ts +20 -0
- package/dist/types.backup/href-client.d.ts +214 -0
- package/dist/types.backup/index.d.ts +112 -0
- package/dist/types.backup/index.rsc.d.ts +51 -0
- package/dist/types.backup/internal-debug.d.ts +1 -0
- package/dist/types.backup/loader-store.d.ts +193 -0
- package/dist/types.backup/loader.d.ts +18 -0
- package/dist/types.backup/loader.rsc.d.ts +18 -0
- package/dist/types.backup/missing-id-error.d.ts +1 -0
- package/dist/types.backup/outlet-context.d.ts +12 -0
- package/dist/types.backup/outlet-provider.d.ts +12 -0
- package/dist/types.backup/prerender/build-shell-capture.d.ts +104 -0
- package/dist/types.backup/prerender/param-hash.d.ts +6 -0
- package/dist/types.backup/prerender/shell-manifest-key.d.ts +18 -0
- package/dist/types.backup/prerender/store.d.ts +62 -0
- package/dist/types.backup/prerender.d.ts +292 -0
- package/dist/types.backup/redirect-origin.d.ts +55 -0
- package/dist/types.backup/regex-escape.d.ts +6 -0
- package/dist/types.backup/render-error-thrower.d.ts +13 -0
- package/dist/types.backup/response-utils.d.ts +35 -0
- package/dist/types.backup/reverse.d.ts +206 -0
- package/dist/types.backup/root-error-boundary.d.ts +32 -0
- package/dist/types.backup/route-content-wrapper.d.ts +40 -0
- package/dist/types.backup/route-definition/dsl-helpers.d.ts +130 -0
- package/dist/types.backup/route-definition/helper-factories.d.ts +22 -0
- package/dist/types.backup/route-definition/helpers-types.d.ts +392 -0
- package/dist/types.backup/route-definition/index.d.ts +7 -0
- package/dist/types.backup/route-definition/redirect.d.ts +48 -0
- package/dist/types.backup/route-definition/resolve-handler-use.d.ts +19 -0
- package/dist/types.backup/route-definition/use-item-types.d.ts +1 -0
- package/dist/types.backup/route-definition.d.ts +1 -0
- package/dist/types.backup/route-map-builder.d.ts +127 -0
- package/dist/types.backup/route-name.d.ts +27 -0
- package/dist/types.backup/route-types.d.ts +172 -0
- package/dist/types.backup/router/basename.d.ts +10 -0
- package/dist/types.backup/router/content-negotiation.d.ts +91 -0
- package/dist/types.backup/router/debug-manifest.d.ts +7 -0
- package/dist/types.backup/router/error-handling.d.ts +76 -0
- package/dist/types.backup/router/find-match.d.ts +19 -0
- package/dist/types.backup/router/handler-context.d.ts +41 -0
- package/dist/types.backup/router/instrument.d.ts +161 -0
- package/dist/types.backup/router/intercept-resolution.d.ts +79 -0
- package/dist/types.backup/router/lazy-includes.d.ts +26 -0
- package/dist/types.backup/router/loader-resolution.d.ts +63 -0
- package/dist/types.backup/router/logging.d.ts +41 -0
- package/dist/types.backup/router/manifest.d.ts +8 -0
- package/dist/types.backup/router/match-api.d.ts +19 -0
- package/dist/types.backup/router/match-context.d.ts +184 -0
- package/dist/types.backup/router/match-handlers.d.ts +49 -0
- package/dist/types.backup/router/match-middleware/background-revalidation.d.ts +113 -0
- package/dist/types.backup/router/match-middleware/cache-lookup.d.ts +113 -0
- package/dist/types.backup/router/match-middleware/cache-store.d.ts +112 -0
- package/dist/types.backup/router/match-middleware/index.d.ts +80 -0
- package/dist/types.backup/router/match-middleware/intercept-resolution.d.ts +116 -0
- package/dist/types.backup/router/match-middleware/segment-resolution.d.ts +94 -0
- package/dist/types.backup/router/match-pipelines.d.ts +103 -0
- package/dist/types.backup/router/match-result.d.ts +114 -0
- package/dist/types.backup/router/metrics.d.ts +6 -0
- package/dist/types.backup/router/middleware-types.d.ts +74 -0
- package/dist/types.backup/router/middleware.d.ts +116 -0
- package/dist/types.backup/router/navigation-snapshot.d.ts +22 -0
- package/dist/types.backup/router/params-util.d.ts +8 -0
- package/dist/types.backup/router/parse-pattern.d.ts +38 -0
- package/dist/types.backup/router/pattern-matching.d.ts +169 -0
- package/dist/types.backup/router/prefetch-cache-ttl.d.ts +27 -0
- package/dist/types.backup/router/prefetch-limits.d.ts +20 -0
- package/dist/types.backup/router/prerender-match.d.ts +50 -0
- package/dist/types.backup/router/preview-match.d.ts +22 -0
- package/dist/types.backup/router/request-classification.d.ts +104 -0
- package/dist/types.backup/router/revalidation.d.ts +57 -0
- package/dist/types.backup/router/route-snapshot.d.ts +112 -0
- package/dist/types.backup/router/router-context.d.ts +137 -0
- package/dist/types.backup/router/router-interfaces.d.ts +432 -0
- package/dist/types.backup/router/router-options.d.ts +738 -0
- package/dist/types.backup/router/router-registry.d.ts +15 -0
- package/dist/types.backup/router/segment-resolution/fresh.d.ts +55 -0
- package/dist/types.backup/router/segment-resolution/helpers.d.ts +93 -0
- package/dist/types.backup/router/segment-resolution/loader-cache.d.ts +33 -0
- package/dist/types.backup/router/segment-resolution/loader-mask.d.ts +44 -0
- package/dist/types.backup/router/segment-resolution/loader-snapshot.d.ts +90 -0
- package/dist/types.backup/router/segment-resolution/mask-nested.d.ts +53 -0
- package/dist/types.backup/router/segment-resolution/revalidation.d.ts +85 -0
- package/dist/types.backup/router/segment-resolution/static-store.d.ts +17 -0
- package/dist/types.backup/router/segment-resolution/streamed-handler-telemetry.d.ts +16 -0
- package/dist/types.backup/router/segment-resolution/view-transition-default.d.ts +28 -0
- package/dist/types.backup/router/segment-resolution.d.ts +3 -0
- package/dist/types.backup/router/segment-wrappers.d.ts +53 -0
- package/dist/types.backup/router/state-cookie-name.d.ts +1 -0
- package/dist/types.backup/router/substitute-pattern-params.d.ts +23 -0
- package/dist/types.backup/router/telemetry-otel.d.ts +113 -0
- package/dist/types.backup/router/telemetry.d.ts +215 -0
- package/dist/types.backup/router/timeout.d.ts +68 -0
- package/dist/types.backup/router/tracing.d.ts +125 -0
- package/dist/types.backup/router/trie-matching.d.ts +32 -0
- package/dist/types.backup/router/types.d.ts +98 -0
- package/dist/types.backup/router/url-params.d.ts +26 -0
- package/dist/types.backup/router.d.ts +7 -0
- package/dist/types.backup/rsc/capture-queue.d.ts +6 -0
- package/dist/types.backup/rsc/full-payload.d.ts +22 -0
- package/dist/types.backup/rsc/handler-context.d.ts +31 -0
- package/dist/types.backup/rsc/handler.d.ts +9 -0
- package/dist/types.backup/rsc/helpers.d.ts +213 -0
- package/dist/types.backup/rsc/index.d.ts +17 -0
- package/dist/types.backup/rsc/json-route-result.d.ts +20 -0
- package/dist/types.backup/rsc/loader-fetch.d.ts +14 -0
- package/dist/types.backup/rsc/manifest-init.d.ts +18 -0
- package/dist/types.backup/rsc/nonce.d.ts +28 -0
- package/dist/types.backup/rsc/origin-guard.d.ts +50 -0
- package/dist/types.backup/rsc/progressive-enhancement.d.ts +19 -0
- package/dist/types.backup/rsc/redirect-guard.d.ts +35 -0
- package/dist/types.backup/rsc/response-cache-serve.d.ts +46 -0
- package/dist/types.backup/rsc/response-error.d.ts +19 -0
- package/dist/types.backup/rsc/response-route-handler.d.ts +29 -0
- package/dist/types.backup/rsc/rsc-rendering.d.ts +23 -0
- package/dist/types.backup/rsc/runtime-warnings.d.ts +22 -0
- package/dist/types.backup/rsc/server-action.d.ts +68 -0
- package/dist/types.backup/rsc/shell-build-manifest.d.ts +84 -0
- package/dist/types.backup/rsc/shell-capture-constants.d.ts +27 -0
- package/dist/types.backup/rsc/shell-capture.d.ts +374 -0
- package/dist/types.backup/rsc/shell-serve.d.ts +136 -0
- package/dist/types.backup/rsc/ssr-setup.d.ts +48 -0
- package/dist/types.backup/rsc/transition-gate.d.ts +27 -0
- package/dist/types.backup/rsc/types.d.ts +290 -0
- package/dist/types.backup/runtime-env.d.ts +1 -0
- package/dist/types.backup/search-params.d.ts +125 -0
- package/dist/types.backup/segment-content-promise.d.ts +13 -0
- package/dist/types.backup/segment-fragments.d.ts +56 -0
- package/dist/types.backup/segment-loader-promise.d.ts +22 -0
- package/dist/types.backup/segment-system.d.ts +84 -0
- package/dist/types.backup/serialize.d.ts +164 -0
- package/dist/types.backup/server/context.d.ts +494 -0
- package/dist/types.backup/server/cookie-parse.d.ts +10 -0
- package/dist/types.backup/server/cookie-store.d.ts +107 -0
- package/dist/types.backup/server/fetchable-loader-store.d.ts +20 -0
- package/dist/types.backup/server/handle-store.d.ts +100 -0
- package/dist/types.backup/server/loader-registry.d.ts +32 -0
- package/dist/types.backup/server/request-context.d.ts +596 -0
- package/dist/types.backup/server/root-layout.d.ts +3 -0
- package/dist/types.backup/server.d.ts +15 -0
- package/dist/types.backup/ssr/index.d.ts +233 -0
- package/dist/types.backup/ssr/inject-rsc-eager.d.ts +3 -0
- package/dist/types.backup/ssr/preinit-client-references.d.ts +71 -0
- package/dist/types.backup/ssr/ssr-root.d.ts +69 -0
- package/dist/types.backup/static-handler.d.ts +57 -0
- package/dist/types.backup/testing/cache-status.d.ts +63 -0
- package/dist/types.backup/testing/collect-handle.d.ts +20 -0
- package/dist/types.backup/testing/dispatch.d.ts +123 -0
- package/dist/types.backup/testing/dom.entry.d.ts +15 -0
- package/dist/types.backup/testing/e2e/fixture.d.ts +37 -0
- package/dist/types.backup/testing/e2e/index.d.ts +30 -0
- package/dist/types.backup/testing/e2e/matchers.d.ts +17 -0
- package/dist/types.backup/testing/e2e/page-helpers.d.ts +62 -0
- package/dist/types.backup/testing/e2e/parity.d.ts +111 -0
- package/dist/types.backup/testing/e2e/server.d.ts +35 -0
- package/dist/types.backup/testing/flight-matchers.d.ts +55 -0
- package/dist/types.backup/testing/flight-normalize.d.ts +1 -0
- package/dist/types.backup/testing/flight-tree.d.ts +192 -0
- package/dist/types.backup/testing/flight.d.ts +115 -0
- package/dist/types.backup/testing/flight.entry.d.ts +27 -0
- package/dist/types.backup/testing/generated-routes.d.ts +66 -0
- package/dist/types.backup/testing/index.d.ts +52 -0
- package/dist/types.backup/testing/internal/context.d.ts +225 -0
- package/dist/types.backup/testing/internal/flight-client-globals.d.ts +1 -0
- package/dist/types.backup/testing/internal/seed-vars.d.ts +30 -0
- package/dist/types.backup/testing/render-handler.d.ts +160 -0
- package/dist/types.backup/testing/render-route.d.ts +246 -0
- package/dist/types.backup/testing/run-loader.d.ts +186 -0
- package/dist/types.backup/testing/run-middleware.d.ts +132 -0
- package/dist/types.backup/testing/run-transition-when.d.ts +77 -0
- package/dist/types.backup/testing/vitest-stubs/cloudflare-email.d.ts +6 -0
- package/dist/types.backup/testing/vitest-stubs/cloudflare-workers.d.ts +13 -0
- package/dist/types.backup/testing/vitest-stubs/plugin-rsc.d.ts +7 -0
- package/dist/types.backup/testing/vitest-stubs/version.d.ts +1 -0
- package/dist/types.backup/testing/vitest.d.ts +205 -0
- package/dist/types.backup/theme/ThemeProvider.d.ts +13 -0
- package/dist/types.backup/theme/ThemeScript.d.ts +45 -0
- package/dist/types.backup/theme/constants.d.ts +39 -0
- package/dist/types.backup/theme/index.d.ts +29 -0
- package/dist/types.backup/theme/theme-context.d.ts +21 -0
- package/dist/types.backup/theme/theme-script.d.ts +26 -0
- package/dist/types.backup/theme/types.d.ts +162 -0
- package/dist/types.backup/theme/use-theme.d.ts +8 -0
- package/dist/types.backup/types/boundaries.d.ts +93 -0
- package/dist/types.backup/types/cache-types.d.ts +191 -0
- package/dist/types.backup/types/error-types.d.ts +114 -0
- package/dist/types.backup/types/global-namespace.d.ts +90 -0
- package/dist/types.backup/types/handler-context.d.ts +658 -0
- package/dist/types.backup/types/index.d.ts +11 -0
- package/dist/types.backup/types/loader-types.d.ts +182 -0
- package/dist/types.backup/types/request-scope.d.ts +93 -0
- package/dist/types.backup/types/route-config.d.ts +105 -0
- package/dist/types.backup/types/route-entry.d.ts +95 -0
- package/dist/types.backup/types/segments.d.ts +234 -0
- package/dist/types.backup/types.d.ts +1 -0
- package/dist/types.backup/urls/include-helper.d.ts +17 -0
- package/dist/types.backup/urls/include-provider.d.ts +27 -0
- package/dist/types.backup/urls/index.d.ts +6 -0
- package/dist/types.backup/urls/path-helper-types.d.ts +197 -0
- package/dist/types.backup/urls/path-helper.d.ts +12 -0
- package/dist/types.backup/urls/pattern-types.d.ts +166 -0
- package/dist/types.backup/urls/response-types.d.ts +67 -0
- package/dist/types.backup/urls/type-extraction.d.ts +157 -0
- package/dist/types.backup/urls/urls-function.d.ts +24 -0
- package/dist/types.backup/urls.d.ts +1 -0
- package/dist/types.backup/use-loader.d.ts +150 -0
- package/dist/types.backup/vercel/index.d.ts +10 -0
- package/dist/types.backup/vercel/tracing.d.ts +70 -0
- package/dist/types.backup/vite/debug.d.ts +80 -0
- package/dist/types.backup/vite/discovery/bundle-postprocess.d.ts +12 -0
- package/dist/types.backup/vite/discovery/dev-prerender-cache.d.ts +65 -0
- package/dist/types.backup/vite/discovery/discover-routers.d.ts +17 -0
- package/dist/types.backup/vite/discovery/discovery-errors.d.ts +113 -0
- package/dist/types.backup/vite/discovery/gate-state.d.ts +79 -0
- package/dist/types.backup/vite/discovery/prerender-collection.d.ts +24 -0
- package/dist/types.backup/vite/discovery/route-types-writer.d.ts +32 -0
- package/dist/types.backup/vite/discovery/self-gen-tracking.d.ts +22 -0
- package/dist/types.backup/vite/discovery/shell-prerender-phase.d.ts +40 -0
- package/dist/types.backup/vite/discovery/state.d.ts +162 -0
- package/dist/types.backup/vite/discovery/virtual-module-codegen.d.ts +15 -0
- package/dist/types.backup/vite/index.d.ts +11 -0
- package/dist/types.backup/vite/inject-client-debug.d.ts +56 -0
- package/dist/types.backup/vite/plugin-types.d.ts +298 -0
- package/dist/types.backup/vite/plugins/cjs-to-esm.d.ts +6 -0
- package/dist/types.backup/vite/plugins/client-ref-dedup.d.ts +40 -0
- package/dist/types.backup/vite/plugins/client-ref-hashing.d.ts +35 -0
- package/dist/types.backup/vite/plugins/cloudflare-protocol-stub.d.ts +64 -0
- package/dist/types.backup/vite/plugins/expose-action-id.d.ts +18 -0
- package/dist/types.backup/vite/plugins/expose-id-utils.d.ts +37 -0
- package/dist/types.backup/vite/plugins/expose-ids/export-analysis.d.ts +19 -0
- package/dist/types.backup/vite/plugins/expose-ids/handler-transform.d.ts +10 -0
- package/dist/types.backup/vite/plugins/expose-ids/loader-transform.d.ts +8 -0
- package/dist/types.backup/vite/plugins/expose-ids/router-transform.d.ts +13 -0
- package/dist/types.backup/vite/plugins/expose-ids/types.d.ts +29 -0
- package/dist/types.backup/vite/plugins/expose-internal-ids.d.ts +6 -0
- package/dist/types.backup/vite/plugins/performance-tracks.d.ts +25 -0
- package/dist/types.backup/vite/plugins/refresh-cmd.d.ts +20 -0
- package/dist/types.backup/vite/plugins/use-cache-transform.d.ts +20 -0
- package/dist/types.backup/vite/plugins/vercel-output.d.ts +85 -0
- package/dist/types.backup/vite/plugins/version-injector.d.ts +21 -0
- package/dist/types.backup/vite/plugins/version-plugin.d.ts +19 -0
- package/dist/types.backup/vite/plugins/virtual-entries.d.ts +36 -0
- package/dist/types.backup/vite/plugins/virtual-stub-plugin.d.ts +7 -0
- package/dist/types.backup/vite/rango.d.ts +29 -0
- package/dist/types.backup/vite/router-discovery.d.ts +23 -0
- package/dist/types.backup/vite/utils/ast-handler-extract.d.ts +64 -0
- package/dist/types.backup/vite/utils/banner.d.ts +2 -0
- package/dist/types.backup/vite/utils/bundle-analysis.d.ts +28 -0
- package/dist/types.backup/vite/utils/client-chunks.d.ts +55 -0
- package/dist/types.backup/vite/utils/directive-prologue.d.ts +16 -0
- package/dist/types.backup/vite/utils/forward-user-plugins.d.ts +37 -0
- package/dist/types.backup/vite/utils/manifest-utils.d.ts +7 -0
- package/dist/types.backup/vite/utils/package-resolution.d.ts +6 -0
- package/dist/types.backup/vite/utils/prerender-utils.d.ts +32 -0
- package/dist/types.backup/vite/utils/shared-utils.d.ts +55 -0
- package/dist/vite/index.js +1 -1
- package/package.json +1 -1
- package/skills/parallel/SKILL.md +1 -1
- package/skills/ppr/SKILL.md +44 -3
- package/src/browser/prefetch/cache.ts +53 -9
- package/src/browser/prefetch/fetch.ts +83 -2
- package/src/cache/cf/cf-cache-store.ts +27 -8
- package/src/cache/types.ts +41 -6
- package/src/cache/vercel/vercel-cache-store.ts +24 -10
- package/src/route-definition/helpers-types.ts +5 -3
- package/src/rsc/capture-queue.ts +120 -47
- package/src/rsc/rsc-rendering.ts +11 -3
- package/src/rsc/shell-build-manifest.ts +20 -7
- package/src/rsc/shell-capture.ts +164 -12
- package/src/rsc/shell-serve.ts +27 -12
- package/src/static-handler.ts +18 -2
- package/src/urls/path-helper-types.ts +9 -10
package/src/rsc/capture-queue.ts
CHANGED
|
@@ -19,15 +19,55 @@
|
|
|
19
19
|
* is bounded; a capture killed mid-queue by that bound simply recaptures on a
|
|
20
20
|
* later request (the existing best-effort contract).
|
|
21
21
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
22
|
+
* Document shells outrank queued navigation-only snapshots. Production Link
|
|
23
|
+
* prefetching can enqueue several expensive navigation captures at once; a
|
|
24
|
+
* strict FIFO made the requesting page's document capture wait
|
|
25
|
+
* behind speculative work until its queue budget expired. The active capture
|
|
26
|
+
* is never interrupted, and each priority remains FIFO.
|
|
24
27
|
*/
|
|
25
|
-
let captureQueue: Promise<void> = Promise.resolve();
|
|
26
28
|
let admittedCaptures = 0;
|
|
29
|
+
let captureRunning = false;
|
|
30
|
+
|
|
31
|
+
interface QueuedCapture {
|
|
32
|
+
waitStart: number;
|
|
33
|
+
state: "waiting" | "running" | "settled";
|
|
34
|
+
signalStart: () => void;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const documentCaptures: QueuedCapture[] = [];
|
|
38
|
+
const navigationCaptures: QueuedCapture[] = [];
|
|
27
39
|
|
|
28
40
|
/** Bound queued/running capture closures retained by one isolate. */
|
|
29
41
|
export const MAX_ADMITTED_CAPTURES: number = 32;
|
|
30
42
|
|
|
43
|
+
/** Point-in-time queue occupancy, for capture-scheduling telemetry. */
|
|
44
|
+
export interface CaptureQueueDepths {
|
|
45
|
+
/** A capture is currently executing (never preempted). */
|
|
46
|
+
running: boolean;
|
|
47
|
+
/** Waiting document-priority captures (run before every navigation capture). */
|
|
48
|
+
document: number;
|
|
49
|
+
/** Waiting navigation-priority captures. */
|
|
50
|
+
navigation: number;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Snapshot the queue's waiting/running state. Wait-timed-out entries still
|
|
55
|
+
* sitting in the arrays (pruned lazily by takeNextCapture) are excluded — they
|
|
56
|
+
* will never run, so counting them would overstate the backlog.
|
|
57
|
+
*/
|
|
58
|
+
export function captureQueueDepths(): CaptureQueueDepths {
|
|
59
|
+
const waiting = (queue: QueuedCapture[]): number => {
|
|
60
|
+
let count = 0;
|
|
61
|
+
for (const queued of queue) if (queued.state === "waiting") count++;
|
|
62
|
+
return count;
|
|
63
|
+
};
|
|
64
|
+
return {
|
|
65
|
+
running: captureRunning,
|
|
66
|
+
document: waiting(documentCaptures),
|
|
67
|
+
navigation: waiting(navigationCaptures),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
31
71
|
/** The caller may drop this best-effort capture and retry on a later request. */
|
|
32
72
|
export class CaptureQueueFullError extends Error {
|
|
33
73
|
constructor() {
|
|
@@ -65,7 +105,7 @@ export class CaptureQueueWaitTimeoutError extends Error {
|
|
|
65
105
|
}
|
|
66
106
|
|
|
67
107
|
/**
|
|
68
|
-
* Upper bound on how long one
|
|
108
|
+
* Upper bound on how long one running capture may hold the queue. A capture task
|
|
69
109
|
* normally settles well inside this (attempt + in-place retry + writes), but
|
|
70
110
|
* a task wedged on never-settling I/O — a workerd waitUntil fetch that pends
|
|
71
111
|
* instead of rejecting (seen on GH runners with the dev prerender store
|
|
@@ -76,70 +116,103 @@ export class CaptureQueueWaitTimeoutError extends Error {
|
|
|
76
116
|
const QUEUE_LINK_CAP_MS = 60_000;
|
|
77
117
|
|
|
78
118
|
/**
|
|
79
|
-
* Run `task` after
|
|
80
|
-
* promise for THIS task's completion
|
|
81
|
-
* the queue itself is insulated).
|
|
119
|
+
* Run `task` after the active capture and every higher/equal-priority capture
|
|
120
|
+
* ahead of it have settled. Returns a promise for THIS task's completion
|
|
121
|
+
* (rejections propagate to the caller — the queue itself is insulated).
|
|
82
122
|
*/
|
|
83
123
|
export function enqueueSerializedCapture(
|
|
84
124
|
task: () => Promise<void>,
|
|
85
|
-
opts?: {
|
|
125
|
+
opts?: {
|
|
126
|
+
maxQueueWaitMs?: number;
|
|
127
|
+
priority?: "document" | "navigation";
|
|
128
|
+
},
|
|
86
129
|
): Promise<void> {
|
|
87
130
|
if (admittedCaptures >= MAX_ADMITTED_CAPTURES) {
|
|
88
131
|
return Promise.reject(new CaptureQueueFullError());
|
|
89
132
|
}
|
|
90
133
|
admittedCaptures++;
|
|
91
|
-
|
|
92
|
-
let
|
|
93
|
-
|
|
94
|
-
|
|
134
|
+
|
|
135
|
+
let signalStart!: () => void;
|
|
136
|
+
const startGate = new Promise<void>((resolve) => {
|
|
137
|
+
signalStart = resolve;
|
|
95
138
|
});
|
|
96
|
-
|
|
97
|
-
|
|
139
|
+
const queued: QueuedCapture = {
|
|
140
|
+
waitStart: performance.now(),
|
|
141
|
+
state: "waiting",
|
|
142
|
+
signalStart,
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const completion = (async () => {
|
|
98
146
|
const budget = opts?.maxQueueWaitMs ?? CAPTURE_QUEUE_WAIT_BUDGET_MS;
|
|
99
|
-
// The wait itself is budget-raced: the drop fires AT the budget, not once
|
|
100
|
-
// the predecessor eventually settles — a waiter parked behind a wedged
|
|
101
|
-
// link must not stay pending until that link's 60s cap just to learn it
|
|
102
|
-
// was already over budget.
|
|
103
147
|
let waitTimer: ReturnType<typeof setTimeout> | undefined;
|
|
104
148
|
const waitTimedOut = await Promise.race([
|
|
105
|
-
|
|
149
|
+
startGate.then(() => false),
|
|
106
150
|
new Promise<boolean>((resolve) => {
|
|
107
|
-
waitTimer = setTimeout(() =>
|
|
151
|
+
waitTimer = setTimeout(() => {
|
|
152
|
+
if (queued.state !== "waiting") return;
|
|
153
|
+
queued.state = "settled";
|
|
154
|
+
admittedCaptures--;
|
|
155
|
+
resolve(true);
|
|
156
|
+
}, budget);
|
|
108
157
|
(waitTimer as { unref?: () => void }).unref?.();
|
|
109
158
|
}),
|
|
110
159
|
]);
|
|
111
160
|
if (waitTimer) clearTimeout(waitTimer);
|
|
112
161
|
if (waitTimedOut) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
// releasing now would let a successor run concurrently with it.
|
|
117
|
-
admittedCaptures--;
|
|
118
|
-
prior.catch(() => {}).then(releaseQueue, releaseQueue);
|
|
119
|
-
throw new CaptureQueueWaitTimeoutError(performance.now() - waitStart);
|
|
162
|
+
throw new CaptureQueueWaitTimeoutError(
|
|
163
|
+
performance.now() - queued.waitStart,
|
|
164
|
+
);
|
|
120
165
|
}
|
|
166
|
+
|
|
167
|
+
let capTimer: ReturnType<typeof setTimeout> | undefined;
|
|
168
|
+
const taskPromise = Promise.resolve()
|
|
169
|
+
.then(task)
|
|
170
|
+
.finally(() => {
|
|
171
|
+
// A capped capture releases serialization, but its detached task still
|
|
172
|
+
// counts against admission until it actually settles.
|
|
173
|
+
admittedCaptures--;
|
|
174
|
+
});
|
|
175
|
+
const cap = new Promise<void>((resolve) => {
|
|
176
|
+
capTimer = setTimeout(resolve, QUEUE_LINK_CAP_MS);
|
|
177
|
+
(capTimer as { unref?: () => void }).unref?.();
|
|
178
|
+
});
|
|
179
|
+
|
|
121
180
|
try {
|
|
122
|
-
|
|
123
|
-
const taskPromise = Promise.resolve()
|
|
124
|
-
.then(task)
|
|
125
|
-
.finally(() => {
|
|
126
|
-
// A timed-out link releases serialization, but its detached task still
|
|
127
|
-
// counts against admission until it actually settles.
|
|
128
|
-
admittedCaptures--;
|
|
129
|
-
});
|
|
130
|
-
try {
|
|
131
|
-
await Promise.race([
|
|
132
|
-
taskPromise,
|
|
133
|
-
new Promise<void>((resolve) => {
|
|
134
|
-
capTimer = setTimeout(resolve, QUEUE_LINK_CAP_MS);
|
|
135
|
-
(capTimer as { unref?: () => void }).unref?.();
|
|
136
|
-
}),
|
|
137
|
-
]);
|
|
138
|
-
} finally {
|
|
139
|
-
if (capTimer) clearTimeout(capTimer);
|
|
140
|
-
}
|
|
181
|
+
await Promise.race([taskPromise, cap]);
|
|
141
182
|
} finally {
|
|
142
|
-
|
|
183
|
+
if (capTimer) clearTimeout(capTimer);
|
|
184
|
+
queued.state = "settled";
|
|
185
|
+
captureRunning = false;
|
|
186
|
+
// Handoff must happen before this caller's waitUntil promise settles.
|
|
187
|
+
// Resolving first lets workerd terminate the context with the queue lock
|
|
188
|
+
// still held, permanently parking later captures in the isolate.
|
|
189
|
+
startNextCapture();
|
|
143
190
|
}
|
|
144
191
|
})();
|
|
192
|
+
|
|
193
|
+
const queue =
|
|
194
|
+
opts?.priority === "document" ? documentCaptures : navigationCaptures;
|
|
195
|
+
queue.push(queued);
|
|
196
|
+
startNextCapture();
|
|
197
|
+
return completion;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function takeNextCapture(): QueuedCapture | undefined {
|
|
201
|
+
for (const queue of [documentCaptures, navigationCaptures]) {
|
|
202
|
+
let queued: QueuedCapture | undefined;
|
|
203
|
+
while ((queued = queue.shift())) {
|
|
204
|
+
if (queued.state === "waiting") return queued;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return undefined;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function startNextCapture(): void {
|
|
211
|
+
if (captureRunning) return;
|
|
212
|
+
const queued = takeNextCapture();
|
|
213
|
+
if (!queued) return;
|
|
214
|
+
|
|
215
|
+
captureRunning = true;
|
|
216
|
+
queued.state = "running";
|
|
217
|
+
queued.signalStart();
|
|
145
218
|
}
|
package/src/rsc/rsc-rendering.ts
CHANGED
|
@@ -79,6 +79,7 @@ import { reportCacheError } from "../cache/cache-error.js";
|
|
|
79
79
|
import type { SearchParamsFilter } from "../cache/search-params-filter.js";
|
|
80
80
|
import { INTERNAL_RANGO_DEBUG } from "../internal-debug.js";
|
|
81
81
|
import type {
|
|
82
|
+
DocumentShellCacheEntry,
|
|
82
83
|
SegmentCacheStore,
|
|
83
84
|
ShellCacheEntry,
|
|
84
85
|
ShellSnapshotRecord,
|
|
@@ -212,7 +213,14 @@ function replayableShellSnapshot(
|
|
|
212
213
|
if (!isValidShellHit(entry, buildVersion)) {
|
|
213
214
|
return { reason: "invalid-version" };
|
|
214
215
|
}
|
|
215
|
-
|
|
216
|
+
// navigationOnly entries store no document half (prelude/postponed absent),
|
|
217
|
+
// so the payload gate applies to document-snapshot entries alone. Replay
|
|
218
|
+
// consumes only the snapshot; fragment corruption inside it is caught by the
|
|
219
|
+
// consumer-side Flight decoders (SegmentFragmentDecodeError →
|
|
220
|
+
// segmentReplayCorrupt → healing capture at the document key).
|
|
221
|
+
if (!entry.navigationOnly && !hasIntactShellPayload(entry)) {
|
|
222
|
+
return { reason: "corrupt-entry" };
|
|
223
|
+
}
|
|
216
224
|
if (entry.handlerLiveHoles) return { reason: "handler-live-holes" };
|
|
217
225
|
if (entry.transitionWhen) return { reason: "transition-when" };
|
|
218
226
|
// Eligibility requires the CANONICAL doc segment record (`docKey`), not just
|
|
@@ -386,7 +394,7 @@ async function handleRscRenderingInner<TEnv>(
|
|
|
386
394
|
// build-manifest hit further down): schedule the background
|
|
387
395
|
// recapture when asked, then commit the composed response.
|
|
388
396
|
const serveHit = (
|
|
389
|
-
entry:
|
|
397
|
+
entry: DocumentShellCacheEntry,
|
|
390
398
|
revalidate: boolean | undefined,
|
|
391
399
|
): Response => {
|
|
392
400
|
if (revalidate) {
|
|
@@ -1159,7 +1167,7 @@ function serveShellHit(
|
|
|
1159
1167
|
reqCtx: RequestContext<any>,
|
|
1160
1168
|
handleStore: ReturnType<typeof getRequestContext>["_handleStore"],
|
|
1161
1169
|
ssrModule: SSRModule,
|
|
1162
|
-
entry:
|
|
1170
|
+
entry: DocumentShellCacheEntry,
|
|
1163
1171
|
descriptor: ShellCaptureDescriptor,
|
|
1164
1172
|
): Response {
|
|
1165
1173
|
const preludeBytes = base64ToBytes(entry.prelude);
|
|
@@ -25,7 +25,11 @@
|
|
|
25
25
|
* markers say whether it is still current.
|
|
26
26
|
*/
|
|
27
27
|
|
|
28
|
-
import type {
|
|
28
|
+
import type {
|
|
29
|
+
DocumentShellCacheEntry,
|
|
30
|
+
SegmentCacheStore,
|
|
31
|
+
ShellCacheEntry,
|
|
32
|
+
} from "../cache/types.js";
|
|
29
33
|
import { sortedSearchString } from "../cache/cache-key-utils.js";
|
|
30
34
|
import type { SearchParamsFilter } from "../cache/search-params-filter.js";
|
|
31
35
|
import {
|
|
@@ -88,20 +92,29 @@ function loadManifest(): Promise<ShellManifestModule | null> {
|
|
|
88
92
|
* Spec-only keying is sound because buildVersion is process-constant on the
|
|
89
93
|
* manifest path (folded into the shipped worker; dev never loads a manifest).
|
|
90
94
|
*/
|
|
91
|
-
const validatedSpecs = new Map<string,
|
|
95
|
+
const validatedSpecs = new Map<string, ValidatedBuildShellEntry | null>();
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* A manifest record whose document half passed hasIntactShellPayload — the
|
|
99
|
+
* casts below sit directly on that runtime gate (build entries are always
|
|
100
|
+
* document-shaped; the predicate narrows entry, not the record around it).
|
|
101
|
+
*/
|
|
102
|
+
type ValidatedBuildShellEntry = BuildShellEntry & {
|
|
103
|
+
entry: DocumentShellCacheEntry;
|
|
104
|
+
};
|
|
92
105
|
|
|
93
106
|
async function validatedManifestRecord(
|
|
94
107
|
mod: ShellManifestModule,
|
|
95
108
|
spec: string,
|
|
96
109
|
buildVersion: string,
|
|
97
|
-
): Promise<
|
|
110
|
+
): Promise<ValidatedBuildShellEntry | undefined> {
|
|
98
111
|
let verdict = validatedSpecs.get(spec);
|
|
99
112
|
if (verdict === undefined) {
|
|
100
113
|
const record = (await mod.loadShellAsset(spec)).default;
|
|
101
114
|
verdict =
|
|
102
115
|
isValidShellHit(record.entry, buildVersion) &&
|
|
103
116
|
hasIntactShellPayload(record.entry)
|
|
104
|
-
? record
|
|
117
|
+
? (record as ValidatedBuildShellEntry)
|
|
105
118
|
: null;
|
|
106
119
|
validatedSpecs.set(spec, verdict);
|
|
107
120
|
}
|
|
@@ -118,7 +131,7 @@ export function resetBuildShellManifestForTests(): void {
|
|
|
118
131
|
const warnedTagCheckUnsupported = new Set<string>();
|
|
119
132
|
|
|
120
133
|
export interface BuildShellHit {
|
|
121
|
-
entry:
|
|
134
|
+
entry: DocumentShellCacheEntry;
|
|
122
135
|
/** Past createdAt + ttl: serve, but schedule the runtime recapture. */
|
|
123
136
|
stale: boolean;
|
|
124
137
|
}
|
|
@@ -273,7 +286,7 @@ export async function lookupBuildShell(
|
|
|
273
286
|
const hasManifest = globalThis.__loadShellManifestModule !== undefined;
|
|
274
287
|
if (!hasManifest && !dev) return null;
|
|
275
288
|
if (sortedSearchString(url.searchParams, filter) !== "") return null;
|
|
276
|
-
let record:
|
|
289
|
+
let record: ValidatedBuildShellEntry | undefined;
|
|
277
290
|
if (hasManifest) {
|
|
278
291
|
const mod = await loadManifest();
|
|
279
292
|
if (!mod) return null;
|
|
@@ -286,7 +299,7 @@ export async function lookupBuildShell(
|
|
|
286
299
|
fetched !== undefined &&
|
|
287
300
|
isValidShellHit(fetched.entry, buildVersion) &&
|
|
288
301
|
hasIntactShellPayload(fetched.entry)
|
|
289
|
-
? fetched
|
|
302
|
+
? (fetched as ValidatedBuildShellEntry)
|
|
290
303
|
: undefined;
|
|
291
304
|
}
|
|
292
305
|
if (!record) return null;
|
package/src/rsc/shell-capture.ts
CHANGED
|
@@ -23,6 +23,7 @@ import { runBackground } from "../cache/background-task.js";
|
|
|
23
23
|
import {
|
|
24
24
|
CaptureQueueFullError,
|
|
25
25
|
CaptureQueueWaitTimeoutError,
|
|
26
|
+
captureQueueDepths,
|
|
26
27
|
enqueueSerializedCapture,
|
|
27
28
|
} from "./capture-queue.js";
|
|
28
29
|
import { SHELL_CAPTURE_MAX_WAIT_MS } from "./shell-capture-constants.js";
|
|
@@ -397,6 +398,43 @@ function warnSnapshotOverCapOnce(
|
|
|
397
398
|
);
|
|
398
399
|
}
|
|
399
400
|
|
|
401
|
+
/**
|
|
402
|
+
* Dev warning threshold (ms) for the slowest bake-source settlement wait. Bake
|
|
403
|
+
* time is by-design shell latency (top-level pushed handle promises and
|
|
404
|
+
* bake-lane loader containers settle before the freeze), but it recurs on
|
|
405
|
+
* EVERY capture of the route and occupies the per-isolate serialized capture
|
|
406
|
+
* queue — silently: the served response's own timing never shows it (a route
|
|
407
|
+
* can read 13ms TTFB while each of its captures holds the queue for seconds).
|
|
408
|
+
* Past this threshold the source gets named once per key with the remedy
|
|
409
|
+
* ladder.
|
|
410
|
+
*/
|
|
411
|
+
const SHELL_CAPTURE_BAKE_WARN_MS = 2_000;
|
|
412
|
+
|
|
413
|
+
/** Keys already warned about an expensive bake source (once per key). */
|
|
414
|
+
const warnedBakeCosts = new Set<string>();
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Dev-only, once per key: name the slowest bake source and the three remedies
|
|
418
|
+
* in preference order. The doctrine ("nesting = liveness") makes the cost
|
|
419
|
+
* legitimate, so this is a cost report with an exit, not a deprecation.
|
|
420
|
+
*/
|
|
421
|
+
function warnBakeCostOnce(key: string, source: string, ms: number): void {
|
|
422
|
+
if (warnedBakeCosts.has(key)) return;
|
|
423
|
+
warnedBakeCosts.add(key);
|
|
424
|
+
console.warn(
|
|
425
|
+
`[rango] Shell capture for "${key}" waited ${ms}ms for ${source} to ` +
|
|
426
|
+
"settle before the shell could freeze. This cost recurs on every capture " +
|
|
427
|
+
"of the route and occupies the per-isolate capture queue; the served " +
|
|
428
|
+
"response never shows it. Top-level promises BAKE by design (the " +
|
|
429
|
+
"container settles; nested promises stay live). To make the value " +
|
|
430
|
+
"per-request instead, nest it ({ data: promise }) and read it with use() " +
|
|
431
|
+
"under Suspense; to keep it baked but cheap, wrap the work in cache() " +
|
|
432
|
+
"(the capture replays the cached value); for a segment loader, add a " +
|
|
433
|
+
"loading() boundary to its entry (live lane, masked at capture). See the " +
|
|
434
|
+
"/ppr skill (node_modules/@rangojs/router/skills/ppr/SKILL.md).",
|
|
435
|
+
);
|
|
436
|
+
}
|
|
437
|
+
|
|
400
438
|
/**
|
|
401
439
|
* One structured event from the background capture pipeline, mirroring the
|
|
402
440
|
* CFCacheReadDebugEvent pattern (cache/cf/cf-cache-types.ts): typed fields an
|
|
@@ -418,6 +456,10 @@ export interface ShellCaptureDebugEvent {
|
|
|
418
456
|
* - skip-backoff: the key is inside its refused-capture backoff window and
|
|
419
457
|
* the capture was not attempted
|
|
420
458
|
* - skip-capacity: the isolate capture queue is full; a later request may retry
|
|
459
|
+
* - skip-inert-store: the resolved store's shell family is missing or
|
|
460
|
+
* declared inert (SegmentCacheStore.shellFamilyInert — a CFCacheStore
|
|
461
|
+
* without a KV namespace); nothing could store the result, so the
|
|
462
|
+
* background render was not scheduled at all
|
|
421
463
|
* - skip-queue-timeout: the capture waited past CAPTURE_QUEUE_WAIT_BUDGET_MS
|
|
422
464
|
* behind other captures and was dropped unrun (no backoff — the route is
|
|
423
465
|
* not doomed, the isolate was busy; a later request re-probes). Carries
|
|
@@ -434,6 +476,7 @@ export interface ShellCaptureDebugEvent {
|
|
|
434
476
|
| "skip-in-flight"
|
|
435
477
|
| "skip-backoff"
|
|
436
478
|
| "skip-capacity"
|
|
479
|
+
| "skip-inert-store"
|
|
437
480
|
| "skip-queue-timeout"
|
|
438
481
|
| "backoff";
|
|
439
482
|
/** Attempt number (1 = first, 2 = in-place retry). Absent on skips. */
|
|
@@ -466,6 +509,22 @@ export interface ShellCaptureDebugEvent {
|
|
|
466
509
|
backoffRemainingMs?: number;
|
|
467
510
|
/** Ms the capture waited in the serialized queue (skip-queue-timeout). */
|
|
468
511
|
queueWaitMs?: number;
|
|
512
|
+
/** Queue priority class at enqueue: document outranks queued navigation. */
|
|
513
|
+
queuePriority?: "document" | "navigation";
|
|
514
|
+
/**
|
|
515
|
+
* Captures ahead at enqueue: the active one plus every waiting capture of
|
|
516
|
+
* same-or-higher priority. 0 = this capture starts immediately.
|
|
517
|
+
*/
|
|
518
|
+
queueAhead?: number;
|
|
519
|
+
/**
|
|
520
|
+
* Ms the capture gate was HELD waiting for the slowest bake source — a
|
|
521
|
+
* top-level pushed handle promise or a bake-lane loader container — to
|
|
522
|
+
* settle, measured from capture start. Bake time is by-design shell latency
|
|
523
|
+
* (the hole doctrine: top-level promises bake), but it recurs on EVERY
|
|
524
|
+
* capture of the route and occupies the serialized queue; this field makes
|
|
525
|
+
* it attributable. Absent when nothing held the gate.
|
|
526
|
+
*/
|
|
527
|
+
bakeWaitMs?: number;
|
|
469
528
|
}
|
|
470
529
|
|
|
471
530
|
/**
|
|
@@ -515,6 +574,15 @@ export function describeShellCaptureEvent(
|
|
|
515
574
|
if (event.queueWaitMs !== undefined) {
|
|
516
575
|
parts.push(`queue-wait=${event.queueWaitMs}ms`);
|
|
517
576
|
}
|
|
577
|
+
if (event.queuePriority !== undefined) {
|
|
578
|
+
parts.push(`queue-priority=${event.queuePriority}`);
|
|
579
|
+
}
|
|
580
|
+
if (event.queueAhead !== undefined) {
|
|
581
|
+
parts.push(`queue-ahead=${event.queueAhead}`);
|
|
582
|
+
}
|
|
583
|
+
if (event.bakeWaitMs !== undefined) {
|
|
584
|
+
parts.push(`bake=${event.bakeWaitMs}ms`);
|
|
585
|
+
}
|
|
518
586
|
return parts.join(" ");
|
|
519
587
|
}
|
|
520
588
|
|
|
@@ -864,6 +932,16 @@ export function scheduleShellCapture(
|
|
|
864
932
|
});
|
|
865
933
|
return;
|
|
866
934
|
}
|
|
935
|
+
// A capture whose write can only no-op is dead work that still occupies the
|
|
936
|
+
// serialized queue (a promise-heavy route bakes for seconds per MISS),
|
|
937
|
+
// starving captures that CAN store. Skip scheduling entirely when the
|
|
938
|
+
// resolved store (same defaulting as captureAndStoreShell) has no shell
|
|
939
|
+
// family or declared it inert (CFCacheStore without a KV namespace).
|
|
940
|
+
const scheduledStore = descriptor.store ?? reqCtx._cacheStore;
|
|
941
|
+
if (!scheduledStore?.putShell || scheduledStore.shellFamilyInert) {
|
|
942
|
+
publishCaptureDebugEvent(descriptor, { key, outcome: "skip-inert-store" });
|
|
943
|
+
return;
|
|
944
|
+
}
|
|
867
945
|
inFlightCaptures.add(key);
|
|
868
946
|
const captureTask = async (span: TraceSpan) => {
|
|
869
947
|
try {
|
|
@@ -941,15 +1019,34 @@ export function scheduleShellCapture(
|
|
|
941
1019
|
const serializedTask = async () => {
|
|
942
1020
|
await observePhase(PHASES.background("shell-capture"), async (span) => {
|
|
943
1021
|
span.setAttribute("rango.shell_key", key);
|
|
1022
|
+
// A production page can enqueue several navigation-only captures through
|
|
1023
|
+
// viewport prefetching. Let a later document MISS overtake that queued
|
|
1024
|
+
// speculative work so it can become a shell HIT before the 15s queue
|
|
1025
|
+
// budget expires. Never preempts the active capture. Priority and the
|
|
1026
|
+
// backlog ahead at enqueue ride the span (and the skip event below), so
|
|
1027
|
+
// a skip-queue-timeout diagnoses itself instead of needing a trace dive.
|
|
1028
|
+
const queuePriority = descriptor.navigationOnly
|
|
1029
|
+
? ("navigation" as const)
|
|
1030
|
+
: ("document" as const);
|
|
1031
|
+
const depths = captureQueueDepths();
|
|
1032
|
+
const queueAhead =
|
|
1033
|
+
(depths.running ? 1 : 0) +
|
|
1034
|
+
depths.document +
|
|
1035
|
+
(queuePriority === "navigation" ? depths.navigation : 0);
|
|
1036
|
+
span.setAttribute("rango.background.queue_priority", queuePriority);
|
|
1037
|
+
span.setAttribute("rango.background.queue_ahead", queueAhead);
|
|
944
1038
|
const queueStart = performance.now();
|
|
945
1039
|
try {
|
|
946
|
-
await enqueueSerializedCapture(
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
1040
|
+
await enqueueSerializedCapture(
|
|
1041
|
+
() => {
|
|
1042
|
+
span.setAttribute(
|
|
1043
|
+
"rango.background.queue_wait_ms",
|
|
1044
|
+
Math.round(performance.now() - queueStart),
|
|
1045
|
+
);
|
|
1046
|
+
return captureTask(span);
|
|
1047
|
+
},
|
|
1048
|
+
{ priority: queuePriority },
|
|
1049
|
+
);
|
|
953
1050
|
} catch (error) {
|
|
954
1051
|
if (error instanceof CaptureQueueFullError) {
|
|
955
1052
|
inFlightCaptures.delete(key);
|
|
@@ -974,6 +1071,8 @@ export function scheduleShellCapture(
|
|
|
974
1071
|
key,
|
|
975
1072
|
outcome: "skip-queue-timeout",
|
|
976
1073
|
queueWaitMs: Math.round(error.waitedMs),
|
|
1074
|
+
queuePriority,
|
|
1075
|
+
queueAhead,
|
|
977
1076
|
});
|
|
978
1077
|
return;
|
|
979
1078
|
}
|
|
@@ -1035,6 +1134,7 @@ type CaptureAttemptStats = Pick<
|
|
|
1035
1134
|
| "snapshotSkipped"
|
|
1036
1135
|
| "untaggedBake"
|
|
1037
1136
|
| "storeWrite"
|
|
1137
|
+
| "bakeWaitMs"
|
|
1038
1138
|
>;
|
|
1039
1139
|
|
|
1040
1140
|
/**
|
|
@@ -1511,6 +1611,29 @@ async function captureAndStoreShell(
|
|
|
1511
1611
|
loaderRecordsForHold && loaderRecordsForHold.size > 0
|
|
1512
1612
|
? Promise.allSettled([handlesBaked, ...loaderRecordsForHold.values()])
|
|
1513
1613
|
: handlesBaked;
|
|
1614
|
+
// Bake-cost attribution: record how long each bake source held the gate,
|
|
1615
|
+
// measured from capture start. Side-channel observers only — holdUntil and
|
|
1616
|
+
// its consumers are untouched, and a rejected source is recorded the same
|
|
1617
|
+
// (allSettled swallows it; the drain below owns the refusal). Folded into
|
|
1618
|
+
// stats.bakeWaitMs (+ a once-per-key dev warning) after a successful
|
|
1619
|
+
// capture; on a refusal the other warnings own the story.
|
|
1620
|
+
const bakeStart = performance.now();
|
|
1621
|
+
const bakeWaits: { source: string; ms: number }[] = [];
|
|
1622
|
+
const observeBake = (source: string, promise: Promise<unknown>): void => {
|
|
1623
|
+
const record = (): void => {
|
|
1624
|
+
bakeWaits.push({
|
|
1625
|
+
source,
|
|
1626
|
+
ms: Math.round(performance.now() - bakeStart),
|
|
1627
|
+
});
|
|
1628
|
+
};
|
|
1629
|
+
promise.then(record, record);
|
|
1630
|
+
};
|
|
1631
|
+
observeBake("top-level pushed handle promises", handlesBaked);
|
|
1632
|
+
if (loaderRecordsForHold) {
|
|
1633
|
+
for (const [loaderId, promise] of loaderRecordsForHold) {
|
|
1634
|
+
observeBake(`bake-lane segment loader "${loaderId}"`, promise);
|
|
1635
|
+
}
|
|
1636
|
+
}
|
|
1514
1637
|
const gate = gateFlightForCapture(rscStream, undefined, holdUntil);
|
|
1515
1638
|
// Quiesce = handles settled AND the Flight shell rows went task-quiet. Either
|
|
1516
1639
|
// half stalling is bounded by captureShellHTML's maxWaitMs.
|
|
@@ -1590,6 +1713,23 @@ async function captureAndStoreShell(
|
|
|
1590
1713
|
}
|
|
1591
1714
|
if (stats) stats.preludeBytes = result.prelude.length;
|
|
1592
1715
|
|
|
1716
|
+
// Every bake source has settled by here (quiesce gates on holdUntil).
|
|
1717
|
+
// Surface the slowest one: sub-ms settles are noise, threshold-crossers
|
|
1718
|
+
// get the dev warning with the remedy ladder.
|
|
1719
|
+
let slowestBake: { source: string; ms: number } | undefined;
|
|
1720
|
+
for (const wait of bakeWaits) {
|
|
1721
|
+
if (!slowestBake || wait.ms > slowestBake.ms) slowestBake = wait;
|
|
1722
|
+
}
|
|
1723
|
+
if (slowestBake && slowestBake.ms > 0) {
|
|
1724
|
+
if (stats) stats.bakeWaitMs = slowestBake.ms;
|
|
1725
|
+
if (
|
|
1726
|
+
process.env.NODE_ENV !== "production" &&
|
|
1727
|
+
slowestBake.ms >= SHELL_CAPTURE_BAKE_WARN_MS
|
|
1728
|
+
) {
|
|
1729
|
+
warnBakeCostOnce(capture.key, slowestBake.source, slowestBake.ms);
|
|
1730
|
+
}
|
|
1731
|
+
}
|
|
1732
|
+
|
|
1593
1733
|
// Store per the flag's key/ttl/swr/tags, into the flag's store: the middleware
|
|
1594
1734
|
// threads the SAME store it resolved for its getShell read (options.store ??
|
|
1595
1735
|
// _cacheStore), so a store-attached middleware writes captures where it reads
|
|
@@ -1746,11 +1886,23 @@ async function captureAndStoreShell(
|
|
|
1746
1886
|
if (store?.putShell) {
|
|
1747
1887
|
try {
|
|
1748
1888
|
const entry: ShellCacheEntry = {
|
|
1749
|
-
//
|
|
1750
|
-
//
|
|
1751
|
-
//
|
|
1752
|
-
|
|
1753
|
-
|
|
1889
|
+
// Document half only for document captures. A navigationOnly entry's
|
|
1890
|
+
// HTML is never served (document reads skip the flag; partial replay
|
|
1891
|
+
// consumes only snapshot/docKey), so storing it would ride every KV
|
|
1892
|
+
// write/read as dead weight — the prerender still ran above as the
|
|
1893
|
+
// completeness arbiter and sanity gate, its output is dropped here.
|
|
1894
|
+
...(capture.navigationOnly
|
|
1895
|
+
? {}
|
|
1896
|
+
: {
|
|
1897
|
+
// slice() copies just this view's bytes into a fresh
|
|
1898
|
+
// ArrayBuffer, so a prelude that is a subarray of a larger
|
|
1899
|
+
// backing buffer encodes only its own region — bufferToBase64
|
|
1900
|
+
// reads the whole ArrayBuffer it is handed.
|
|
1901
|
+
prelude: bufferToBase64(
|
|
1902
|
+
result.prelude.slice().buffer as ArrayBuffer,
|
|
1903
|
+
),
|
|
1904
|
+
postponed: result.postponed,
|
|
1905
|
+
}),
|
|
1754
1906
|
reactVersion: React.version,
|
|
1755
1907
|
buildVersion: capture.buildVersion,
|
|
1756
1908
|
// The theme this capture's payload was built with (buildFullPayload
|
package/src/rsc/shell-serve.ts
CHANGED
|
@@ -20,7 +20,11 @@ import React from "react";
|
|
|
20
20
|
import { isPprEntry, type EntryData } from "../server/context.js";
|
|
21
21
|
import { sortedSearchString } from "../cache/cache-key-utils.js";
|
|
22
22
|
import type { SearchParamsFilter } from "../cache/search-params-filter.js";
|
|
23
|
-
import type {
|
|
23
|
+
import type {
|
|
24
|
+
DocumentShellCacheEntry,
|
|
25
|
+
ShellCacheEntry,
|
|
26
|
+
SegmentCacheStore,
|
|
27
|
+
} from "../cache/types.js";
|
|
24
28
|
import { SHELL_CAPTURE_MAX_WAIT_MS } from "./shell-capture-constants.js";
|
|
25
29
|
|
|
26
30
|
/** Debug/status header the browser (and e2e assertions) can read: HIT | MISS. */
|
|
@@ -150,18 +154,29 @@ export function isValidShellHit(
|
|
|
150
154
|
}
|
|
151
155
|
|
|
152
156
|
/**
|
|
153
|
-
*
|
|
154
|
-
* whose prelude is not decodable base64 or whose
|
|
155
|
-
* parseable JSON would otherwise throw AFTER the 200 +
|
|
156
|
-
* flushed (`serveShellHit` decodes at stream construction,
|
|
157
|
-
* parses in the tail) — the client gets a visually complete
|
|
158
|
-
* hydrates, re-served on every request until the entry ages
|
|
159
|
-
* path exists; failure schedules no recapture by itself).
|
|
160
|
-
* a corrupt entry (store-layer fault) into a plain MISS
|
|
161
|
-
* overwrites. Cost: one duplicate decode/parse per HIT, sub-ms
|
|
162
|
-
* prelude flush that dominates the path.
|
|
157
|
+
* DOCUMENT-half integrity gate and type narrowing, run BEFORE the HIT response
|
|
158
|
+
* commits: a stored entry whose prelude is not decodable base64 or whose
|
|
159
|
+
* postponed blob is not parseable JSON would otherwise throw AFTER the 200 +
|
|
160
|
+
* full static prelude flushed (`serveShellHit` decodes at stream construction,
|
|
161
|
+
* `resumeShellHTML` parses in the tail) — the client gets a visually complete
|
|
162
|
+
* page that never hydrates, re-served on every request until the entry ages
|
|
163
|
+
* out (no eviction path exists; failure schedules no recapture by itself).
|
|
164
|
+
* Checking here turns a corrupt entry (store-layer fault) into a plain MISS
|
|
165
|
+
* the recapture overwrites. Cost: one duplicate decode/parse per HIT, sub-ms
|
|
166
|
+
* against a prelude flush that dominates the path.
|
|
167
|
+
*
|
|
168
|
+
* navigationOnly entries store no document half (prelude/postponed absent) and
|
|
169
|
+
* therefore never pass. The partial-replay path skips this gate for them
|
|
170
|
+
* (replayableShellSnapshot) — snapshot fragment corruption is caught by the
|
|
171
|
+
* consumer-side Flight decoders instead (SegmentFragmentDecodeError → healing
|
|
172
|
+
* capture).
|
|
163
173
|
*/
|
|
164
|
-
export function hasIntactShellPayload(
|
|
174
|
+
export function hasIntactShellPayload(
|
|
175
|
+
entry: ShellCacheEntry,
|
|
176
|
+
): entry is DocumentShellCacheEntry {
|
|
177
|
+
if (typeof entry.prelude !== "string" || entry.postponed === undefined) {
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
165
180
|
try {
|
|
166
181
|
base64ToBytes(entry.prelude);
|
|
167
182
|
if (entry.postponed !== null) JSON.parse(entry.postponed);
|