@rangojs/router 0.0.0-experimental.bd6e11bc → 0.0.0-experimental.bdaf10aa
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +8 -4
- package/README.md +296 -887
- package/dist/bin/rango.js +459 -91
- package/dist/testing/vitest.js +36 -2
- package/dist/vite/index.js +1708 -414
- package/package.json +35 -10
- package/skills/api-client/SKILL.md +211 -0
- package/skills/breadcrumbs/SKILL.md +82 -5
- package/skills/bundle-analysis/SKILL.md +2 -2
- package/skills/cache-guide/SKILL.md +14 -9
- package/skills/caching/SKILL.md +221 -12
- package/skills/catalog.json +271 -0
- package/skills/comparison/SKILL.md +50 -0
- package/skills/comparison/agents/openai.yaml +4 -0
- package/skills/comparison/references/framework-comparison.md +837 -0
- package/skills/composability/SKILL.md +83 -2
- package/skills/css/SKILL.md +76 -0
- package/skills/debug-manifest/SKILL.md +5 -3
- package/skills/defer-hydration/SKILL.md +235 -0
- package/skills/document-cache/SKILL.md +11 -3
- package/skills/fonts/SKILL.md +1 -1
- package/skills/handler-use/SKILL.md +9 -9
- package/skills/hooks/SKILL.md +73 -900
- package/skills/hooks/data.md +273 -0
- package/skills/hooks/handle-and-actions.md +103 -0
- package/skills/hooks/navigation.md +110 -0
- package/skills/hooks/outlets.md +41 -0
- package/skills/hooks/state.md +228 -0
- package/skills/hooks/urls.md +135 -0
- package/skills/host-router/SKILL.md +84 -7
- package/skills/i18n/SKILL.md +1 -1
- package/skills/intercept/SKILL.md +51 -17
- package/skills/layout/SKILL.md +38 -16
- package/skills/links/SKILL.md +1 -1
- package/skills/loader/SKILL.md +48 -20
- package/skills/middleware/SKILL.md +11 -5
- package/skills/migrate-nextjs/SKILL.md +203 -20
- package/skills/migrate-react-router/SKILL.md +59 -675
- package/skills/migrate-react-router/cloudflare-workers.md +129 -0
- package/skills/migrate-react-router/component-migration.md +196 -0
- package/skills/migrate-react-router/data-and-actions.md +225 -0
- package/skills/migrate-react-router/route-mapping.md +271 -0
- package/skills/mime-routes/SKILL.md +3 -3
- package/skills/observability/SKILL.md +70 -5
- package/skills/parallel/SKILL.md +32 -8
- package/skills/ppr/SKILL.md +622 -0
- package/skills/prerender/SKILL.md +59 -28
- package/skills/rango/SKILL.md +124 -50
- package/skills/response-routes/SKILL.md +78 -46
- package/skills/route/SKILL.md +85 -6
- package/skills/router-setup/SKILL.md +41 -6
- package/skills/scripts/SKILL.md +179 -0
- package/skills/server-actions/SKILL.md +28 -3
- package/skills/shell-manifest/SKILL.md +185 -0
- package/skills/streams-and-websockets/SKILL.md +1 -1
- package/skills/tailwind/SKILL.md +28 -4
- package/skills/testing/SKILL.md +68 -654
- package/skills/testing/bindings.md +103 -0
- package/skills/testing/cache-prerender.md +127 -0
- package/skills/testing/client-components.md +124 -0
- package/skills/testing/e2e-parity.md +125 -0
- package/skills/testing/flight.md +91 -0
- package/skills/testing/handles.md +131 -0
- package/skills/testing/loader.md +128 -0
- package/skills/testing/middleware.md +99 -0
- package/skills/testing/render-handler.md +122 -0
- package/skills/testing/response-routes.md +95 -0
- package/skills/testing/reverse-and-types.md +85 -0
- package/skills/testing/server-actions.md +107 -0
- package/skills/testing/server-tree.md +128 -0
- package/skills/testing/setup.md +123 -0
- package/skills/theme/SKILL.md +1 -1
- package/skills/typesafety/SKILL.md +45 -918
- package/skills/typesafety/env-and-bindings.md +254 -0
- package/skills/typesafety/generated-files-and-cli.md +335 -0
- package/skills/typesafety/params-and-search.md +153 -0
- package/skills/typesafety/route-types.md +209 -0
- package/skills/use-cache/SKILL.md +47 -17
- package/skills/vercel/SKILL.md +128 -0
- package/skills/view-transitions/SKILL.md +44 -1
- package/src/__augment-tests__/augmented.check.ts +2 -3
- package/src/__internal.ts +0 -65
- package/src/browser/action-coordinator.ts +1 -1
- package/src/browser/action-fence.ts +47 -0
- package/src/browser/app-shell.ts +14 -27
- package/src/browser/connection-warmup.ts +134 -0
- package/src/browser/cookie-name.ts +140 -0
- package/src/browser/event-controller.ts +178 -100
- package/src/browser/invalidate-client-cache.ts +52 -0
- package/src/browser/logging.ts +28 -0
- package/src/browser/merge-segment-loaders.ts +6 -4
- package/src/browser/navigation-bridge.ts +81 -68
- package/src/browser/navigation-client.ts +115 -70
- package/src/browser/navigation-store-handle.ts +38 -0
- package/src/browser/navigation-store.ts +153 -88
- package/src/browser/navigation-transaction.ts +0 -32
- package/src/browser/network-error-handler.ts +34 -7
- package/src/browser/partial-update.ts +157 -144
- package/src/browser/prefetch/cache.ts +148 -81
- package/src/browser/prefetch/fetch.ts +231 -51
- package/src/browser/prefetch/queue.ts +25 -7
- package/src/browser/rango-state.ts +157 -115
- package/src/browser/react/Link.tsx +40 -7
- package/src/browser/react/NavigationProvider.tsx +140 -99
- package/src/browser/react/ScrollRestoration.tsx +10 -6
- package/src/browser/react/filter-segment-order.ts +17 -2
- package/src/browser/react/index.ts +0 -51
- package/src/browser/react/location-state-shared.ts +14 -15
- package/src/browser/react/location-state.ts +0 -1
- package/src/browser/react/use-action.ts +6 -15
- package/src/browser/react/use-handle.ts +0 -5
- package/src/browser/react/use-href.tsx +8 -1
- package/src/browser/react/use-link-status.ts +33 -8
- package/src/browser/react/use-navigation.ts +10 -5
- package/src/browser/react/use-params.ts +0 -2
- package/src/browser/react/use-router.ts +6 -4
- package/src/browser/react/use-search-params.ts +0 -5
- package/src/browser/react/use-segments.ts +0 -13
- package/src/browser/response-adapter.ts +74 -8
- package/src/browser/rsc-router.tsx +97 -22
- package/src/browser/scroll-restoration.ts +15 -8
- package/src/browser/segment-reconciler.ts +31 -21
- package/src/browser/server-action-bridge.ts +216 -38
- package/src/browser/types.ts +94 -22
- package/src/browser/validate-redirect-origin.ts +43 -16
- package/src/build/generate-manifest.ts +155 -131
- package/src/build/generate-route-types.ts +1 -1
- package/src/build/index.ts +11 -5
- package/src/build/prefix-tree-utils.ts +123 -0
- package/src/build/route-trie.ts +152 -22
- package/src/build/route-types/ast-route-extraction.ts +15 -8
- package/src/build/route-types/codegen.ts +12 -1
- package/src/build/route-types/include-resolution.ts +455 -61
- package/src/build/route-types/param-extraction.ts +6 -3
- package/src/build/route-types/per-module-writer.ts +15 -2
- package/src/build/route-types/router-processing.ts +77 -41
- package/src/build/route-types/source-scan.ts +105 -7
- package/src/build/runtime-discovery.ts +4 -1
- package/src/cache/cache-error.ts +104 -0
- package/src/cache/cache-key-utils.ts +58 -13
- package/src/cache/cache-policy.ts +108 -34
- package/src/cache/cache-runtime.ts +454 -101
- package/src/cache/cache-scope.ts +159 -54
- package/src/cache/cache-tag.ts +149 -0
- package/src/cache/cf/cf-base64.ts +33 -0
- package/src/cache/cf/cf-cache-constants.ts +127 -0
- package/src/cache/cf/cf-cache-store.ts +2170 -377
- package/src/cache/cf/cf-cache-types.ts +349 -0
- package/src/cache/cf/cf-kv-utils.ts +46 -0
- package/src/cache/cf/cf-tag-marker-memo.ts +105 -0
- package/src/cache/cf/index.ts +6 -16
- package/src/cache/document-cache.ts +126 -41
- package/src/cache/handle-snapshot.ts +70 -0
- package/src/cache/index.ts +23 -20
- package/src/cache/memory-segment-store.ts +243 -37
- package/src/cache/profile-registry.ts +46 -31
- package/src/cache/read-through-swr.ts +56 -12
- package/src/cache/segment-codec.ts +13 -21
- package/src/cache/shell-snapshot.ts +417 -0
- package/src/cache/tag-invalidation.ts +230 -0
- package/src/cache/types.ts +194 -99
- package/src/cache/vercel/index.ts +11 -0
- package/src/cache/vercel/vercel-cache-store.ts +1132 -0
- package/src/client.rsc.tsx +39 -22
- package/src/client.tsx +28 -58
- package/src/cloudflare/index.ts +11 -0
- package/src/cloudflare/tracing.ts +108 -0
- package/src/component-utils.ts +19 -0
- package/src/components/DefaultDocument.tsx +8 -2
- package/src/context-var.ts +13 -1
- package/src/decode-loader-results.ts +18 -2
- package/src/defer.ts +185 -0
- package/src/deps/ssr.ts +0 -1
- package/src/encode-kv.ts +49 -0
- package/src/errors.ts +0 -3
- package/src/escape-script.ts +52 -0
- package/src/handle.ts +57 -40
- package/src/handles/MetaTags.tsx +24 -53
- package/src/handles/Scripts.tsx +183 -0
- package/src/handles/breadcrumbs.ts +35 -8
- package/src/handles/deferred-resolution.ts +127 -0
- package/src/handles/is-thenable.ts +18 -0
- package/src/handles/meta.ts +14 -40
- package/src/handles/script.ts +244 -0
- package/src/host/cookie-handler.ts +9 -60
- package/src/host/errors.ts +13 -22
- package/src/host/index.ts +7 -0
- package/src/host/pattern-matcher.ts +23 -52
- package/src/host/router.ts +1 -65
- package/src/host/testing.ts +40 -27
- package/src/host/types.ts +6 -2
- package/src/href-client.ts +7 -12
- package/src/index.rsc.ts +88 -8
- package/src/index.ts +90 -16
- package/src/internal-debug.ts +11 -10
- package/src/loader.rsc.ts +19 -9
- package/src/loader.ts +12 -4
- package/src/outlet-provider.tsx +1 -5
- package/src/prerender/param-hash.ts +16 -16
- package/src/prerender/store.ts +32 -37
- package/src/prerender.ts +75 -7
- package/src/redirect-origin.ts +114 -0
- package/src/regex-escape.ts +8 -0
- package/src/render-error-thrower.tsx +20 -0
- package/src/response-utils.ts +25 -0
- package/src/root-error-boundary.tsx +1 -19
- package/src/route-content-wrapper.tsx +13 -49
- package/src/route-definition/dsl-helpers.ts +60 -53
- package/src/route-definition/helper-factories.ts +0 -2
- package/src/route-definition/helpers-types.ts +46 -46
- package/src/route-definition/index.ts +1 -2
- package/src/route-definition/redirect.ts +44 -11
- package/src/route-definition/resolve-handler-use.ts +6 -1
- package/src/route-definition/use-item-types.ts +3 -6
- package/src/route-map-builder.ts +41 -20
- package/src/route-types.ts +0 -5
- package/src/router/content-negotiation.ts +58 -23
- package/src/router/error-handling.ts +44 -17
- package/src/router/find-match.ts +129 -30
- package/src/router/handler-context.ts +6 -1
- package/src/router/instrument.ts +355 -0
- package/src/router/intercept-resolution.ts +35 -2
- package/src/router/lazy-includes.ts +79 -56
- package/src/router/loader-resolution.ts +151 -73
- package/src/router/logging.ts +0 -6
- package/src/router/manifest.ts +74 -40
- package/src/router/match-api.ts +76 -52
- package/src/router/match-context.ts +0 -22
- package/src/router/match-handlers.ts +181 -178
- package/src/router/match-middleware/background-revalidation.ts +40 -24
- package/src/router/match-middleware/cache-lookup.ts +115 -194
- package/src/router/match-middleware/cache-store.ts +61 -50
- package/src/router/match-middleware/intercept-resolution.ts +0 -22
- package/src/router/match-middleware/segment-resolution.ts +0 -22
- package/src/router/match-pipelines.ts +1 -42
- package/src/router/match-result.ts +36 -67
- package/src/router/metrics.ts +0 -34
- package/src/router/middleware-types.ts +0 -116
- package/src/router/middleware.ts +231 -120
- package/src/router/navigation-snapshot.ts +7 -56
- package/src/router/params-util.ts +23 -0
- package/src/router/parse-pattern.ts +115 -0
- package/src/router/pattern-matching.ts +99 -152
- package/src/router/prefetch-cache-ttl.ts +51 -0
- package/src/router/prefetch-limits.ts +37 -0
- package/src/router/prerender-match.ts +111 -66
- package/src/router/preview-match.ts +3 -1
- package/src/router/request-classification.ts +47 -42
- package/src/router/revalidation.ts +75 -81
- package/src/router/route-snapshot.ts +14 -3
- package/src/router/router-context.ts +6 -29
- package/src/router/router-interfaces.ts +70 -8
- package/src/router/router-options.ts +126 -4
- package/src/router/segment-resolution/fresh.ts +104 -80
- package/src/router/segment-resolution/helpers.ts +86 -6
- package/src/router/segment-resolution/loader-cache.ts +155 -39
- package/src/router/segment-resolution/loader-mask.ts +60 -0
- package/src/router/segment-resolution/loader-snapshot.ts +259 -0
- package/src/router/segment-resolution/mask-nested.ts +83 -0
- package/src/router/segment-resolution/revalidation.ts +215 -304
- package/src/router/segment-resolution/static-store.ts +19 -5
- package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
- package/src/router/segment-resolution/view-transition-default.ts +35 -15
- package/src/router/segment-resolution.ts +5 -1
- package/src/router/segment-wrappers.ts +6 -5
- package/src/router/state-cookie-name.ts +33 -0
- package/src/router/substitute-pattern-params.ts +54 -35
- package/src/router/telemetry-otel.ts +160 -200
- package/src/router/telemetry.ts +9 -23
- package/src/router/timeout.ts +0 -20
- package/src/router/tracing.ts +215 -0
- package/src/router/trie-matching.ts +171 -64
- package/src/router/types.ts +1 -63
- package/src/router/url-params.ts +13 -5
- package/src/router.ts +119 -48
- package/src/rsc/full-payload.ts +70 -0
- package/src/rsc/handler-context.ts +1 -0
- package/src/rsc/handler.ts +267 -152
- package/src/rsc/helpers.ts +78 -4
- package/src/rsc/index.ts +1 -4
- package/src/rsc/json-route-result.ts +38 -0
- package/src/rsc/loader-fetch.ts +114 -38
- package/src/rsc/manifest-init.ts +29 -42
- package/src/rsc/nonce.ts +10 -1
- package/src/rsc/origin-guard.ts +11 -15
- package/src/rsc/progressive-enhancement.ts +120 -13
- package/src/rsc/redirect-guard.ts +100 -0
- package/src/rsc/response-cache-serve.ts +238 -0
- package/src/rsc/response-error.ts +79 -12
- package/src/rsc/response-route-handler.ts +58 -141
- package/src/rsc/rsc-rendering.ts +492 -49
- package/src/rsc/runtime-warnings.ts +14 -0
- package/src/rsc/server-action.ts +268 -82
- package/src/rsc/shell-capture.ts +1190 -0
- package/src/rsc/shell-serve.ts +181 -0
- package/src/rsc/transition-gate.ts +89 -0
- package/src/rsc/types.ts +45 -3
- package/src/runtime-env.ts +18 -0
- package/src/search-params.ts +31 -26
- package/src/segment-loader-promise.ts +49 -4
- package/src/segment-system.tsx +260 -95
- package/src/server/context.ts +99 -9
- package/src/server/cookie-parse.ts +32 -0
- package/src/server/cookie-store.ts +125 -2
- package/src/server/handle-store.ts +21 -38
- package/src/server/loader-registry.ts +33 -42
- package/src/server/request-context.ts +379 -138
- package/src/ssr/index.tsx +491 -182
- package/src/ssr/inject-rsc-eager.ts +167 -0
- package/src/ssr/ssr-root.tsx +228 -0
- package/src/static-handler.ts +10 -13
- package/src/testing/cache-status.ts +44 -48
- package/src/testing/collect-handle.ts +14 -31
- package/src/testing/dispatch.ts +533 -160
- package/src/testing/e2e/fixture.ts +45 -11
- package/src/testing/e2e/index.ts +1 -22
- package/src/testing/e2e/matchers.ts +0 -16
- package/src/testing/e2e/parity.ts +85 -4
- package/src/testing/e2e/server.ts +12 -0
- package/src/testing/flight-matchers.ts +7 -14
- package/src/testing/flight-normalize.ts +11 -0
- package/src/testing/flight-runtime.d.ts +36 -0
- package/src/testing/flight-tree.ts +682 -0
- package/src/testing/flight.entry.ts +30 -0
- package/src/testing/flight.ts +145 -70
- package/src/testing/generated-routes.ts +26 -50
- package/src/testing/index.ts +18 -19
- package/src/testing/internal/context.ts +184 -68
- 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 +134 -115
- package/src/testing/run-loader.ts +140 -51
- package/src/testing/run-middleware.ts +59 -33
- package/src/testing/run-transition-when.ts +164 -0
- package/src/testing/vitest-stubs/cloudflare-email.ts +1 -1
- package/src/testing/vitest-stubs/cloudflare-workers.ts +1 -1
- package/src/testing/vitest.ts +138 -16
- package/src/theme/ThemeProvider.tsx +56 -84
- package/src/theme/ThemeScript.tsx +7 -9
- package/src/theme/constants.ts +52 -13
- package/src/theme/index.ts +0 -7
- package/src/theme/theme-context.ts +1 -5
- package/src/theme/theme-script.ts +22 -21
- package/src/theme/use-theme.ts +0 -3
- package/src/types/boundaries.ts +0 -35
- package/src/types/cache-types.ts +13 -4
- package/src/types/error-types.ts +30 -90
- package/src/types/global-namespace.ts +15 -15
- package/src/types/handler-context.ts +45 -15
- package/src/types/index.ts +2 -10
- package/src/types/loader-types.ts +6 -3
- package/src/types/request-scope.ts +8 -22
- package/src/types/route-config.ts +20 -52
- package/src/types/route-entry.ts +0 -6
- package/src/types/segments.ts +100 -13
- package/src/urls/include-helper.ts +10 -12
- package/src/urls/include-provider.ts +71 -0
- package/src/urls/index.ts +2 -8
- package/src/urls/path-helper-types.ts +52 -14
- package/src/urls/path-helper.ts +5 -54
- package/src/urls/pattern-types.ts +36 -0
- package/src/urls/type-extraction.ts +76 -42
- package/src/urls/urls-function.ts +0 -14
- package/src/use-loader.tsx +0 -186
- package/src/vercel/index.ts +11 -0
- package/src/vercel/tracing.ts +88 -0
- package/src/vite/discovery/bundle-postprocess.ts +2 -1
- package/src/vite/discovery/dev-prerender-cache.ts +117 -0
- package/src/vite/discovery/discover-routers.ts +34 -43
- package/src/vite/discovery/discovery-errors.ts +61 -0
- package/src/vite/discovery/prerender-collection.ts +33 -46
- package/src/vite/discovery/state.ts +12 -1
- package/src/vite/discovery/virtual-module-codegen.ts +1 -11
- package/src/vite/index.ts +9 -0
- package/src/vite/inject-client-debug.ts +88 -0
- package/src/vite/plugin-types.ts +143 -10
- package/src/vite/plugins/cjs-to-esm.ts +8 -12
- package/src/vite/plugins/client-ref-dedup.ts +0 -11
- package/src/vite/plugins/client-ref-hashing.ts +0 -10
- package/src/vite/plugins/cloudflare-protocol-stub.ts +0 -20
- package/src/vite/plugins/expose-action-id.ts +2 -73
- package/src/vite/plugins/expose-id-utils.ts +85 -56
- package/src/vite/plugins/expose-ids/export-analysis.ts +30 -43
- package/src/vite/plugins/expose-ids/handler-transform.ts +5 -31
- package/src/vite/plugins/expose-ids/loader-transform.ts +12 -20
- package/src/vite/plugins/expose-ids/router-transform.ts +98 -26
- package/src/vite/plugins/expose-internal-ids.ts +10 -1
- package/src/vite/plugins/performance-tracks.ts +0 -3
- package/src/vite/plugins/refresh-cmd.ts +1 -1
- package/src/vite/plugins/use-cache-transform.ts +21 -46
- package/src/vite/plugins/vercel-output.ts +384 -0
- package/src/vite/plugins/version-injector.ts +22 -27
- package/src/vite/plugins/version-plugin.ts +6 -66
- package/src/vite/plugins/virtual-entries.ts +137 -26
- package/src/vite/rango.ts +146 -135
- package/src/vite/router-discovery.ts +189 -48
- package/src/vite/utils/ast-handler-extract.ts +11 -20
- package/src/vite/utils/bundle-analysis.ts +6 -13
- package/src/vite/utils/client-chunks.ts +0 -6
- package/src/vite/utils/directive-prologue.ts +40 -0
- package/src/vite/utils/forward-user-plugins.ts +0 -22
- package/src/vite/utils/manifest-utils.ts +4 -75
- package/src/vite/utils/package-resolution.ts +1 -73
- package/src/vite/utils/prerender-utils.ts +71 -44
- package/src/vite/utils/shared-utils.ts +55 -37
- package/src/browser/react/use-client-cache.ts +0 -58
- package/src/browser/shallow.ts +0 -40
- package/src/handles/index.ts +0 -7
- package/src/network-error-thrower.tsx +0 -23
- package/src/router/middleware-cookies.ts +0 -55
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
import type { CacheDefaults, SegmentCacheStore } from "./types.js";
|
|
10
10
|
import { _getRequestContext } from "../server/request-context.js";
|
|
11
11
|
import type { RequestContext } from "../server/request-context.js";
|
|
12
|
+
import { normalizeTags } from "./cache-tag.js";
|
|
13
|
+
import { reportCacheError } from "./cache-error.js";
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
16
|
* Default TTL for route-level cache() DSL and loader cache.
|
|
@@ -22,31 +24,62 @@ export const DEFAULT_ROUTE_TTL = 60;
|
|
|
22
24
|
*/
|
|
23
25
|
export const DEFAULT_FUNCTION_TTL = 900;
|
|
24
26
|
|
|
27
|
+
/**
|
|
28
|
+
* A finite, non-negative seconds value? A NaN/Infinity ttl/swr (from a bad
|
|
29
|
+
* cache() option or store defaults) flows into computeExpiration ->
|
|
30
|
+
* staleAt/expiresAt = NaN, where every `now > NaN` is false so the entry never
|
|
31
|
+
* evicts and is served fresh forever; a negative value makes every read a miss.
|
|
32
|
+
* Shared with cache-scope.ts (the segment getters) so every cache path validates
|
|
33
|
+
* the same way. profile-registry.ts uses the same predicate but fails fast at
|
|
34
|
+
* config time; the resolvers here degrade because they run on the live path.
|
|
35
|
+
*/
|
|
36
|
+
export function isFiniteNonNegativeSeconds(value: number): boolean {
|
|
37
|
+
return Number.isFinite(value) && value >= 0;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function warnInvalidSeconds(label: string, value: number): void {
|
|
41
|
+
if (process.env.NODE_ENV !== "production") {
|
|
42
|
+
console.warn(`[cache] Invalid ${label} ${value}; falling back to default`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
25
46
|
/**
|
|
26
47
|
* Resolve effective TTL from the 3-tier cascade:
|
|
27
|
-
* explicit → store defaults → fallback.
|
|
48
|
+
* explicit → store defaults → fallback. A non-finite/negative resolved value
|
|
49
|
+
* degrades to the fallback (loader cache and "use cache" setItem both resolve
|
|
50
|
+
* ttl here, so this is where those paths are guarded; the segment cache is
|
|
51
|
+
* guarded in cache-scope.ts).
|
|
28
52
|
*/
|
|
29
53
|
export function resolveTtl(
|
|
30
54
|
explicit: number | undefined,
|
|
31
55
|
defaults: CacheDefaults | undefined,
|
|
32
56
|
fallback: number,
|
|
33
57
|
): number {
|
|
34
|
-
|
|
35
|
-
if (
|
|
58
|
+
let value: number;
|
|
59
|
+
if (explicit !== undefined) value = explicit;
|
|
60
|
+
else if (defaults?.ttl !== undefined) value = defaults.ttl;
|
|
61
|
+
else return fallback;
|
|
62
|
+
if (isFiniteNonNegativeSeconds(value)) return value;
|
|
63
|
+
warnInvalidSeconds("ttl", value);
|
|
36
64
|
return fallback;
|
|
37
65
|
}
|
|
38
66
|
|
|
39
67
|
/**
|
|
40
68
|
* Resolve effective SWR window from the 2-tier cascade:
|
|
41
69
|
* explicit → store defaults.
|
|
42
|
-
* Returns 0 when unset (no SWR window)
|
|
70
|
+
* Returns 0 when unset (no SWR window) or when the resolved value is
|
|
71
|
+
* non-finite/negative (degrade rather than feed bad math into expiry).
|
|
43
72
|
*/
|
|
44
73
|
export function resolveSwrWindow(
|
|
45
74
|
explicit: number | undefined,
|
|
46
75
|
defaults: CacheDefaults | undefined,
|
|
47
76
|
): number {
|
|
48
|
-
|
|
49
|
-
if (
|
|
77
|
+
let value: number;
|
|
78
|
+
if (explicit !== undefined) value = explicit;
|
|
79
|
+
else if (defaults?.swr !== undefined) value = defaults.swr;
|
|
80
|
+
else return 0;
|
|
81
|
+
if (isFiniteNonNegativeSeconds(value)) return value;
|
|
82
|
+
warnInvalidSeconds("swr", value);
|
|
50
83
|
return 0;
|
|
51
84
|
}
|
|
52
85
|
|
|
@@ -68,24 +101,6 @@ export function computeExpiration(
|
|
|
68
101
|
return { staleAt, expiresAt };
|
|
69
102
|
}
|
|
70
103
|
|
|
71
|
-
// ============================================================================
|
|
72
|
-
// Cache Key Resolution
|
|
73
|
-
// ============================================================================
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Resolve cache key using the 3-tier priority:
|
|
77
|
-
* 1. keyFn (full override from route/loader cache options)
|
|
78
|
-
* 2. store.keyGenerator (modifies default key)
|
|
79
|
-
* 3. defaultKey (used when neither keyFn nor keyGenerator is provided)
|
|
80
|
-
*
|
|
81
|
-
* Errors from keyFn and store.keyGenerator propagate to the caller.
|
|
82
|
-
* Cache identity is correctness-critical: if explicit key logic throws,
|
|
83
|
-
* silently remapping to a different key could cause cache collisions or
|
|
84
|
-
* serve stale/wrong data. Callers must handle the error or let it surface.
|
|
85
|
-
*
|
|
86
|
-
* Uses _getRequestContext (non-throwing) so that calls outside ALS
|
|
87
|
-
* (e.g. build-time) gracefully fall back to defaultKey.
|
|
88
|
-
*/
|
|
89
104
|
export async function resolveCacheKey(
|
|
90
105
|
keyFn: ((ctx: RequestContext) => string | Promise<string>) | undefined,
|
|
91
106
|
store: SegmentCacheStore | null,
|
|
@@ -94,32 +109,91 @@ export async function resolveCacheKey(
|
|
|
94
109
|
): Promise<string> {
|
|
95
110
|
const requestCtx = _getRequestContext();
|
|
96
111
|
|
|
97
|
-
// Priority 1: Route/loader-level key function (full override)
|
|
98
112
|
if (keyFn && requestCtx) {
|
|
99
113
|
return await keyFn(requestCtx);
|
|
100
114
|
}
|
|
101
115
|
|
|
102
|
-
// Priority 2: Store-level keyGenerator (modifies default key)
|
|
103
116
|
if (store?.keyGenerator && requestCtx) {
|
|
104
117
|
return await store.keyGenerator(requestCtx, defaultKey);
|
|
105
118
|
}
|
|
106
119
|
|
|
107
|
-
// Priority 3: Default key (no custom key logic provided)
|
|
108
120
|
return defaultKey;
|
|
109
121
|
}
|
|
110
122
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
123
|
+
export function resolveTagsOption<TEnv>(
|
|
124
|
+
tags: string[] | ((ctx: RequestContext<TEnv>) => string[]) | undefined,
|
|
125
|
+
ctx: RequestContext<TEnv> | undefined,
|
|
126
|
+
label: string,
|
|
127
|
+
): string[] | undefined {
|
|
128
|
+
if (!tags) return undefined;
|
|
129
|
+
if (typeof tags === "function") {
|
|
130
|
+
if (!ctx) {
|
|
131
|
+
console.warn(
|
|
132
|
+
`[${label}] Dynamic tags function present but no request context; ` +
|
|
133
|
+
`caching without tags (this entry will not be tag-invalidatable).`,
|
|
134
|
+
);
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
137
|
+
try {
|
|
138
|
+
return normalizeTagList(tags(ctx));
|
|
139
|
+
} catch (error) {
|
|
140
|
+
reportCacheError(
|
|
141
|
+
error,
|
|
142
|
+
"cache-write",
|
|
143
|
+
`[${label}] Tags function failed, caching without tags`,
|
|
144
|
+
ctx,
|
|
145
|
+
);
|
|
146
|
+
return undefined;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return normalizeTagList(tags);
|
|
150
|
+
}
|
|
114
151
|
|
|
115
152
|
/**
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
153
|
+
* Normalize a resolved tags array so the WRITE path matches the invalidate path:
|
|
154
|
+
* updateTag()/revalidateTag()/cacheTag() all drop empty/whitespace-only tags via
|
|
155
|
+
* normalizeTag(). Without this, an empty tag attached at write time would enter
|
|
156
|
+
* the store index but could never be invalidated (the verbs normalize it away),
|
|
157
|
+
* and on CFCacheStore would also cost a wasted KV marker read per request.
|
|
158
|
+
* Returns undefined when nothing usable remains, keeping the entry header-free.
|
|
119
159
|
*/
|
|
160
|
+
function normalizeTagList(tags: string[]): string[] | undefined {
|
|
161
|
+
const out = normalizeTags(tags);
|
|
162
|
+
return out.length > 0 ? out : undefined;
|
|
163
|
+
}
|
|
164
|
+
|
|
120
165
|
export function resolveCacheStore(
|
|
121
166
|
explicitStore: SegmentCacheStore | undefined,
|
|
122
167
|
): SegmentCacheStore | null {
|
|
123
|
-
if (explicitStore)
|
|
168
|
+
if (explicitStore) {
|
|
169
|
+
registerExplicitTaggedStore(explicitStore);
|
|
170
|
+
return explicitStore;
|
|
171
|
+
}
|
|
124
172
|
return _getRequestContext()?._cacheStore ?? null;
|
|
125
173
|
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Upper bound on the per-handler explicit-store registry. A module-singleton
|
|
177
|
+
* store (the recommended pattern) dedupes to a single entry and never approaches
|
|
178
|
+
* this. The cap bounds the niche case of an explicit store constructed PER
|
|
179
|
+
* request/boundary (e.g. a ctx-bound CFCacheStore, which must take a per-request
|
|
180
|
+
* ctx): without it the registry - which intentionally persists across requests so
|
|
181
|
+
* a server action's updateTag() can reach stores a prior render registered -
|
|
182
|
+
* would accumulate one dead instance per request and fan invalidation out to
|
|
183
|
+
* finished execution contexts. LRU-touch on re-resolution keeps a live, re-used
|
|
184
|
+
* store from being evicted by that churn.
|
|
185
|
+
*/
|
|
186
|
+
const EXPLICIT_STORE_REGISTRY_CAP = 64;
|
|
187
|
+
|
|
188
|
+
function registerExplicitTaggedStore(store: SegmentCacheStore): void {
|
|
189
|
+
const set = _getRequestContext()?._explicitTaggedStores;
|
|
190
|
+
if (!set) return;
|
|
191
|
+
// LRU touch: move an already-present store to the most-recent position (Set
|
|
192
|
+
// preserves insertion order) so a store re-resolved every request stays live.
|
|
193
|
+
set.delete(store);
|
|
194
|
+
set.add(store);
|
|
195
|
+
if (set.size > EXPLICIT_STORE_REGISTRY_CAP) {
|
|
196
|
+
const oldest = set.values().next().value;
|
|
197
|
+
if (oldest !== undefined) set.delete(oldest);
|
|
198
|
+
}
|
|
199
|
+
}
|