@rangojs/router 0.0.0-experimental.14 → 0.0.0-experimental.141
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 +17 -0
- package/README.md +432 -7
- package/dist/bin/rango.js +2073 -213
- package/dist/testing/vitest.js +82 -0
- package/dist/vite/index.js +7258 -2714
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +140 -67
- package/skills/api-client/SKILL.md +211 -0
- package/skills/breadcrumbs/SKILL.md +329 -0
- package/skills/bundle-analysis/SKILL.md +159 -0
- package/skills/cache-guide/SKILL.md +487 -0
- package/skills/caching/SKILL.md +357 -25
- package/skills/comparison/SKILL.md +50 -0
- package/skills/comparison/agents/openai.yaml +4 -0
- package/skills/comparison/references/framework-comparison.md +837 -0
- package/skills/composability/SKILL.md +246 -0
- package/skills/css/SKILL.md +76 -0
- package/skills/debug-manifest/SKILL.md +16 -10
- package/skills/document-cache/SKILL.md +87 -62
- package/skills/fonts/SKILL.md +6 -4
- package/skills/handler-use/SKILL.md +364 -0
- package/skills/hooks/SKILL.md +557 -79
- package/skills/host-router/SKILL.md +320 -0
- package/skills/i18n/SKILL.md +276 -0
- package/skills/intercept/SKILL.md +207 -15
- package/skills/layout/SKILL.md +146 -6
- package/skills/links/SKILL.md +304 -25
- package/skills/loader/SKILL.md +616 -54
- package/skills/middleware/SKILL.md +217 -37
- package/skills/migrate-nextjs/SKILL.md +611 -0
- package/skills/migrate-react-router/SKILL.md +927 -0
- package/skills/mime-routes/SKILL.md +42 -11
- package/skills/observability/SKILL.md +194 -0
- package/skills/parallel/SKILL.md +284 -3
- package/skills/ppr/SKILL.md +293 -0
- package/skills/prerender/SKILL.md +437 -52
- package/skills/rango/SKILL.md +369 -22
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +263 -121
- package/skills/route/SKILL.md +350 -21
- package/skills/router-setup/SKILL.md +246 -33
- package/skills/scripts/SKILL.md +179 -0
- package/skills/server-actions/SKILL.md +775 -0
- package/skills/shell-manifest/SKILL.md +185 -0
- package/skills/streams-and-websockets/SKILL.md +283 -0
- package/skills/tailwind/SKILL.md +27 -3
- package/skills/testing/SKILL.md +126 -222
- package/skills/testing/bindings.md +103 -0
- package/skills/testing/cache-prerender.md +127 -0
- package/skills/testing/client-components.md +124 -0
- package/skills/testing/e2e-parity.md +125 -0
- package/skills/testing/flight.md +91 -0
- package/skills/testing/handles.md +131 -0
- package/skills/testing/loader.md +128 -0
- package/skills/testing/middleware.md +99 -0
- package/skills/testing/render-handler.md +122 -0
- package/skills/testing/response-routes.md +95 -0
- package/skills/testing/reverse-and-types.md +85 -0
- package/skills/testing/server-actions.md +107 -0
- package/skills/testing/server-tree.md +128 -0
- package/skills/testing/setup.md +123 -0
- package/skills/theme/SKILL.md +9 -8
- package/skills/typesafety/SKILL.md +532 -103
- package/skills/use-cache/SKILL.md +367 -0
- package/skills/vercel/SKILL.md +128 -0
- package/skills/view-transitions/SKILL.md +337 -0
- package/src/__augment-tests__/augment.ts +81 -0
- package/src/__augment-tests__/augmented.check.ts +116 -0
- package/src/__internal.ts +77 -44
- package/src/bin/rango.ts +312 -15
- package/src/browser/action-coordinator.ts +114 -0
- package/src/browser/action-fence.ts +47 -0
- package/src/browser/app-shell.ts +39 -0
- package/src/browser/app-version.ts +14 -0
- package/src/browser/connection-warmup.ts +134 -0
- package/src/browser/cookie-name.ts +140 -0
- package/src/browser/event-controller.ts +293 -202
- package/src/browser/history-state.ts +101 -0
- package/src/browser/index.ts +3 -3
- package/src/browser/intercept-utils.ts +52 -0
- package/src/browser/invalidate-client-cache.ts +52 -0
- package/src/browser/link-interceptor.ts +24 -4
- package/src/browser/logging.ts +11 -0
- package/src/browser/merge-segment-loaders.ts +20 -12
- package/src/browser/navigation-bridge.ts +385 -576
- package/src/browser/navigation-client.ts +245 -75
- package/src/browser/navigation-store-handle.ts +38 -0
- package/src/browser/navigation-store.ts +184 -118
- package/src/browser/navigation-transaction.ts +247 -0
- package/src/browser/network-error-handler.ts +88 -0
- package/src/browser/partial-update.ts +412 -364
- package/src/browser/prefetch/cache.ts +359 -0
- package/src/browser/prefetch/fetch.ts +452 -0
- package/src/browser/prefetch/observer.ts +65 -0
- package/src/browser/prefetch/policy.ts +48 -0
- package/src/browser/prefetch/queue.ts +209 -0
- package/src/browser/prefetch/resource-ready.ts +77 -0
- package/src/browser/rango-state.ts +194 -0
- package/src/browser/react/Link.tsx +275 -68
- package/src/browser/react/NavigationProvider.tsx +265 -109
- package/src/browser/react/ScrollRestoration.tsx +10 -6
- package/src/browser/react/context.ts +11 -0
- package/src/browser/react/filter-segment-order.ts +70 -0
- package/src/browser/react/index.ts +0 -48
- package/src/browser/react/location-state-shared.ts +272 -60
- package/src/browser/react/location-state.ts +90 -20
- package/src/browser/react/mount-context.ts +6 -1
- package/src/browser/react/nonce-context.ts +23 -0
- package/src/browser/react/shallow-equal.ts +27 -0
- package/src/browser/react/use-action.ts +35 -66
- package/src/browser/react/use-handle.ts +39 -126
- package/src/browser/react/use-href.tsx +8 -1
- package/src/browser/react/use-link-status.ts +39 -13
- package/src/browser/react/use-navigation.ts +53 -69
- package/src/browser/react/use-params.ts +75 -0
- package/src/browser/react/use-pathname.ts +47 -0
- package/src/browser/react/use-reverse.ts +106 -0
- package/src/browser/react/use-router.ts +98 -0
- package/src/browser/react/use-search-params.ts +51 -0
- package/src/browser/react/use-segments.ts +72 -99
- package/src/browser/response-adapter.ts +164 -0
- package/src/browser/rsc-router.tsx +300 -72
- package/src/browser/scroll-restoration.ts +138 -50
- package/src/browser/segment-reconciler.ts +243 -0
- package/src/browser/segment-structure-assert.ts +17 -1
- package/src/browser/server-action-bridge.ts +668 -613
- package/src/browser/types.ts +223 -51
- package/src/browser/validate-redirect-origin.ts +56 -0
- package/src/build/collect-fallback-refs.ts +107 -0
- package/src/build/generate-manifest.ts +252 -161
- package/src/build/generate-route-types.ts +41 -1038
- package/src/build/index.ts +12 -7
- package/src/build/prefix-tree-utils.ts +123 -0
- package/src/build/route-trie.ts +225 -42
- package/src/build/route-types/ast-helpers.ts +25 -0
- package/src/build/route-types/ast-route-extraction.ts +105 -0
- package/src/build/route-types/codegen.ts +113 -0
- package/src/build/route-types/include-resolution.ts +812 -0
- package/src/build/route-types/param-extraction.ts +51 -0
- package/src/build/route-types/per-module-writer.ts +144 -0
- package/src/build/route-types/router-processing.ts +695 -0
- package/src/build/route-types/scan-filter.ts +85 -0
- package/src/build/route-types/source-scan.ts +216 -0
- package/src/build/runtime-discovery.ts +223 -0
- package/src/cache/background-task.ts +34 -0
- package/src/cache/cache-error.ts +104 -0
- package/src/cache/cache-key-utils.ts +60 -0
- package/src/cache/cache-policy.ts +199 -0
- package/src/cache/cache-runtime.ts +525 -0
- package/src/cache/cache-scope.ts +298 -332
- package/src/cache/cache-tag.ts +103 -0
- package/src/cache/cf/cf-base64.ts +33 -0
- package/src/cache/cf/cf-cache-constants.ts +127 -0
- package/src/cache/cf/cf-cache-store.ts +2508 -158
- package/src/cache/cf/cf-cache-types.ts +349 -0
- package/src/cache/cf/cf-kv-utils.ts +46 -0
- package/src/cache/cf/cf-tag-marker-memo.ts +105 -0
- package/src/cache/cf/index.ts +17 -17
- package/src/cache/document-cache.ts +199 -92
- package/src/cache/handle-capture.ts +81 -0
- package/src/cache/handle-snapshot.ts +111 -0
- package/src/cache/index.ts +24 -35
- package/src/cache/memory-segment-store.ts +363 -30
- package/src/cache/profile-registry.ts +88 -0
- package/src/cache/read-through-swr.ts +178 -0
- package/src/cache/segment-codec.ts +248 -0
- package/src/cache/shell-snapshot.ts +368 -0
- package/src/cache/tag-invalidation.ts +230 -0
- package/src/cache/taint.ts +153 -0
- package/src/cache/types.ts +222 -211
- package/src/cache/vercel/index.ts +11 -0
- package/src/cache/vercel/vercel-cache-store.ts +1113 -0
- package/src/client.rsc.tsx +43 -21
- package/src/client.tsx +131 -347
- package/src/cloudflare/index.ts +11 -0
- package/src/cloudflare/tracing.ts +109 -0
- package/src/component-utils.ts +23 -4
- package/src/components/DefaultDocument.tsx +13 -3
- package/src/context-var.ts +168 -0
- package/src/debug.ts +19 -9
- package/src/decode-loader-results.ts +52 -0
- package/src/defer.ts +185 -0
- package/src/deps/ssr.ts +0 -1
- package/src/encode-kv.ts +49 -0
- package/src/errors.ts +106 -10
- package/src/escape-script.ts +52 -0
- package/src/handle.ts +110 -35
- package/src/handles/MetaTags.tsx +83 -59
- package/src/handles/Scripts.tsx +183 -0
- package/src/handles/breadcrumbs.ts +93 -0
- package/src/handles/deferred-resolution.ts +127 -0
- package/src/handles/is-thenable.ts +18 -0
- package/src/handles/meta.ts +44 -53
- package/src/handles/script.ts +244 -0
- package/src/host/cookie-handler.ts +20 -65
- package/src/host/errors.ts +21 -30
- package/src/host/index.ts +13 -9
- package/src/host/pattern-matcher.ts +50 -79
- package/src/host/router.ts +151 -121
- package/src/host/testing.ts +45 -32
- package/src/host/types.ts +52 -11
- package/src/host/utils.ts +2 -2
- package/src/href-client.ts +192 -57
- package/src/index.rsc.ts +173 -35
- package/src/index.ts +241 -73
- package/src/internal-debug.ts +9 -2
- package/src/loader-store.ts +500 -0
- package/src/loader.rsc.ts +31 -99
- package/src/loader.ts +30 -12
- package/src/missing-id-error.ts +68 -0
- package/src/outlet-context.ts +1 -1
- package/src/outlet-provider.tsx +41 -0
- package/src/prerender/param-hash.ts +16 -14
- package/src/prerender/store.ts +121 -21
- package/src/prerender.ts +460 -26
- package/src/redirect-origin.ts +100 -0
- package/src/regex-escape.ts +8 -0
- package/src/render-error-thrower.tsx +20 -0
- package/src/response-utils.ts +62 -0
- package/src/reverse.ts +198 -128
- package/src/root-error-boundary.tsx +42 -48
- package/src/route-content-wrapper.tsx +22 -77
- package/src/route-definition/dsl-helpers.ts +1116 -0
- package/src/route-definition/helper-factories.ts +88 -0
- package/src/route-definition/helpers-types.ts +505 -0
- package/src/route-definition/index.ts +54 -0
- package/src/route-definition/redirect.ts +134 -0
- package/src/route-definition/resolve-handler-use.ts +160 -0
- package/src/route-definition/use-item-types.ts +29 -0
- package/src/route-definition.ts +1 -1481
- package/src/route-map-builder.ts +82 -144
- package/src/route-name.ts +53 -0
- package/src/route-types.ts +71 -45
- package/src/router/basename.ts +14 -0
- package/src/router/content-negotiation.ts +263 -0
- package/src/router/debug-manifest.ts +72 -0
- package/src/router/error-handling.ts +54 -27
- package/src/router/find-match.ts +245 -0
- package/src/router/handler-context.ts +377 -125
- package/src/router/instrument.ts +350 -0
- package/src/router/intercept-resolution.ts +59 -28
- package/src/router/lazy-includes.ts +254 -0
- package/src/router/loader-resolution.ts +421 -157
- package/src/router/logging.ts +106 -6
- package/src/router/manifest.ts +131 -57
- package/src/router/match-api.ts +167 -246
- package/src/router/match-context.ts +4 -24
- package/src/router/match-handlers.ts +440 -0
- package/src/router/match-middleware/background-revalidation.ts +117 -93
- package/src/router/match-middleware/cache-lookup.ts +297 -150
- package/src/router/match-middleware/cache-store.ts +123 -51
- package/src/router/match-middleware/intercept-resolution.ts +44 -43
- package/src/router/match-middleware/segment-resolution.ts +64 -22
- package/src/router/match-pipelines.ts +11 -87
- package/src/router/match-result.ts +121 -50
- package/src/router/metrics.ts +219 -28
- package/src/router/middleware-types.ts +93 -0
- package/src/router/middleware.ts +505 -441
- package/src/router/navigation-snapshot.ts +133 -0
- package/src/router/params-util.ts +23 -0
- package/src/router/parse-pattern.ts +115 -0
- package/src/router/pattern-matching.ts +311 -142
- package/src/router/prefetch-cache-ttl.ts +51 -0
- package/src/router/prefetch-limits.ts +37 -0
- package/src/router/prerender-match.ts +547 -0
- package/src/router/preview-match.ts +102 -0
- package/src/router/request-classification.ts +278 -0
- package/src/router/revalidation.ts +203 -62
- package/src/router/route-snapshot.ts +246 -0
- package/src/router/router-context.ts +45 -48
- package/src/router/router-interfaces.ts +554 -0
- package/src/router/router-options.ts +779 -0
- package/src/router/router-registry.ts +21 -0
- package/src/router/segment-resolution/fresh.ts +772 -0
- package/src/router/segment-resolution/helpers.ts +348 -0
- package/src/router/segment-resolution/loader-cache.ts +250 -0
- package/src/router/segment-resolution/loader-mask.ts +44 -0
- package/src/router/segment-resolution/revalidation.ts +1331 -0
- package/src/router/segment-resolution/static-store.ts +81 -0
- package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
- package/src/router/segment-resolution/view-transition-default.ts +56 -0
- package/src/router/segment-resolution.ts +25 -1354
- package/src/router/segment-wrappers.ts +292 -0
- package/src/router/state-cookie-name.ts +33 -0
- package/src/router/substitute-pattern-params.ts +75 -0
- package/src/router/telemetry-otel.ts +261 -0
- package/src/router/telemetry.ts +377 -0
- package/src/router/timeout.ts +128 -0
- package/src/router/tracing.ts +206 -0
- package/src/router/trie-matching.ts +240 -61
- package/src/router/types.ts +23 -70
- package/src/router/url-params.ts +57 -0
- package/src/router.ts +781 -2378
- package/src/rsc/full-payload.ts +70 -0
- package/src/rsc/handler-context.ts +46 -0
- package/src/rsc/handler.ts +905 -1142
- package/src/rsc/helpers.ts +275 -19
- package/src/rsc/index.ts +2 -25
- package/src/rsc/json-route-result.ts +38 -0
- package/src/rsc/loader-fetch.ts +305 -0
- package/src/rsc/manifest-init.ts +77 -0
- package/src/rsc/nonce.ts +14 -0
- package/src/rsc/origin-guard.ts +155 -0
- package/src/rsc/progressive-enhancement.ts +502 -0
- package/src/rsc/redirect-guard.ts +99 -0
- package/src/rsc/response-cache-serve.ts +238 -0
- package/src/rsc/response-error.ts +104 -0
- package/src/rsc/response-route-handler.ts +257 -0
- package/src/rsc/rsc-rendering.ts +527 -0
- package/src/rsc/runtime-warnings.ts +55 -0
- package/src/rsc/server-action.ts +522 -0
- package/src/rsc/shell-capture.ts +897 -0
- package/src/rsc/shell-serve.ts +124 -0
- package/src/rsc/ssr-setup.ts +144 -0
- package/src/rsc/transition-gate.ts +89 -0
- package/src/rsc/types.ts +95 -12
- package/src/runtime-env.ts +18 -0
- package/src/search-params.ts +99 -82
- package/src/segment-content-promise.ts +67 -0
- package/src/segment-loader-promise.ts +149 -0
- package/src/segment-system.tsx +349 -134
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +459 -85
- package/src/server/cookie-parse.ts +32 -0
- package/src/server/cookie-store.ts +310 -0
- package/src/server/fetchable-loader-store.ts +11 -6
- package/src/server/handle-store.ts +123 -42
- package/src/server/loader-registry.ts +51 -100
- package/src/server/request-context.ts +848 -157
- package/src/server.ts +15 -8
- package/src/ssr/index.tsx +443 -135
- package/src/ssr/ssr-root.tsx +228 -0
- package/src/static-handler.ts +45 -18
- package/src/testing/cache-status.ts +162 -0
- package/src/testing/collect-handle.ts +46 -0
- package/src/testing/dispatch.ts +701 -0
- package/src/testing/dom.entry.ts +22 -0
- package/src/testing/e2e/fixture.ts +188 -0
- package/src/testing/e2e/index.ts +128 -0
- package/src/testing/e2e/matchers.ts +35 -0
- package/src/testing/e2e/page-helpers.ts +272 -0
- package/src/testing/e2e/parity.ts +387 -0
- package/src/testing/e2e/server.ts +195 -0
- package/src/testing/flight-matchers.ts +97 -0
- package/src/testing/flight-normalize.ts +11 -0
- package/src/testing/flight-runtime.d.ts +57 -0
- package/src/testing/flight-tree.ts +682 -0
- package/src/testing/flight.entry.ts +52 -0
- package/src/testing/flight.ts +257 -0
- package/src/testing/generated-routes.ts +199 -0
- package/src/testing/index.ts +105 -0
- package/src/testing/internal/context.ts +371 -0
- package/src/testing/internal/flight-client-globals.ts +30 -0
- package/src/testing/internal/seed-vars.ts +54 -0
- package/src/testing/render-handler.ts +357 -0
- package/src/testing/render-route.tsx +584 -0
- package/src/testing/run-loader.ts +385 -0
- package/src/testing/run-middleware.ts +205 -0
- package/src/testing/run-transition-when.ts +164 -0
- package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
- package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
- package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
- package/src/testing/vitest-stubs/version.ts +5 -0
- package/src/testing/vitest.ts +305 -0
- package/src/theme/ThemeProvider.tsx +76 -98
- package/src/theme/ThemeScript.tsx +12 -14
- package/src/theme/constants.ts +57 -15
- package/src/theme/index.ts +3 -20
- package/src/theme/theme-context.ts +5 -35
- package/src/theme/theme-script.ts +43 -39
- package/src/theme/use-theme.ts +0 -3
- package/src/types/boundaries.ts +123 -0
- package/src/types/cache-types.ts +207 -0
- package/src/types/error-types.ts +132 -0
- package/src/types/global-namespace.ts +113 -0
- package/src/types/handler-context.ts +839 -0
- package/src/types/index.ts +81 -0
- package/src/types/loader-types.ts +212 -0
- package/src/types/request-scope.ts +112 -0
- package/src/types/route-config.ts +138 -0
- package/src/types/route-entry.ts +114 -0
- package/src/types/segments.ts +271 -0
- package/src/types.ts +1 -1795
- package/src/urls/include-helper.ts +162 -0
- package/src/urls/include-provider.ts +71 -0
- package/src/urls/index.ts +44 -0
- package/src/urls/path-helper-types.ts +413 -0
- package/src/urls/path-helper.ts +280 -0
- package/src/urls/pattern-types.ts +160 -0
- package/src/urls/response-types.ts +109 -0
- package/src/urls/type-extraction.ts +316 -0
- package/src/urls/urls-function.ts +80 -0
- package/src/urls.ts +1 -1341
- package/src/use-loader.tsx +406 -141
- package/src/vercel/index.ts +11 -0
- package/src/vercel/tracing.ts +88 -0
- package/src/vite/debug.ts +185 -0
- package/src/vite/discovery/bundle-postprocess.ts +182 -0
- package/src/vite/discovery/discover-routers.ts +389 -0
- package/src/vite/discovery/discovery-errors.ts +255 -0
- package/src/vite/discovery/gate-state.ts +171 -0
- package/src/vite/discovery/prerender-collection.ts +467 -0
- package/src/vite/discovery/route-types-writer.ts +214 -0
- package/src/vite/discovery/self-gen-tracking.ts +73 -0
- package/src/vite/discovery/state.ts +161 -0
- package/src/vite/discovery/virtual-module-codegen.ts +183 -0
- package/src/vite/index.ts +23 -2255
- package/src/vite/inject-client-debug.ts +36 -0
- package/src/vite/plugin-types.ts +303 -0
- package/src/vite/plugins/cjs-to-esm.ts +90 -0
- package/src/vite/plugins/client-ref-dedup.ts +120 -0
- package/src/vite/plugins/client-ref-hashing.ts +118 -0
- package/src/vite/plugins/cloudflare-protocol-loader-hook.d.mts +23 -0
- package/src/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/src/vite/plugins/cloudflare-protocol-stub.ts +194 -0
- package/src/vite/{expose-action-id.ts → plugins/expose-action-id.ts} +88 -110
- package/src/vite/{expose-id-utils.ts → plugins/expose-id-utils.ts} +89 -79
- package/src/vite/plugins/expose-ids/export-analysis.ts +363 -0
- package/src/vite/plugins/expose-ids/handler-transform.ts +130 -0
- package/src/vite/plugins/expose-ids/loader-transform.ts +64 -0
- package/src/vite/plugins/expose-ids/router-transform.ts +199 -0
- package/src/vite/plugins/expose-ids/types.ts +45 -0
- package/src/vite/plugins/expose-internal-ids.ts +805 -0
- package/src/vite/plugins/performance-tracks.ts +89 -0
- package/src/vite/plugins/refresh-cmd.ts +127 -0
- package/src/vite/plugins/use-cache-transform.ts +313 -0
- package/src/vite/plugins/vercel-output.ts +384 -0
- package/src/vite/plugins/version-injector.ts +94 -0
- package/src/vite/plugins/version-plugin.ts +263 -0
- package/src/vite/plugins/virtual-entries.ts +234 -0
- package/src/vite/plugins/virtual-stub-plugin.ts +29 -0
- package/src/vite/rango.ts +560 -0
- package/src/vite/router-discovery.ts +1638 -0
- package/src/vite/{ast-handler-extract.ts → utils/ast-handler-extract.ts} +200 -37
- package/src/vite/utils/banner.ts +36 -0
- package/src/vite/utils/bundle-analysis.ts +132 -0
- 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 +15 -0
- package/src/vite/utils/package-resolution.ts +89 -0
- package/src/vite/utils/prerender-utils.ts +249 -0
- package/src/vite/utils/shared-utils.ts +269 -0
- package/CLAUDE.md +0 -43
- package/dist/vite/index.named-routes.gen.ts +0 -103
- package/src/browser/lru-cache.ts +0 -69
- package/src/browser/react/use-client-cache.ts +0 -56
- package/src/browser/request-controller.ts +0 -164
- package/src/browser/shallow.ts +0 -35
- package/src/cache/memory-store.ts +0 -253
- package/src/handles/index.ts +0 -6
- package/src/href-context.ts +0 -33
- package/src/network-error-thrower.tsx +0 -21
- package/src/router.gen.ts +0 -6
- package/src/static-handler.gen.ts +0 -5
- package/src/urls.gen.ts +0 -8
- package/src/vite/expose-internal-ids.ts +0 -1167
- package/src/vite/package-resolution.ts +0 -125
- package/src/vite/virtual-entries.ts +0 -114
- /package/src/vite/{version.d.ts → plugins/version.d.ts} +0 -0
|
@@ -101,10 +101,14 @@
|
|
|
101
101
|
* - Non-GET request (only GET requests are cacheable)
|
|
102
102
|
*/
|
|
103
103
|
import type { ResolvedSegment } from "../../types.js";
|
|
104
|
-
import {
|
|
104
|
+
import {
|
|
105
|
+
getRequestContext,
|
|
106
|
+
runWithRequestContext,
|
|
107
|
+
} from "../../server/request-context.js";
|
|
105
108
|
import type { MatchContext, MatchPipelineState } from "../match-context.js";
|
|
106
109
|
import { getRouterContext } from "../router-context.js";
|
|
107
|
-
import { debugLog, debugWarn } from "../logging.js";
|
|
110
|
+
import { debugLog, debugWarn, getOrCreateRequestId } from "../logging.js";
|
|
111
|
+
import { INTERNAL_RANGO_DEBUG } from "../../internal-debug.js";
|
|
108
112
|
import type { GeneratorMiddleware } from "./cache-lookup.js";
|
|
109
113
|
|
|
110
114
|
/**
|
|
@@ -120,21 +124,16 @@ export function withCacheStore<TEnv>(
|
|
|
120
124
|
return async function* (
|
|
121
125
|
source: AsyncGenerator<ResolvedSegment>,
|
|
122
126
|
): AsyncGenerator<ResolvedSegment> {
|
|
123
|
-
const pipelineStart = performance.now();
|
|
124
127
|
const ms = ctx.metricsStore;
|
|
125
128
|
|
|
126
|
-
// Collect all segments while passing them through
|
|
127
129
|
const allSegments: ResolvedSegment[] = [];
|
|
128
130
|
for await (const segment of source) {
|
|
129
131
|
allSegments.push(segment);
|
|
130
132
|
yield segment;
|
|
131
133
|
}
|
|
132
134
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
// 2. This is an action (actions don't cache)
|
|
136
|
-
// 3. Cache was already hit (no need to re-cache)
|
|
137
|
-
// 4. Non-GET request (only cache GET requests)
|
|
135
|
+
const ownStart = performance.now();
|
|
136
|
+
|
|
138
137
|
if (
|
|
139
138
|
!ctx.cacheScope?.enabled ||
|
|
140
139
|
ctx.isAction ||
|
|
@@ -142,25 +141,39 @@ export function withCacheStore<TEnv>(
|
|
|
142
141
|
ctx.request.method !== "GET"
|
|
143
142
|
) {
|
|
144
143
|
if (ms) {
|
|
145
|
-
ms.metrics.push({
|
|
144
|
+
ms.metrics.push({
|
|
145
|
+
label: "pipeline:cache-store",
|
|
146
|
+
duration: performance.now() - ownStart,
|
|
147
|
+
startTime: ownStart - ms.requestStart,
|
|
148
|
+
});
|
|
146
149
|
}
|
|
147
150
|
return;
|
|
148
151
|
}
|
|
149
152
|
|
|
150
153
|
const {
|
|
151
154
|
createHandlerContext,
|
|
152
|
-
|
|
155
|
+
setupLoaderAccess,
|
|
153
156
|
resolveAllSegments,
|
|
154
157
|
resolveInterceptEntry,
|
|
158
|
+
createHandleStore,
|
|
155
159
|
} = getRouterContext<TEnv>();
|
|
156
160
|
|
|
157
|
-
//
|
|
158
|
-
|
|
161
|
+
// On a fresh intercept miss the intercept slot segments flow through
|
|
162
|
+
// `source` into allSegments AND are also recorded on state.interceptSegments.
|
|
163
|
+
// Dedup by id so each segment is cached once — cacheRoute serializes the
|
|
164
|
+
// array verbatim (no id-dedup), so an un-deduped append doubles the intercept
|
|
165
|
+
// segment in the cached entry, re-rendering the slot twice on the next hit.
|
|
166
|
+
const seenSegmentIds = new Set(allSegments.map((s) => s.id));
|
|
167
|
+
const allSegmentsToCache = [
|
|
168
|
+
...allSegments,
|
|
169
|
+
...state.interceptSegments.filter((s) => !seenSegmentIds.has(s.id)),
|
|
170
|
+
];
|
|
159
171
|
|
|
160
|
-
// Check if any non-loader segments have null components
|
|
161
|
-
// This happens when client already had those segments (partial navigation)
|
|
162
172
|
const hasNullComponents = allSegmentsToCache.some(
|
|
163
|
-
(s) =>
|
|
173
|
+
(s) =>
|
|
174
|
+
s.component === null &&
|
|
175
|
+
s.type !== "loader" &&
|
|
176
|
+
ctx.clientSegmentSet.has(s.id),
|
|
164
177
|
);
|
|
165
178
|
|
|
166
179
|
const requestCtx = getRequestContext();
|
|
@@ -168,10 +181,22 @@ export function withCacheStore<TEnv>(
|
|
|
168
181
|
|
|
169
182
|
const cacheScope = ctx.cacheScope;
|
|
170
183
|
|
|
171
|
-
//
|
|
172
|
-
//
|
|
184
|
+
// Record the route's segment-DSL cache tags into the request tag union NOW,
|
|
185
|
+
// synchronously in the pipeline. The actual store write (cacheRoute) runs in
|
|
186
|
+
// requestCtx.waitUntil() below — and the proactive path re-resolves the whole
|
|
187
|
+
// tree first — so cacheRoute's own tag recording races the document cache's
|
|
188
|
+
// post-body-drain snapshot of _requestTags. On a first-write miss the document
|
|
189
|
+
// tag union could miss these tags and revalidateTag()/updateTag() would not
|
|
190
|
+
// invalidate the cached document. Recording here (before the snapshot) closes
|
|
191
|
+
// the window for both the direct and proactive write paths; the duplicate
|
|
192
|
+
// record inside cacheRoute is idempotent.
|
|
193
|
+
cacheScope.recordTags(requestCtx);
|
|
194
|
+
|
|
195
|
+
const reqId = INTERNAL_RANGO_DEBUG
|
|
196
|
+
? getOrCreateRequestId(ctx.request)
|
|
197
|
+
: undefined;
|
|
198
|
+
|
|
173
199
|
requestCtx.onResponse((response) => {
|
|
174
|
-
// Only cache successful responses
|
|
175
200
|
if (response.status !== 200) {
|
|
176
201
|
debugLog("cacheStore", "skipping cache for non-200 response", {
|
|
177
202
|
status: response.status,
|
|
@@ -181,57 +206,74 @@ export function withCacheStore<TEnv>(
|
|
|
181
206
|
}
|
|
182
207
|
|
|
183
208
|
if (hasNullComponents) {
|
|
184
|
-
// Proactive caching: render all segments fresh in background
|
|
185
|
-
// This ensures cache has complete components for future requests
|
|
186
209
|
requestCtx.waitUntil(async () => {
|
|
210
|
+
const savedMetrics = ctx.Store.metrics;
|
|
211
|
+
ctx.Store.metrics = undefined;
|
|
212
|
+
|
|
213
|
+
const start = performance.now();
|
|
187
214
|
debugLog("cacheStore", "proactive caching started", {
|
|
188
215
|
pathname: ctx.pathname,
|
|
189
216
|
});
|
|
217
|
+
const originalHandleStore = requestCtx._handleStore;
|
|
218
|
+
requestCtx._handleStore = createHandleStore();
|
|
190
219
|
try {
|
|
191
|
-
// Create fresh context for proactive caching
|
|
192
|
-
// This prevents handle data from polluting the response stream
|
|
193
220
|
const proactiveHandlerContext = createHandlerContext(
|
|
194
221
|
ctx.matched.params,
|
|
195
222
|
ctx.request,
|
|
196
223
|
ctx.url.searchParams,
|
|
197
224
|
ctx.pathname,
|
|
198
225
|
ctx.url,
|
|
199
|
-
ctx.
|
|
226
|
+
ctx.env,
|
|
200
227
|
ctx.routeMap,
|
|
201
|
-
ctx.matched.routeKey
|
|
228
|
+
ctx.matched.routeKey,
|
|
229
|
+
ctx.matched.responseType,
|
|
230
|
+
ctx.matched.pt === true,
|
|
202
231
|
);
|
|
203
232
|
const proactiveLoaderPromises = new Map<string, Promise<any>>();
|
|
204
233
|
|
|
205
|
-
|
|
206
|
-
setupLoaderAccessSilent(
|
|
207
|
-
proactiveHandlerContext,
|
|
208
|
-
proactiveLoaderPromises,
|
|
209
|
-
);
|
|
234
|
+
setupLoaderAccess(proactiveHandlerContext, proactiveLoaderPromises);
|
|
210
235
|
|
|
211
|
-
// Re-resolve ALL segments without revalidation
|
|
212
236
|
const Store = ctx.Store;
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
237
|
+
// Re-establish the request-context ALS around the re-render. Store
|
|
238
|
+
// is a different ALS (DSL build context); on workerd a waitUntil
|
|
239
|
+
// task runs detached from the request's I/O context, so a handler/
|
|
240
|
+
// component that reads the ambient getRequestContext() during this
|
|
241
|
+
// background re-render would otherwise throw "called outside of a
|
|
242
|
+
// request context".
|
|
243
|
+
const freshSegments = await runWithRequestContext(requestCtx, () =>
|
|
244
|
+
Store.run(() =>
|
|
245
|
+
resolveAllSegments(
|
|
246
|
+
ctx.entries,
|
|
247
|
+
ctx.routeKey,
|
|
248
|
+
ctx.matched.params,
|
|
249
|
+
proactiveHandlerContext,
|
|
250
|
+
proactiveLoaderPromises,
|
|
251
|
+
{ skipLoaders: true },
|
|
252
|
+
),
|
|
220
253
|
),
|
|
221
254
|
);
|
|
222
255
|
|
|
223
|
-
// Also resolve intercept segments fresh if applicable
|
|
224
256
|
let freshInterceptSegments: ResolvedSegment[] = [];
|
|
225
257
|
if (ctx.interceptResult) {
|
|
226
|
-
freshInterceptSegments = await
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
258
|
+
freshInterceptSegments = await runWithRequestContext(
|
|
259
|
+
requestCtx,
|
|
260
|
+
() =>
|
|
261
|
+
Store.run(() =>
|
|
262
|
+
resolveInterceptEntry(
|
|
263
|
+
ctx.interceptResult!.intercept,
|
|
264
|
+
ctx.interceptResult!.entry,
|
|
265
|
+
ctx.matched.params,
|
|
266
|
+
proactiveHandlerContext,
|
|
267
|
+
true, // belongsToRoute
|
|
268
|
+
// No revalidationContext = render fresh
|
|
269
|
+
undefined,
|
|
270
|
+
// Skip intercept middleware: the foreground already ran it
|
|
271
|
+
// before the response was sent. Re-running here (post-
|
|
272
|
+
// response, background) would fire side effects twice and a
|
|
273
|
+
// short-circuit Response would silently abort this write.
|
|
274
|
+
{ skipMiddleware: true },
|
|
275
|
+
),
|
|
276
|
+
),
|
|
235
277
|
);
|
|
236
278
|
}
|
|
237
279
|
|
|
@@ -239,32 +281,58 @@ export function withCacheStore<TEnv>(
|
|
|
239
281
|
...freshSegments,
|
|
240
282
|
...freshInterceptSegments,
|
|
241
283
|
];
|
|
284
|
+
requestCtx._handleStore.seal();
|
|
242
285
|
await cacheScope.cacheRoute(
|
|
243
286
|
ctx.pathname,
|
|
244
287
|
ctx.matched.params,
|
|
245
288
|
completeSegments,
|
|
246
289
|
ctx.isIntercept,
|
|
247
290
|
);
|
|
291
|
+
if (INTERNAL_RANGO_DEBUG) {
|
|
292
|
+
const dur = performance.now() - start;
|
|
293
|
+
console.log(
|
|
294
|
+
`[RSC Background][req:${reqId}] Proactive cache ${ctx.pathname} (${dur.toFixed(2)}ms) segments=${completeSegments.length}`,
|
|
295
|
+
);
|
|
296
|
+
}
|
|
248
297
|
debugLog("cacheStore", "proactive caching complete", {
|
|
249
298
|
pathname: ctx.pathname,
|
|
250
299
|
});
|
|
251
300
|
} catch (error) {
|
|
301
|
+
if (INTERNAL_RANGO_DEBUG) {
|
|
302
|
+
const dur = performance.now() - start;
|
|
303
|
+
console.log(
|
|
304
|
+
`[RSC Background][req:${reqId}] Proactive cache ${ctx.pathname} FAILED (${dur.toFixed(2)}ms) error=${String(error)}`,
|
|
305
|
+
);
|
|
306
|
+
}
|
|
252
307
|
debugWarn("cacheStore", "proactive caching failed", {
|
|
253
308
|
pathname: ctx.pathname,
|
|
254
309
|
error: String(error),
|
|
255
310
|
});
|
|
311
|
+
} finally {
|
|
312
|
+
requestCtx._handleStore = originalHandleStore;
|
|
313
|
+
ctx.Store.metrics = savedMetrics;
|
|
256
314
|
}
|
|
257
315
|
});
|
|
258
316
|
} else {
|
|
259
|
-
|
|
260
|
-
|
|
317
|
+
if (INTERNAL_RANGO_DEBUG) {
|
|
318
|
+
console.log(
|
|
319
|
+
`[RSC CacheStore][req:${reqId}] Direct cache path: scheduling cacheRoute for ${ctx.pathname} (${allSegmentsToCache.length} segments, hasNullComponents=${hasNullComponents})`,
|
|
320
|
+
);
|
|
321
|
+
}
|
|
261
322
|
requestCtx.waitUntil(async () => {
|
|
323
|
+
const start = performance.now();
|
|
262
324
|
await cacheScope.cacheRoute(
|
|
263
325
|
ctx.pathname,
|
|
264
326
|
ctx.matched.params,
|
|
265
327
|
allSegmentsToCache,
|
|
266
328
|
ctx.isIntercept,
|
|
267
329
|
);
|
|
330
|
+
if (INTERNAL_RANGO_DEBUG) {
|
|
331
|
+
const dur = performance.now() - start;
|
|
332
|
+
console.log(
|
|
333
|
+
`[RSC Background][req:${reqId}] Cache store ${ctx.pathname} (${dur.toFixed(2)}ms) segments=${allSegmentsToCache.length}`,
|
|
334
|
+
);
|
|
335
|
+
}
|
|
268
336
|
});
|
|
269
337
|
}
|
|
270
338
|
|
|
@@ -272,7 +340,11 @@ export function withCacheStore<TEnv>(
|
|
|
272
340
|
});
|
|
273
341
|
|
|
274
342
|
if (ms) {
|
|
275
|
-
ms.metrics.push({
|
|
343
|
+
ms.metrics.push({
|
|
344
|
+
label: "pipeline:cache-store",
|
|
345
|
+
duration: performance.now() - ownStart,
|
|
346
|
+
startTime: ownStart - ms.requestStart,
|
|
347
|
+
});
|
|
276
348
|
}
|
|
277
349
|
};
|
|
278
350
|
}
|
|
@@ -118,51 +118,51 @@ import { debugLog } from "../logging.js";
|
|
|
118
118
|
*/
|
|
119
119
|
export function withInterceptResolution<TEnv>(
|
|
120
120
|
ctx: MatchContext<TEnv>,
|
|
121
|
-
state: MatchPipelineState
|
|
121
|
+
state: MatchPipelineState,
|
|
122
122
|
): GeneratorMiddleware<ResolvedSegment> {
|
|
123
123
|
return async function* (
|
|
124
|
-
source: AsyncGenerator<ResolvedSegment
|
|
124
|
+
source: AsyncGenerator<ResolvedSegment>,
|
|
125
125
|
): AsyncGenerator<ResolvedSegment> {
|
|
126
|
-
const pipelineStart = performance.now();
|
|
127
126
|
const ms = ctx.metricsStore;
|
|
128
127
|
|
|
129
|
-
// First, yield all segments from the source (main segment resolution or cache)
|
|
130
128
|
const segments: ResolvedSegment[] = [];
|
|
131
129
|
for await (const segment of source) {
|
|
132
130
|
segments.push(segment);
|
|
133
131
|
yield segment;
|
|
134
132
|
}
|
|
135
133
|
|
|
136
|
-
|
|
134
|
+
const ownStart = performance.now();
|
|
135
|
+
|
|
137
136
|
if (ctx.isFullMatch) {
|
|
138
137
|
if (ms) {
|
|
139
|
-
ms.metrics.push({
|
|
138
|
+
ms.metrics.push({
|
|
139
|
+
label: "pipeline:intercept",
|
|
140
|
+
duration: performance.now() - ownStart,
|
|
141
|
+
startTime: ownStart - ms.requestStart,
|
|
142
|
+
});
|
|
140
143
|
}
|
|
141
144
|
return;
|
|
142
145
|
}
|
|
143
146
|
|
|
144
|
-
// Skip intercept resolution if:
|
|
145
|
-
// 1. No intercept result
|
|
146
|
-
// 2. Already have intercept segments (from cache hit with intercept key)
|
|
147
|
-
// 3. Cache hit with intercept key
|
|
148
147
|
const skipInterceptResolution =
|
|
149
148
|
!ctx.interceptResult ||
|
|
150
149
|
state.interceptSegments.length > 0 ||
|
|
151
150
|
(state.cacheHit && ctx.isIntercept);
|
|
152
151
|
|
|
153
152
|
if (skipInterceptResolution) {
|
|
154
|
-
// For cache hit with intercept, extract intercept segments from cached data for slots
|
|
155
|
-
// and re-resolve loaders for fresh data
|
|
156
153
|
if (ctx.interceptResult && state.cacheHit && ctx.isIntercept) {
|
|
157
154
|
await handleCacheHitIntercept(ctx, state, segments);
|
|
158
155
|
}
|
|
159
156
|
if (ms) {
|
|
160
|
-
ms.metrics.push({
|
|
157
|
+
ms.metrics.push({
|
|
158
|
+
label: "pipeline:intercept",
|
|
159
|
+
duration: performance.now() - ownStart,
|
|
160
|
+
startTime: ownStart - ms.requestStart,
|
|
161
|
+
});
|
|
161
162
|
}
|
|
162
163
|
return;
|
|
163
164
|
}
|
|
164
165
|
|
|
165
|
-
// Resolve intercept segments
|
|
166
166
|
const { resolveInterceptEntry } = getRouterContext<TEnv>();
|
|
167
167
|
|
|
168
168
|
const slotName = ctx.interceptResult!.intercept.slotName;
|
|
@@ -171,7 +171,6 @@ export function withInterceptResolution<TEnv>(
|
|
|
171
171
|
slotName,
|
|
172
172
|
});
|
|
173
173
|
|
|
174
|
-
// Resolve intercept entry (middleware, loaders, handler)
|
|
175
174
|
const Store = ctx.Store;
|
|
176
175
|
const interceptSegments = await Store.run(() =>
|
|
177
176
|
resolveInterceptEntry(
|
|
@@ -189,37 +188,34 @@ export function withInterceptResolution<TEnv>(
|
|
|
189
188
|
routeKey: ctx.routeKey,
|
|
190
189
|
actionContext: ctx.actionContext,
|
|
191
190
|
stale: ctx.stale,
|
|
192
|
-
}
|
|
193
|
-
)
|
|
191
|
+
},
|
|
192
|
+
),
|
|
194
193
|
);
|
|
195
194
|
|
|
196
|
-
// Update state
|
|
197
195
|
state.interceptSegments = interceptSegments;
|
|
198
196
|
state.slots[slotName] = {
|
|
199
197
|
active: true,
|
|
200
198
|
segments: interceptSegments,
|
|
201
199
|
};
|
|
202
200
|
|
|
203
|
-
// Yield intercept segments
|
|
204
201
|
for (const segment of interceptSegments) {
|
|
205
202
|
yield segment;
|
|
206
203
|
}
|
|
207
204
|
|
|
208
205
|
if (ms) {
|
|
209
|
-
ms.metrics.push({
|
|
206
|
+
ms.metrics.push({
|
|
207
|
+
label: "pipeline:intercept",
|
|
208
|
+
duration: performance.now() - ownStart,
|
|
209
|
+
startTime: ownStart - ms.requestStart,
|
|
210
|
+
});
|
|
210
211
|
}
|
|
211
212
|
};
|
|
212
213
|
}
|
|
213
214
|
|
|
214
|
-
/**
|
|
215
|
-
* Handle cache hit with intercept scenario
|
|
216
|
-
*
|
|
217
|
-
* Extract intercept segments from cached data and re-resolve loaders for fresh data.
|
|
218
|
-
*/
|
|
219
215
|
async function handleCacheHitIntercept<TEnv>(
|
|
220
216
|
ctx: MatchContext<TEnv>,
|
|
221
217
|
state: MatchPipelineState,
|
|
222
|
-
segments: ResolvedSegment[]
|
|
218
|
+
segments: ResolvedSegment[],
|
|
223
219
|
): Promise<void> {
|
|
224
220
|
if (!ctx.interceptResult) return;
|
|
225
221
|
|
|
@@ -227,14 +223,11 @@ async function handleCacheHitIntercept<TEnv>(
|
|
|
227
223
|
|
|
228
224
|
const slotName = ctx.interceptResult.intercept.slotName;
|
|
229
225
|
|
|
230
|
-
// Find intercept segments from cached segments (namespace starts with "intercept:")
|
|
231
226
|
const interceptSegments = segments.filter((s) =>
|
|
232
|
-
s.namespace?.startsWith("intercept:")
|
|
227
|
+
s.namespace?.startsWith("intercept:"),
|
|
233
228
|
);
|
|
234
229
|
state.interceptSegments = interceptSegments;
|
|
235
230
|
|
|
236
|
-
// Re-resolve intercept loaders for fresh data on cache hit
|
|
237
|
-
// This keeps cached component/layout but fetches fresh loader data
|
|
238
231
|
if (resolveInterceptLoadersOnly) {
|
|
239
232
|
const Store = ctx.Store;
|
|
240
233
|
const freshLoaderResult = await Store.run(() =>
|
|
@@ -253,28 +246,36 @@ async function handleCacheHitIntercept<TEnv>(
|
|
|
253
246
|
routeKey: ctx.routeKey,
|
|
254
247
|
actionContext: ctx.actionContext,
|
|
255
248
|
stale: ctx.stale,
|
|
256
|
-
}
|
|
257
|
-
)
|
|
249
|
+
},
|
|
250
|
+
),
|
|
258
251
|
);
|
|
259
252
|
|
|
260
|
-
// Update intercept segment's loaderDataPromise with fresh data
|
|
261
253
|
if (freshLoaderResult) {
|
|
262
254
|
const interceptMainSegment = interceptSegments.find(
|
|
263
|
-
(s) => s.type === "parallel" && s.slot
|
|
255
|
+
(s) => s.type === "parallel" && s.slot,
|
|
264
256
|
);
|
|
265
257
|
if (interceptMainSegment) {
|
|
266
|
-
interceptMainSegment.loaderDataPromise =
|
|
258
|
+
interceptMainSegment.loaderDataPromise =
|
|
259
|
+
freshLoaderResult.loaderDataPromise;
|
|
267
260
|
interceptMainSegment.loaderIds = freshLoaderResult.loaderIds;
|
|
268
|
-
debugLog(
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
261
|
+
debugLog(
|
|
262
|
+
"matchPartial.intercept",
|
|
263
|
+
"cache hit with fresh intercept loaders",
|
|
264
|
+
{
|
|
265
|
+
routeName: ctx.localRouteName,
|
|
266
|
+
slotName,
|
|
267
|
+
},
|
|
268
|
+
);
|
|
272
269
|
}
|
|
273
270
|
} else {
|
|
274
|
-
debugLog(
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
271
|
+
debugLog(
|
|
272
|
+
"matchPartial.intercept",
|
|
273
|
+
"cache hit without intercept loader revalidation",
|
|
274
|
+
{
|
|
275
|
+
routeName: ctx.localRouteName,
|
|
276
|
+
slotName,
|
|
277
|
+
},
|
|
278
|
+
);
|
|
278
279
|
}
|
|
279
280
|
}
|
|
280
281
|
|
|
@@ -87,62 +87,96 @@
|
|
|
87
87
|
* if (state.cacheHit) return; // Now we can check
|
|
88
88
|
*/
|
|
89
89
|
import type { ResolvedSegment } from "../../types.js";
|
|
90
|
+
import type { EntryData } from "../../server/context.js";
|
|
91
|
+
import { _getRequestContext } from "../../server/request-context.js";
|
|
90
92
|
import type { MatchContext, MatchPipelineState } from "../match-context.js";
|
|
91
93
|
import { getRouterContext } from "../router-context.js";
|
|
92
94
|
import type { GeneratorMiddleware } from "./cache-lookup.js";
|
|
93
95
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
96
|
+
export function treeHasStreaming(entries: EntryData[]): boolean {
|
|
97
|
+
for (const entry of entries) {
|
|
98
|
+
if (
|
|
99
|
+
"loading" in entry &&
|
|
100
|
+
entry.loading !== undefined &&
|
|
101
|
+
entry.loading !== false
|
|
102
|
+
)
|
|
103
|
+
return true;
|
|
104
|
+
if (entry.layout) {
|
|
105
|
+
if (treeHasStreaming(entry.layout)) return true;
|
|
106
|
+
}
|
|
107
|
+
if (entry.parallel) {
|
|
108
|
+
for (const key in entry.parallel) {
|
|
109
|
+
const parallelEntry = entry.parallel[key as `@${string}`];
|
|
110
|
+
if (parallelEntry) {
|
|
111
|
+
if (
|
|
112
|
+
"loading" in parallelEntry &&
|
|
113
|
+
parallelEntry.loading !== undefined &&
|
|
114
|
+
parallelEntry.loading !== false
|
|
115
|
+
)
|
|
116
|
+
return true;
|
|
117
|
+
if (parallelEntry.layout) {
|
|
118
|
+
if (treeHasStreaming(parallelEntry.layout)) return true;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
|
|
100
127
|
export function withSegmentResolution<TEnv>(
|
|
101
128
|
ctx: MatchContext<TEnv>,
|
|
102
|
-
state: MatchPipelineState
|
|
129
|
+
state: MatchPipelineState,
|
|
103
130
|
): GeneratorMiddleware<ResolvedSegment> {
|
|
104
131
|
return async function* (
|
|
105
|
-
source: AsyncGenerator<ResolvedSegment
|
|
132
|
+
source: AsyncGenerator<ResolvedSegment>,
|
|
106
133
|
): AsyncGenerator<ResolvedSegment> {
|
|
107
|
-
const pipelineStart = performance.now();
|
|
108
134
|
const ms = ctx.metricsStore;
|
|
109
135
|
|
|
110
|
-
// IMPORTANT: Always iterate source first to give cache-lookup a chance
|
|
111
|
-
// to run and set state.cacheHit. Without this, cache-lookup never executes!
|
|
112
136
|
for await (const segment of source) {
|
|
113
137
|
yield segment;
|
|
114
138
|
}
|
|
115
139
|
|
|
116
|
-
|
|
140
|
+
const ownStart = performance.now();
|
|
141
|
+
|
|
117
142
|
if (state.cacheHit) {
|
|
118
143
|
if (ms) {
|
|
119
|
-
ms.metrics.push({
|
|
144
|
+
ms.metrics.push({
|
|
145
|
+
label: "pipeline:segment-resolve",
|
|
146
|
+
duration: performance.now() - ownStart,
|
|
147
|
+
startTime: ownStart - ms.requestStart,
|
|
148
|
+
});
|
|
120
149
|
}
|
|
121
150
|
return;
|
|
122
151
|
}
|
|
123
152
|
|
|
153
|
+
const reqCtx = _getRequestContext();
|
|
154
|
+
if (reqCtx && reqCtx._treeHasStreaming === undefined) {
|
|
155
|
+
reqCtx._treeHasStreaming = treeHasStreaming(ctx.entries);
|
|
156
|
+
}
|
|
157
|
+
|
|
124
158
|
const { resolveAllSegmentsWithRevalidation, resolveAllSegments } =
|
|
125
159
|
getRouterContext<TEnv>();
|
|
126
160
|
|
|
127
161
|
const Store = ctx.Store;
|
|
128
162
|
|
|
129
163
|
if (ctx.isFullMatch) {
|
|
130
|
-
// Full match (document request) - simple resolution without revalidation
|
|
131
164
|
const segments = await Store.run(() =>
|
|
132
165
|
resolveAllSegments(
|
|
133
166
|
ctx.entries,
|
|
134
167
|
ctx.routeKey,
|
|
135
168
|
ctx.matched.params,
|
|
136
169
|
ctx.handlerContext,
|
|
137
|
-
ctx.loaderPromises
|
|
138
|
-
)
|
|
170
|
+
ctx.loaderPromises,
|
|
171
|
+
),
|
|
139
172
|
);
|
|
140
173
|
|
|
141
|
-
// Update state with resolved segments
|
|
142
174
|
state.segments = segments;
|
|
143
175
|
state.matchedIds = segments.map((s: { id: string }) => s.id);
|
|
144
176
|
|
|
145
|
-
|
|
177
|
+
if (reqCtx) {
|
|
178
|
+
reqCtx._resolveRenderBarrier(segments);
|
|
179
|
+
}
|
|
146
180
|
for (const segment of segments) {
|
|
147
181
|
yield segment;
|
|
148
182
|
}
|
|
@@ -159,18 +193,22 @@ export function withSegmentResolution<TEnv>(
|
|
|
159
193
|
ctx.request,
|
|
160
194
|
ctx.prevUrl,
|
|
161
195
|
ctx.url,
|
|
162
|
-
ctx.loaderPromises,
|
|
163
196
|
ctx.actionContext,
|
|
164
197
|
ctx.interceptResult,
|
|
165
198
|
ctx.localRouteName,
|
|
166
|
-
ctx.pathname
|
|
167
|
-
|
|
199
|
+
ctx.pathname,
|
|
200
|
+
ctx.stale,
|
|
201
|
+
),
|
|
168
202
|
);
|
|
169
203
|
|
|
170
204
|
// Update state with resolved segments
|
|
171
205
|
state.segments = result.segments;
|
|
172
206
|
state.matchedIds = result.matchedIds;
|
|
173
207
|
|
|
208
|
+
if (reqCtx) {
|
|
209
|
+
reqCtx._resolveRenderBarrier(result.segments);
|
|
210
|
+
}
|
|
211
|
+
|
|
174
212
|
// Yield all resolved segments
|
|
175
213
|
for (const segment of result.segments) {
|
|
176
214
|
yield segment;
|
|
@@ -178,7 +216,11 @@ export function withSegmentResolution<TEnv>(
|
|
|
178
216
|
}
|
|
179
217
|
|
|
180
218
|
if (ms) {
|
|
181
|
-
ms.metrics.push({
|
|
219
|
+
ms.metrics.push({
|
|
220
|
+
label: "pipeline:segment-resolve",
|
|
221
|
+
duration: performance.now() - ownStart,
|
|
222
|
+
startTime: ownStart - ms.requestStart,
|
|
223
|
+
});
|
|
182
224
|
}
|
|
183
225
|
};
|
|
184
226
|
}
|