@rangojs/router 0.0.0-experimental.12 → 0.0.0-experimental.120
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 +9 -0
- package/README.md +1037 -4
- package/dist/__internal.d.ts +83 -0
- package/dist/__internal.d.ts.map +1 -0
- package/dist/__internal.js +19 -0
- package/dist/__internal.js.map +1 -0
- package/dist/__mocks__/version.d.ts +7 -0
- package/dist/__mocks__/version.d.ts.map +1 -0
- package/dist/__mocks__/version.js +7 -0
- package/dist/__mocks__/version.js.map +1 -0
- package/dist/__tests__/client-href.test.d.ts +2 -0
- package/dist/__tests__/client-href.test.d.ts.map +1 -0
- package/dist/__tests__/client-href.test.js +74 -0
- package/dist/__tests__/client-href.test.js.map +1 -0
- package/dist/__tests__/component-utils.test.d.ts +2 -0
- package/dist/__tests__/component-utils.test.d.ts.map +1 -0
- package/dist/__tests__/component-utils.test.js +51 -0
- package/dist/__tests__/component-utils.test.js.map +1 -0
- package/dist/__tests__/event-controller.test.d.ts +2 -0
- package/dist/__tests__/event-controller.test.d.ts.map +1 -0
- package/dist/__tests__/event-controller.test.js +538 -0
- package/dist/__tests__/event-controller.test.js.map +1 -0
- package/dist/__tests__/helpers/route-tree.d.ts +118 -0
- package/dist/__tests__/helpers/route-tree.d.ts.map +1 -0
- package/dist/__tests__/helpers/route-tree.js +374 -0
- package/dist/__tests__/helpers/route-tree.js.map +1 -0
- package/dist/__tests__/match-result.test.d.ts +2 -0
- package/dist/__tests__/match-result.test.d.ts.map +1 -0
- package/dist/__tests__/match-result.test.js +154 -0
- package/dist/__tests__/match-result.test.js.map +1 -0
- package/dist/__tests__/navigation-store.test.d.ts +2 -0
- package/dist/__tests__/navigation-store.test.d.ts.map +1 -0
- package/dist/__tests__/navigation-store.test.js +440 -0
- package/dist/__tests__/navigation-store.test.js.map +1 -0
- package/dist/__tests__/partial-update.test.d.ts +2 -0
- package/dist/__tests__/partial-update.test.d.ts.map +1 -0
- package/dist/__tests__/partial-update.test.js +1009 -0
- package/dist/__tests__/partial-update.test.js.map +1 -0
- package/dist/__tests__/reverse-types.test.d.ts +8 -0
- package/dist/__tests__/reverse-types.test.d.ts.map +1 -0
- package/dist/__tests__/reverse-types.test.js +656 -0
- package/dist/__tests__/reverse-types.test.js.map +1 -0
- package/dist/__tests__/route-definition.test.d.ts +2 -0
- package/dist/__tests__/route-definition.test.d.ts.map +1 -0
- package/dist/__tests__/route-definition.test.js +55 -0
- package/dist/__tests__/route-definition.test.js.map +1 -0
- package/dist/__tests__/router-helpers.test.d.ts +2 -0
- package/dist/__tests__/router-helpers.test.d.ts.map +1 -0
- package/dist/__tests__/router-helpers.test.js +377 -0
- package/dist/__tests__/router-helpers.test.js.map +1 -0
- package/dist/__tests__/router-integration-2.test.d.ts +2 -0
- package/dist/__tests__/router-integration-2.test.d.ts.map +1 -0
- package/dist/__tests__/router-integration-2.test.js +426 -0
- package/dist/__tests__/router-integration-2.test.js.map +1 -0
- package/dist/__tests__/router-integration.test.d.ts +2 -0
- package/dist/__tests__/router-integration.test.d.ts.map +1 -0
- package/dist/__tests__/router-integration.test.js +1051 -0
- package/dist/__tests__/router-integration.test.js.map +1 -0
- package/dist/__tests__/search-params.test.d.ts +5 -0
- package/dist/__tests__/search-params.test.d.ts.map +1 -0
- package/dist/__tests__/search-params.test.js +306 -0
- package/dist/__tests__/search-params.test.js.map +1 -0
- package/dist/__tests__/segment-system.test.d.ts +2 -0
- package/dist/__tests__/segment-system.test.d.ts.map +1 -0
- package/dist/__tests__/segment-system.test.js +627 -0
- package/dist/__tests__/segment-system.test.js.map +1 -0
- package/dist/__tests__/static-handler-types.test.d.ts +8 -0
- package/dist/__tests__/static-handler-types.test.d.ts.map +1 -0
- package/dist/__tests__/static-handler-types.test.js +63 -0
- package/dist/__tests__/static-handler-types.test.js.map +1 -0
- package/dist/__tests__/urls.test.d.ts +2 -0
- package/dist/__tests__/urls.test.d.ts.map +1 -0
- package/dist/__tests__/urls.test.js +421 -0
- package/dist/__tests__/urls.test.js.map +1 -0
- package/dist/__tests__/use-mount.test.d.ts +2 -0
- package/dist/__tests__/use-mount.test.d.ts.map +1 -0
- package/dist/__tests__/use-mount.test.js +35 -0
- package/dist/__tests__/use-mount.test.js.map +1 -0
- package/dist/bin/rango.d.ts +2 -0
- package/dist/bin/rango.d.ts.map +1 -0
- package/dist/bin/rango.js +1704 -212
- package/dist/bin/rango.js.map +1 -0
- package/dist/browser/event-controller.d.ts +191 -0
- package/dist/browser/event-controller.d.ts.map +1 -0
- package/dist/browser/event-controller.js +559 -0
- package/dist/browser/event-controller.js.map +1 -0
- package/dist/browser/index.d.ts +2 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.js +14 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/link-interceptor.d.ts +38 -0
- package/dist/browser/link-interceptor.d.ts.map +1 -0
- package/dist/browser/link-interceptor.js +99 -0
- package/dist/browser/link-interceptor.js.map +1 -0
- package/dist/browser/logging.d.ts +10 -0
- package/dist/browser/logging.d.ts.map +1 -0
- package/dist/browser/logging.js +29 -0
- package/dist/browser/logging.js.map +1 -0
- package/dist/browser/lru-cache.d.ts +17 -0
- package/dist/browser/lru-cache.d.ts.map +1 -0
- package/dist/browser/lru-cache.js +50 -0
- package/dist/browser/lru-cache.js.map +1 -0
- package/dist/browser/merge-segment-loaders.d.ts +39 -0
- package/dist/browser/merge-segment-loaders.d.ts.map +1 -0
- package/dist/browser/merge-segment-loaders.js +102 -0
- package/dist/browser/merge-segment-loaders.js.map +1 -0
- package/dist/browser/navigation-bridge.d.ts +102 -0
- package/dist/browser/navigation-bridge.d.ts.map +1 -0
- package/dist/browser/navigation-bridge.js +708 -0
- package/dist/browser/navigation-bridge.js.map +1 -0
- package/dist/browser/navigation-client.d.ts +25 -0
- package/dist/browser/navigation-client.d.ts.map +1 -0
- package/dist/browser/navigation-client.js +157 -0
- package/dist/browser/navigation-client.js.map +1 -0
- package/dist/browser/navigation-store.d.ts +101 -0
- package/dist/browser/navigation-store.d.ts.map +1 -0
- package/dist/browser/navigation-store.js +625 -0
- package/dist/browser/navigation-store.js.map +1 -0
- package/dist/browser/partial-update.d.ts +75 -0
- package/dist/browser/partial-update.d.ts.map +1 -0
- package/dist/browser/partial-update.js +426 -0
- package/dist/browser/partial-update.js.map +1 -0
- package/dist/browser/react/Link.d.ts +86 -0
- package/dist/browser/react/Link.d.ts.map +1 -0
- package/dist/browser/react/Link.js +128 -0
- package/dist/browser/react/Link.js.map +1 -0
- package/dist/browser/react/NavigationProvider.d.ts +63 -0
- package/dist/browser/react/NavigationProvider.d.ts.map +1 -0
- package/dist/browser/react/NavigationProvider.js +216 -0
- package/dist/browser/react/NavigationProvider.js.map +1 -0
- package/dist/browser/react/ScrollRestoration.d.ts +75 -0
- package/dist/browser/react/ScrollRestoration.d.ts.map +1 -0
- package/dist/browser/react/ScrollRestoration.js +57 -0
- package/dist/browser/react/ScrollRestoration.js.map +1 -0
- package/dist/browser/react/context.d.ts +46 -0
- package/dist/browser/react/context.d.ts.map +1 -0
- package/dist/browser/react/context.js +10 -0
- package/dist/browser/react/context.js.map +1 -0
- package/dist/browser/react/index.d.ts +11 -0
- package/dist/browser/react/index.d.ts.map +1 -0
- package/dist/browser/react/index.js +22 -0
- package/dist/browser/react/index.js.map +1 -0
- package/dist/browser/react/location-state-shared.d.ts +63 -0
- package/dist/browser/react/location-state-shared.d.ts.map +1 -0
- package/dist/browser/react/location-state-shared.js +81 -0
- package/dist/browser/react/location-state-shared.js.map +1 -0
- package/dist/browser/react/location-state.d.ts +23 -0
- package/dist/browser/react/location-state.d.ts.map +1 -0
- package/dist/browser/react/location-state.js +29 -0
- package/dist/browser/react/location-state.js.map +1 -0
- package/dist/browser/react/mount-context.d.ts +24 -0
- package/dist/browser/react/mount-context.d.ts.map +1 -0
- package/dist/browser/react/mount-context.js +24 -0
- package/dist/browser/react/mount-context.js.map +1 -0
- package/dist/browser/react/use-action.d.ts +64 -0
- package/dist/browser/react/use-action.d.ts.map +1 -0
- package/dist/browser/react/use-action.js +134 -0
- package/dist/browser/react/use-action.js.map +1 -0
- package/dist/browser/react/use-client-cache.d.ts +41 -0
- package/dist/browser/react/use-client-cache.d.ts.map +1 -0
- package/dist/browser/react/use-client-cache.js +39 -0
- package/dist/browser/react/use-client-cache.js.map +1 -0
- package/dist/browser/react/use-handle.d.ts +31 -0
- package/dist/browser/react/use-handle.d.ts.map +1 -0
- package/dist/browser/react/use-handle.js +144 -0
- package/dist/browser/react/use-handle.js.map +1 -0
- package/dist/browser/react/use-href.d.ts +33 -0
- package/dist/browser/react/use-href.d.ts.map +1 -0
- package/dist/browser/react/use-href.js +39 -0
- package/dist/browser/react/use-href.js.map +1 -0
- package/dist/browser/react/use-link-status.d.ts +37 -0
- package/dist/browser/react/use-link-status.d.ts.map +1 -0
- package/dist/browser/react/use-link-status.js +99 -0
- package/dist/browser/react/use-link-status.js.map +1 -0
- package/dist/browser/react/use-mount.d.ts +25 -0
- package/dist/browser/react/use-mount.d.ts.map +1 -0
- package/dist/browser/react/use-mount.js +30 -0
- package/dist/browser/react/use-mount.js.map +1 -0
- package/dist/browser/react/use-navigation.d.ts +27 -0
- package/dist/browser/react/use-navigation.d.ts.map +1 -0
- package/dist/browser/react/use-navigation.js +87 -0
- package/dist/browser/react/use-navigation.js.map +1 -0
- package/dist/browser/react/use-segments.d.ts +38 -0
- package/dist/browser/react/use-segments.d.ts.map +1 -0
- package/dist/browser/react/use-segments.js +130 -0
- package/dist/browser/react/use-segments.js.map +1 -0
- package/dist/browser/request-controller.d.ts +26 -0
- package/dist/browser/request-controller.d.ts.map +1 -0
- package/dist/browser/request-controller.js +147 -0
- package/dist/browser/request-controller.js.map +1 -0
- package/dist/browser/rsc-router.d.ts +129 -0
- package/dist/browser/rsc-router.d.ts.map +1 -0
- package/dist/browser/rsc-router.js +195 -0
- package/dist/browser/rsc-router.js.map +1 -0
- package/dist/browser/scroll-restoration.d.ts +93 -0
- package/dist/browser/scroll-restoration.d.ts.map +1 -0
- package/dist/browser/scroll-restoration.js +321 -0
- package/dist/browser/scroll-restoration.js.map +1 -0
- package/dist/browser/segment-structure-assert.d.ts +17 -0
- package/dist/browser/segment-structure-assert.d.ts.map +1 -0
- package/dist/browser/segment-structure-assert.js +59 -0
- package/dist/browser/segment-structure-assert.js.map +1 -0
- package/dist/browser/server-action-bridge.d.ts +26 -0
- package/dist/browser/server-action-bridge.d.ts.map +1 -0
- package/dist/browser/server-action-bridge.js +668 -0
- package/dist/browser/server-action-bridge.js.map +1 -0
- package/dist/browser/shallow.d.ts +12 -0
- package/dist/browser/shallow.d.ts.map +1 -0
- package/dist/browser/shallow.js +34 -0
- package/dist/browser/shallow.js.map +1 -0
- package/dist/browser/types.d.ts +369 -0
- package/dist/browser/types.d.ts.map +1 -0
- package/dist/browser/types.js +2 -0
- package/dist/browser/types.js.map +1 -0
- package/dist/build/__tests__/generate-cli.test.d.ts +2 -0
- package/dist/build/__tests__/generate-cli.test.d.ts.map +1 -0
- package/dist/build/__tests__/generate-cli.test.js +237 -0
- package/dist/build/__tests__/generate-cli.test.js.map +1 -0
- package/dist/build/__tests__/generate-manifest.test.d.ts +2 -0
- package/dist/build/__tests__/generate-manifest.test.d.ts.map +1 -0
- package/dist/build/__tests__/generate-manifest.test.js +119 -0
- package/dist/build/__tests__/generate-manifest.test.js.map +1 -0
- package/dist/build/__tests__/generate-route-types.test.d.ts +2 -0
- package/dist/build/__tests__/generate-route-types.test.d.ts.map +1 -0
- package/dist/build/__tests__/generate-route-types.test.js +620 -0
- package/dist/build/__tests__/generate-route-types.test.js.map +1 -0
- package/dist/build/__tests__/per-router-manifest.test.d.ts +2 -0
- package/dist/build/__tests__/per-router-manifest.test.d.ts.map +1 -0
- package/dist/build/__tests__/per-router-manifest.test.js +308 -0
- package/dist/build/__tests__/per-router-manifest.test.js.map +1 -0
- package/dist/build/generate-manifest.d.ts +81 -0
- package/dist/build/generate-manifest.d.ts.map +1 -0
- package/dist/build/generate-manifest.js +276 -0
- package/dist/build/generate-manifest.js.map +1 -0
- package/dist/build/generate-route-types.d.ts +115 -0
- package/dist/build/generate-route-types.d.ts.map +1 -0
- package/dist/build/generate-route-types.js +740 -0
- package/dist/build/generate-route-types.js.map +1 -0
- package/dist/build/index.d.ts +21 -0
- package/dist/build/index.d.ts.map +1 -0
- package/dist/build/index.js +21 -0
- package/dist/build/index.js.map +1 -0
- package/dist/build/route-trie.d.ts +71 -0
- package/dist/build/route-trie.d.ts.map +1 -0
- package/dist/build/route-trie.js +175 -0
- package/dist/build/route-trie.js.map +1 -0
- package/dist/cache/__tests__/cache-scope.test.d.ts +2 -0
- package/dist/cache/__tests__/cache-scope.test.d.ts.map +1 -0
- package/dist/cache/__tests__/cache-scope.test.js +208 -0
- package/dist/cache/__tests__/cache-scope.test.js.map +1 -0
- package/dist/cache/__tests__/document-cache.test.d.ts +2 -0
- package/dist/cache/__tests__/document-cache.test.d.ts.map +1 -0
- package/dist/cache/__tests__/document-cache.test.js +345 -0
- package/dist/cache/__tests__/document-cache.test.js.map +1 -0
- package/dist/cache/__tests__/memory-segment-store.test.d.ts +2 -0
- package/dist/cache/__tests__/memory-segment-store.test.d.ts.map +1 -0
- package/dist/cache/__tests__/memory-segment-store.test.js +425 -0
- package/dist/cache/__tests__/memory-segment-store.test.js.map +1 -0
- package/dist/cache/__tests__/memory-store.test.d.ts +2 -0
- package/dist/cache/__tests__/memory-store.test.d.ts.map +1 -0
- package/dist/cache/__tests__/memory-store.test.js +367 -0
- package/dist/cache/__tests__/memory-store.test.js.map +1 -0
- package/dist/cache/cache-scope.d.ts +102 -0
- package/dist/cache/cache-scope.d.ts.map +1 -0
- package/dist/cache/cache-scope.js +440 -0
- package/dist/cache/cache-scope.js.map +1 -0
- package/dist/cache/cf/__tests__/cf-cache-store.test.d.ts +2 -0
- package/dist/cache/cf/__tests__/cf-cache-store.test.d.ts.map +1 -0
- package/dist/cache/cf/__tests__/cf-cache-store.test.js +330 -0
- package/dist/cache/cf/__tests__/cf-cache-store.test.js.map +1 -0
- package/dist/cache/cf/cf-cache-store.d.ts +165 -0
- package/dist/cache/cf/cf-cache-store.d.ts.map +1 -0
- package/dist/cache/cf/cf-cache-store.js +242 -0
- package/dist/cache/cf/cf-cache-store.js.map +1 -0
- package/dist/cache/cf/index.d.ts +14 -0
- package/dist/cache/cf/index.d.ts.map +1 -0
- package/dist/cache/cf/index.js +17 -0
- package/dist/cache/cf/index.js.map +1 -0
- package/dist/cache/document-cache.d.ts +64 -0
- package/dist/cache/document-cache.d.ts.map +1 -0
- package/dist/cache/document-cache.js +228 -0
- package/dist/cache/document-cache.js.map +1 -0
- package/dist/cache/index.d.ts +19 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +21 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/memory-segment-store.d.ts +110 -0
- package/dist/cache/memory-segment-store.d.ts.map +1 -0
- package/dist/cache/memory-segment-store.js +117 -0
- package/dist/cache/memory-segment-store.js.map +1 -0
- package/dist/cache/memory-store.d.ts +41 -0
- package/dist/cache/memory-store.d.ts.map +1 -0
- package/dist/cache/memory-store.js +191 -0
- package/dist/cache/memory-store.js.map +1 -0
- package/dist/cache/types.d.ts +317 -0
- package/dist/cache/types.d.ts.map +1 -0
- package/dist/cache/types.js +12 -0
- package/dist/cache/types.js.map +1 -0
- package/dist/client.d.ts +248 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +367 -0
- package/dist/client.js.map +1 -0
- package/dist/client.rsc.d.ts +26 -0
- package/dist/client.rsc.d.ts.map +1 -0
- package/dist/client.rsc.js +46 -0
- package/dist/client.rsc.js.map +1 -0
- package/dist/component-utils.d.ts +36 -0
- package/dist/component-utils.d.ts.map +1 -0
- package/dist/component-utils.js +61 -0
- package/dist/component-utils.js.map +1 -0
- package/dist/components/DefaultDocument.d.ts +13 -0
- package/dist/components/DefaultDocument.d.ts.map +1 -0
- package/dist/components/DefaultDocument.js +15 -0
- package/dist/components/DefaultDocument.js.map +1 -0
- package/dist/debug.d.ts +58 -0
- package/dist/debug.d.ts.map +1 -0
- package/dist/debug.js +157 -0
- package/dist/debug.js.map +1 -0
- package/dist/default-error-boundary.d.ts +11 -0
- package/dist/default-error-boundary.d.ts.map +1 -0
- package/dist/default-error-boundary.js +45 -0
- package/dist/default-error-boundary.js.map +1 -0
- package/dist/deps/browser.d.ts +2 -0
- package/dist/deps/browser.d.ts.map +1 -0
- package/dist/deps/browser.js +3 -0
- package/dist/deps/browser.js.map +1 -0
- package/dist/deps/html-stream-client.d.ts +2 -0
- package/dist/deps/html-stream-client.d.ts.map +1 -0
- package/dist/deps/html-stream-client.js +3 -0
- package/dist/deps/html-stream-client.js.map +1 -0
- package/dist/deps/html-stream-server.d.ts +2 -0
- package/dist/deps/html-stream-server.d.ts.map +1 -0
- package/dist/deps/html-stream-server.js +3 -0
- package/dist/deps/html-stream-server.js.map +1 -0
- package/dist/deps/rsc.d.ts +2 -0
- package/dist/deps/rsc.d.ts.map +1 -0
- package/dist/deps/rsc.js +4 -0
- package/dist/deps/rsc.js.map +1 -0
- package/dist/deps/ssr.d.ts +2 -0
- package/dist/deps/ssr.d.ts.map +1 -0
- package/dist/deps/ssr.js +3 -0
- package/dist/deps/ssr.js.map +1 -0
- package/dist/errors.d.ts +174 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +241 -0
- package/dist/errors.js.map +1 -0
- package/dist/handle.d.ts +78 -0
- package/dist/handle.d.ts.map +1 -0
- package/dist/handle.js +82 -0
- package/dist/handle.js.map +1 -0
- package/dist/handles/MetaTags.d.ts +14 -0
- package/dist/handles/MetaTags.d.ts.map +1 -0
- package/dist/handles/MetaTags.js +136 -0
- package/dist/handles/MetaTags.js.map +1 -0
- package/dist/handles/index.d.ts +6 -0
- package/dist/handles/index.d.ts.map +1 -0
- package/dist/handles/index.js +6 -0
- package/dist/handles/index.js.map +1 -0
- package/dist/handles/meta.d.ts +39 -0
- package/dist/handles/meta.d.ts.map +1 -0
- package/dist/handles/meta.js +202 -0
- package/dist/handles/meta.js.map +1 -0
- package/dist/host/__tests__/errors.test.d.ts +2 -0
- package/dist/host/__tests__/errors.test.d.ts.map +1 -0
- package/dist/host/__tests__/errors.test.js +76 -0
- package/dist/host/__tests__/errors.test.js.map +1 -0
- package/dist/host/__tests__/pattern-comprehensive.test.d.ts +2 -0
- package/dist/host/__tests__/pattern-comprehensive.test.d.ts.map +1 -0
- package/dist/host/__tests__/pattern-comprehensive.test.js +732 -0
- package/dist/host/__tests__/pattern-comprehensive.test.js.map +1 -0
- package/dist/host/__tests__/pattern-matcher.test.d.ts +2 -0
- package/dist/host/__tests__/pattern-matcher.test.d.ts.map +1 -0
- package/dist/host/__tests__/pattern-matcher.test.js +251 -0
- package/dist/host/__tests__/pattern-matcher.test.js.map +1 -0
- package/dist/host/__tests__/router.test.d.ts +2 -0
- package/dist/host/__tests__/router.test.d.ts.map +1 -0
- package/dist/host/__tests__/router.test.js +241 -0
- package/dist/host/__tests__/router.test.js.map +1 -0
- package/dist/host/__tests__/testing.test.d.ts +2 -0
- package/dist/host/__tests__/testing.test.d.ts.map +1 -0
- package/dist/host/__tests__/testing.test.js +64 -0
- package/dist/host/__tests__/testing.test.js.map +1 -0
- package/dist/host/__tests__/utils.test.d.ts +2 -0
- package/dist/host/__tests__/utils.test.d.ts.map +1 -0
- package/dist/host/__tests__/utils.test.js +29 -0
- package/dist/host/__tests__/utils.test.js.map +1 -0
- package/dist/host/cookie-handler.d.ts +34 -0
- package/dist/host/cookie-handler.d.ts.map +1 -0
- package/dist/host/cookie-handler.js +124 -0
- package/dist/host/cookie-handler.js.map +1 -0
- package/dist/host/errors.d.ts +56 -0
- package/dist/host/errors.d.ts.map +1 -0
- package/dist/host/errors.js +79 -0
- package/dist/host/errors.js.map +1 -0
- package/dist/host/index.d.ts +29 -0
- package/dist/host/index.d.ts.map +1 -0
- package/dist/host/index.js +32 -0
- package/dist/host/index.js.map +1 -0
- package/dist/host/pattern-matcher.d.ts +36 -0
- package/dist/host/pattern-matcher.d.ts.map +1 -0
- package/dist/host/pattern-matcher.js +172 -0
- package/dist/host/pattern-matcher.js.map +1 -0
- package/dist/host/router.d.ts +26 -0
- package/dist/host/router.d.ts.map +1 -0
- package/dist/host/router.js +218 -0
- package/dist/host/router.js.map +1 -0
- package/dist/host/testing.d.ts +36 -0
- package/dist/host/testing.d.ts.map +1 -0
- package/dist/host/testing.js +55 -0
- package/dist/host/testing.js.map +1 -0
- package/dist/host/types.d.ts +115 -0
- package/dist/host/types.d.ts.map +1 -0
- package/dist/host/types.js +7 -0
- package/dist/host/types.js.map +1 -0
- package/dist/host/utils.d.ts +21 -0
- package/dist/host/utils.d.ts.map +1 -0
- package/dist/host/utils.js +23 -0
- package/dist/host/utils.js.map +1 -0
- package/dist/href-client.d.ts +131 -0
- package/dist/href-client.d.ts.map +1 -0
- package/dist/href-client.js +64 -0
- package/dist/href-client.js.map +1 -0
- package/{src/href-context.ts → dist/href-context.d.ts} +7 -11
- package/dist/href-context.d.ts.map +1 -0
- package/dist/href-context.js +21 -0
- package/dist/href-context.js.map +1 -0
- package/dist/index.d.ts +73 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +91 -0
- package/dist/index.js.map +1 -0
- package/dist/index.rsc.d.ts +32 -0
- package/dist/index.rsc.d.ts.map +1 -0
- package/dist/index.rsc.js +40 -0
- package/dist/index.rsc.js.map +1 -0
- package/dist/internal-debug.d.ts +2 -0
- package/dist/internal-debug.d.ts.map +1 -0
- package/dist/internal-debug.js +5 -0
- package/dist/internal-debug.js.map +1 -0
- package/dist/loader.d.ts +14 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +20 -0
- package/dist/loader.js.map +1 -0
- package/dist/loader.rsc.d.ts +19 -0
- package/dist/loader.rsc.d.ts.map +1 -0
- package/dist/loader.rsc.js +99 -0
- package/dist/loader.rsc.js.map +1 -0
- package/dist/network-error-thrower.d.ts +17 -0
- package/dist/network-error-thrower.d.ts.map +1 -0
- package/dist/network-error-thrower.js +14 -0
- package/dist/network-error-thrower.js.map +1 -0
- package/dist/outlet-context.d.ts +13 -0
- package/dist/outlet-context.d.ts.map +1 -0
- package/dist/outlet-context.js +3 -0
- package/dist/outlet-context.js.map +1 -0
- package/dist/prerender/__tests__/param-hash.test.d.ts +2 -0
- package/dist/prerender/__tests__/param-hash.test.d.ts.map +1 -0
- package/dist/prerender/__tests__/param-hash.test.js +148 -0
- package/dist/prerender/__tests__/param-hash.test.js.map +1 -0
- package/dist/prerender/param-hash.d.ts +16 -0
- package/dist/prerender/param-hash.d.ts.map +1 -0
- package/dist/prerender/param-hash.js +36 -0
- package/dist/prerender/param-hash.js.map +1 -0
- package/dist/prerender/store.d.ts +38 -0
- package/dist/prerender/store.d.ts.map +1 -0
- package/dist/prerender/store.js +61 -0
- package/dist/prerender/store.js.map +1 -0
- package/dist/prerender.d.ts +66 -0
- package/dist/prerender.d.ts.map +1 -0
- package/dist/prerender.js +57 -0
- package/dist/prerender.js.map +1 -0
- package/dist/reverse.d.ts +196 -0
- package/dist/reverse.d.ts.map +1 -0
- package/dist/reverse.js +78 -0
- package/dist/reverse.js.map +1 -0
- package/dist/root-error-boundary.d.ts +33 -0
- package/dist/root-error-boundary.d.ts.map +1 -0
- package/dist/root-error-boundary.js +165 -0
- package/dist/root-error-boundary.js.map +1 -0
- package/dist/route-content-wrapper.d.ts +46 -0
- package/dist/route-content-wrapper.d.ts.map +1 -0
- package/dist/route-content-wrapper.js +77 -0
- package/dist/route-content-wrapper.js.map +1 -0
- package/dist/route-definition.d.ts +421 -0
- package/dist/route-definition.d.ts.map +1 -0
- package/dist/route-definition.js +868 -0
- package/dist/route-definition.js.map +1 -0
- package/dist/route-map-builder.d.ts +155 -0
- package/dist/route-map-builder.d.ts.map +1 -0
- package/dist/route-map-builder.js +237 -0
- package/dist/route-map-builder.js.map +1 -0
- package/dist/route-types.d.ts +165 -0
- package/dist/route-types.d.ts.map +1 -0
- package/dist/route-types.js +7 -0
- package/dist/route-types.js.map +1 -0
- package/dist/router/__tests__/handler-context.test.d.ts +2 -0
- package/dist/router/__tests__/handler-context.test.d.ts.map +1 -0
- package/dist/router/__tests__/handler-context.test.js +65 -0
- package/dist/router/__tests__/handler-context.test.js.map +1 -0
- package/dist/router/__tests__/loader-cycle-detection.test.d.ts +2 -0
- package/dist/router/__tests__/loader-cycle-detection.test.d.ts.map +1 -0
- package/dist/router/__tests__/loader-cycle-detection.test.js +221 -0
- package/dist/router/__tests__/loader-cycle-detection.test.js.map +1 -0
- package/dist/router/__tests__/match-context.test.d.ts +2 -0
- package/dist/router/__tests__/match-context.test.d.ts.map +1 -0
- package/dist/router/__tests__/match-context.test.js +92 -0
- package/dist/router/__tests__/match-context.test.js.map +1 -0
- package/dist/router/__tests__/match-pipelines.test.d.ts +2 -0
- package/dist/router/__tests__/match-pipelines.test.d.ts.map +1 -0
- package/dist/router/__tests__/match-pipelines.test.js +417 -0
- package/dist/router/__tests__/match-pipelines.test.js.map +1 -0
- package/dist/router/__tests__/match-result.test.d.ts +2 -0
- package/dist/router/__tests__/match-result.test.d.ts.map +1 -0
- package/dist/router/__tests__/match-result.test.js +457 -0
- package/dist/router/__tests__/match-result.test.js.map +1 -0
- package/dist/router/__tests__/on-error.test.d.ts +2 -0
- package/dist/router/__tests__/on-error.test.d.ts.map +1 -0
- package/dist/router/__tests__/on-error.test.js +678 -0
- package/dist/router/__tests__/on-error.test.js.map +1 -0
- package/dist/router/__tests__/pattern-matching.test.d.ts +2 -0
- package/dist/router/__tests__/pattern-matching.test.d.ts.map +1 -0
- package/dist/router/__tests__/pattern-matching.test.js +629 -0
- package/dist/router/__tests__/pattern-matching.test.js.map +1 -0
- package/dist/router/__tests__/segment-resolution-parallel-loading.test.d.ts +2 -0
- package/dist/router/__tests__/segment-resolution-parallel-loading.test.d.ts.map +1 -0
- package/dist/router/__tests__/segment-resolution-parallel-loading.test.js +155 -0
- package/dist/router/__tests__/segment-resolution-parallel-loading.test.js.map +1 -0
- package/dist/router/error-handling.d.ts +77 -0
- package/dist/router/error-handling.d.ts.map +1 -0
- package/dist/router/error-handling.js +202 -0
- package/dist/router/error-handling.js.map +1 -0
- package/dist/router/handler-context.d.ts +20 -0
- package/dist/router/handler-context.d.ts.map +1 -0
- package/dist/router/handler-context.js +198 -0
- package/dist/router/handler-context.js.map +1 -0
- package/dist/router/intercept-resolution.d.ts +66 -0
- package/dist/router/intercept-resolution.d.ts.map +1 -0
- package/dist/router/intercept-resolution.js +246 -0
- package/dist/router/intercept-resolution.js.map +1 -0
- package/dist/router/loader-resolution.d.ts +64 -0
- package/dist/router/loader-resolution.d.ts.map +1 -0
- package/dist/router/loader-resolution.js +284 -0
- package/dist/router/loader-resolution.js.map +1 -0
- package/dist/router/logging.d.ts +15 -0
- package/dist/router/logging.d.ts.map +1 -0
- package/dist/router/logging.js +99 -0
- package/dist/router/logging.js.map +1 -0
- package/dist/router/manifest.d.ts +22 -0
- package/dist/router/manifest.d.ts.map +1 -0
- package/dist/router/manifest.js +181 -0
- package/dist/router/manifest.js.map +1 -0
- package/dist/router/match-api.d.ts +35 -0
- package/dist/router/match-api.d.ts.map +1 -0
- package/dist/router/match-api.js +406 -0
- package/dist/router/match-api.js.map +1 -0
- package/dist/router/match-context.d.ts +206 -0
- package/dist/router/match-context.d.ts.map +1 -0
- package/dist/router/match-context.js +17 -0
- package/dist/router/match-context.js.map +1 -0
- package/dist/router/match-middleware/background-revalidation.d.ts +127 -0
- package/dist/router/match-middleware/background-revalidation.d.ts.map +1 -0
- package/dist/router/match-middleware/background-revalidation.js +75 -0
- package/dist/router/match-middleware/background-revalidation.js.map +1 -0
- package/dist/router/match-middleware/cache-lookup.d.ts +112 -0
- package/dist/router/match-middleware/cache-lookup.d.ts.map +1 -0
- package/dist/router/match-middleware/cache-lookup.js +257 -0
- package/dist/router/match-middleware/cache-lookup.js.map +1 -0
- package/dist/router/match-middleware/cache-store.d.ts +113 -0
- package/dist/router/match-middleware/cache-store.d.ts.map +1 -0
- package/dist/router/match-middleware/cache-store.js +108 -0
- package/dist/router/match-middleware/cache-store.js.map +1 -0
- package/dist/router/match-middleware/index.d.ts +81 -0
- package/dist/router/match-middleware/index.d.ts.map +1 -0
- package/dist/router/match-middleware/index.js +80 -0
- package/dist/router/match-middleware/index.js.map +1 -0
- package/dist/router/match-middleware/intercept-resolution.d.ts +117 -0
- package/dist/router/match-middleware/intercept-resolution.d.ts.map +1 -0
- package/dist/router/match-middleware/intercept-resolution.js +134 -0
- package/dist/router/match-middleware/intercept-resolution.js.map +1 -0
- package/dist/router/match-middleware/segment-resolution.d.ts +99 -0
- package/dist/router/match-middleware/segment-resolution.d.ts.map +1 -0
- package/dist/router/match-middleware/segment-resolution.js +53 -0
- package/dist/router/match-middleware/segment-resolution.js.map +1 -0
- package/dist/router/match-pipelines.d.ts +147 -0
- package/dist/router/match-pipelines.d.ts.map +1 -0
- package/dist/router/match-pipelines.js +82 -0
- package/dist/router/match-pipelines.js.map +1 -0
- package/dist/router/match-result.d.ts +126 -0
- package/dist/router/match-result.d.ts.map +1 -0
- package/dist/router/match-result.js +93 -0
- package/dist/router/match-result.js.map +1 -0
- package/dist/router/metrics.d.ts +20 -0
- package/dist/router/metrics.d.ts.map +1 -0
- package/dist/router/metrics.js +47 -0
- package/dist/router/metrics.js.map +1 -0
- package/dist/router/middleware.d.ts +249 -0
- package/dist/router/middleware.d.ts.map +1 -0
- package/dist/router/middleware.js +434 -0
- package/dist/router/middleware.js.map +1 -0
- package/dist/router/middleware.test.d.ts +2 -0
- package/dist/router/middleware.test.d.ts.map +1 -0
- package/dist/router/middleware.test.js +816 -0
- package/dist/router/middleware.test.js.map +1 -0
- package/dist/router/pattern-matching.d.ts +149 -0
- package/dist/router/pattern-matching.d.ts.map +1 -0
- package/dist/router/pattern-matching.js +349 -0
- package/dist/router/pattern-matching.js.map +1 -0
- package/dist/router/revalidation.d.ts +44 -0
- package/dist/router/revalidation.d.ts.map +1 -0
- package/dist/router/revalidation.js +147 -0
- package/dist/router/revalidation.js.map +1 -0
- package/dist/router/router-context.d.ts +135 -0
- package/dist/router/router-context.d.ts.map +1 -0
- package/dist/router/router-context.js +36 -0
- package/dist/router/router-context.js.map +1 -0
- package/dist/router/segment-resolution.d.ts +127 -0
- package/dist/router/segment-resolution.d.ts.map +1 -0
- package/dist/router/segment-resolution.js +919 -0
- package/dist/router/segment-resolution.js.map +1 -0
- package/dist/router/trie-matching.d.ts +40 -0
- package/dist/router/trie-matching.d.ts.map +1 -0
- package/dist/router/trie-matching.js +127 -0
- package/dist/router/trie-matching.js.map +1 -0
- package/dist/router/types.d.ts +136 -0
- package/dist/router/types.d.ts.map +1 -0
- package/dist/router/types.js +7 -0
- package/dist/router/types.js.map +1 -0
- package/dist/router.d.ts +753 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.gen.d.ts +6 -0
- package/dist/router.gen.d.ts.map +1 -0
- package/dist/router.gen.js +6 -0
- package/dist/router.gen.js.map +1 -0
- package/dist/router.js +1304 -0
- package/dist/router.js.map +1 -0
- package/dist/rsc/__tests__/helpers.test.d.ts +2 -0
- package/dist/rsc/__tests__/helpers.test.d.ts.map +1 -0
- package/dist/rsc/__tests__/helpers.test.js +140 -0
- package/dist/rsc/__tests__/helpers.test.js.map +1 -0
- package/dist/rsc/handler.d.ts +45 -0
- package/dist/rsc/handler.d.ts.map +1 -0
- package/dist/rsc/handler.js +1172 -0
- package/dist/rsc/handler.js.map +1 -0
- package/dist/rsc/helpers.d.ts +16 -0
- package/dist/rsc/helpers.d.ts.map +1 -0
- package/dist/rsc/helpers.js +55 -0
- package/dist/rsc/helpers.js.map +1 -0
- package/dist/rsc/index.d.ts +22 -0
- package/dist/rsc/index.d.ts.map +1 -0
- package/dist/rsc/index.js +23 -0
- package/dist/rsc/index.js.map +1 -0
- package/dist/rsc/nonce.d.ts +9 -0
- package/dist/rsc/nonce.d.ts.map +1 -0
- package/dist/rsc/nonce.js +18 -0
- package/dist/rsc/nonce.js.map +1 -0
- package/dist/rsc/types.d.ts +206 -0
- package/dist/rsc/types.d.ts.map +1 -0
- package/dist/rsc/types.js +8 -0
- package/dist/rsc/types.js.map +1 -0
- package/dist/search-params.d.ts +103 -0
- package/dist/search-params.d.ts.map +1 -0
- package/dist/search-params.js +74 -0
- package/dist/search-params.js.map +1 -0
- package/dist/segment-system.d.ts +75 -0
- package/dist/segment-system.d.ts.map +1 -0
- package/dist/segment-system.js +336 -0
- package/dist/segment-system.js.map +1 -0
- package/dist/server/context.d.ts +245 -0
- package/dist/server/context.d.ts.map +1 -0
- package/dist/server/context.js +197 -0
- package/dist/server/context.js.map +1 -0
- package/dist/server/fetchable-loader-store.d.ts +18 -0
- package/dist/server/fetchable-loader-store.d.ts.map +1 -0
- package/dist/server/fetchable-loader-store.js +18 -0
- package/dist/server/fetchable-loader-store.js.map +1 -0
- package/dist/server/handle-store.d.ts +85 -0
- package/dist/server/handle-store.d.ts.map +1 -0
- package/dist/server/handle-store.js +142 -0
- package/dist/server/handle-store.js.map +1 -0
- package/dist/server/loader-registry.d.ts +55 -0
- package/dist/server/loader-registry.d.ts.map +1 -0
- package/dist/server/loader-registry.js +132 -0
- package/dist/server/loader-registry.js.map +1 -0
- package/dist/server/request-context.d.ts +226 -0
- package/dist/server/request-context.d.ts.map +1 -0
- package/dist/server/request-context.js +290 -0
- package/dist/server/request-context.js.map +1 -0
- package/dist/server/root-layout.d.ts +4 -0
- package/dist/server/root-layout.d.ts.map +1 -0
- package/dist/server/root-layout.js +5 -0
- package/dist/server/root-layout.js.map +1 -0
- package/dist/server.d.ts +15 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +20 -0
- package/dist/server.js.map +1 -0
- package/dist/ssr/__tests__/ssr-handler.test.d.ts +2 -0
- package/dist/ssr/__tests__/ssr-handler.test.d.ts.map +1 -0
- package/dist/ssr/__tests__/ssr-handler.test.js +132 -0
- package/dist/ssr/__tests__/ssr-handler.test.js.map +1 -0
- package/dist/ssr/index.d.ts +98 -0
- package/dist/ssr/index.d.ts.map +1 -0
- package/dist/ssr/index.js +158 -0
- package/dist/ssr/index.js.map +1 -0
- package/dist/static-handler.d.ts +50 -0
- package/dist/static-handler.d.ts.map +1 -0
- package/dist/static-handler.gen.d.ts +5 -0
- package/dist/static-handler.gen.d.ts.map +1 -0
- package/dist/static-handler.gen.js +5 -0
- package/dist/static-handler.gen.js.map +1 -0
- package/dist/static-handler.js +29 -0
- package/dist/static-handler.js.map +1 -0
- package/dist/testing/vitest.js +82 -0
- package/dist/theme/ThemeProvider.d.ts +20 -0
- package/dist/theme/ThemeProvider.d.ts.map +1 -0
- package/dist/theme/ThemeProvider.js +240 -0
- package/dist/theme/ThemeProvider.js.map +1 -0
- package/dist/theme/ThemeScript.d.ts +48 -0
- package/dist/theme/ThemeScript.d.ts.map +1 -0
- package/dist/theme/ThemeScript.js +13 -0
- package/dist/theme/ThemeScript.js.map +1 -0
- package/dist/theme/__tests__/theme.test.d.ts +2 -0
- package/dist/theme/__tests__/theme.test.d.ts.map +1 -0
- package/dist/theme/__tests__/theme.test.js +103 -0
- package/dist/theme/__tests__/theme.test.js.map +1 -0
- package/dist/theme/constants.d.ts +29 -0
- package/dist/theme/constants.d.ts.map +1 -0
- package/dist/theme/constants.js +48 -0
- package/dist/theme/constants.js.map +1 -0
- package/dist/theme/index.d.ts +31 -0
- package/dist/theme/index.d.ts.map +1 -0
- package/dist/theme/index.js +36 -0
- package/dist/theme/index.js.map +1 -0
- package/dist/theme/theme-context.d.ts +40 -0
- package/dist/theme/theme-context.d.ts.map +1 -0
- package/dist/theme/theme-context.js +60 -0
- package/dist/theme/theme-context.js.map +1 -0
- package/dist/theme/theme-script.d.ts +27 -0
- package/dist/theme/theme-script.d.ts.map +1 -0
- package/dist/theme/theme-script.js +147 -0
- package/dist/theme/theme-script.js.map +1 -0
- package/dist/theme/types.d.ts +163 -0
- package/dist/theme/types.d.ts.map +1 -0
- package/dist/theme/types.js +11 -0
- package/dist/theme/types.js.map +1 -0
- package/dist/theme/use-theme.d.ts +12 -0
- package/dist/theme/use-theme.d.ts.map +1 -0
- package/dist/theme/use-theme.js +40 -0
- package/dist/theme/use-theme.js.map +1 -0
- package/dist/types.d.ts +1479 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -0
- package/dist/urls.d.ts +441 -0
- package/dist/urls.d.ts.map +1 -0
- package/dist/urls.gen.d.ts +8 -0
- package/dist/urls.gen.d.ts.map +1 -0
- package/dist/urls.gen.js +8 -0
- package/dist/urls.gen.js.map +1 -0
- package/dist/urls.js +443 -0
- package/dist/urls.js.map +1 -0
- package/dist/use-loader.d.ts +127 -0
- package/dist/use-loader.d.ts.map +1 -0
- package/dist/use-loader.js +237 -0
- package/dist/use-loader.js.map +1 -0
- package/dist/vite/__tests__/ast-handler-extract.test.d.ts +2 -0
- package/dist/vite/__tests__/ast-handler-extract.test.d.ts.map +1 -0
- package/dist/vite/__tests__/ast-handler-extract.test.js +294 -0
- package/dist/vite/__tests__/ast-handler-extract.test.js.map +1 -0
- package/dist/vite/__tests__/expose-id-utils.test.d.ts +2 -0
- package/dist/vite/__tests__/expose-id-utils.test.d.ts.map +1 -0
- package/dist/vite/__tests__/expose-id-utils.test.js +224 -0
- package/dist/vite/__tests__/expose-id-utils.test.js.map +1 -0
- package/dist/vite/__tests__/expose-internal-ids.test.d.ts +2 -0
- package/dist/vite/__tests__/expose-internal-ids.test.d.ts.map +1 -0
- package/dist/vite/__tests__/expose-internal-ids.test.js +647 -0
- package/dist/vite/__tests__/expose-internal-ids.test.js.map +1 -0
- package/dist/vite/__tests__/expose-router-id.test.d.ts +2 -0
- package/dist/vite/__tests__/expose-router-id.test.d.ts.map +1 -0
- package/dist/vite/__tests__/expose-router-id.test.js +39 -0
- package/dist/vite/__tests__/expose-router-id.test.js.map +1 -0
- package/dist/vite/ast-handler-extract.d.ts +49 -0
- package/dist/vite/ast-handler-extract.d.ts.map +1 -0
- package/dist/vite/ast-handler-extract.js +249 -0
- package/dist/vite/ast-handler-extract.js.map +1 -0
- package/dist/vite/expose-action-id.d.ts +19 -0
- package/dist/vite/expose-action-id.d.ts.map +1 -0
- package/dist/vite/expose-action-id.js +250 -0
- package/dist/vite/expose-action-id.js.map +1 -0
- package/dist/vite/expose-id-utils.d.ts +69 -0
- package/dist/vite/expose-id-utils.d.ts.map +1 -0
- package/dist/vite/expose-id-utils.js +289 -0
- package/dist/vite/expose-id-utils.js.map +1 -0
- package/dist/vite/expose-internal-ids.d.ts +22 -0
- package/dist/vite/expose-internal-ids.d.ts.map +1 -0
- package/dist/vite/expose-internal-ids.js +886 -0
- package/dist/vite/expose-internal-ids.js.map +1 -0
- package/dist/vite/index.d.ts +149 -0
- package/dist/vite/index.d.ts.map +1 -0
- package/dist/vite/index.js +5994 -2763
- package/dist/vite/index.js.bak +5448 -0
- package/dist/vite/index.js.map +1 -0
- package/dist/vite/index.named-routes.gen.ts +103 -0
- package/dist/vite/package-resolution.d.ts +43 -0
- package/dist/vite/package-resolution.d.ts.map +1 -0
- package/{src/vite/package-resolution.ts → dist/vite/package-resolution.js} +53 -66
- package/dist/vite/package-resolution.js.map +1 -0
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/dist/vite/virtual-entries.d.ts +25 -0
- package/dist/vite/virtual-entries.d.ts.map +1 -0
- package/{src/vite/virtual-entries.ts → dist/vite/virtual-entries.js} +12 -16
- package/dist/vite/virtual-entries.js.map +1 -0
- package/package.json +64 -54
- package/skills/api-client/SKILL.md +211 -0
- package/skills/breadcrumbs/SKILL.md +252 -0
- package/skills/bundle-analysis/SKILL.md +159 -0
- package/skills/cache-guide/SKILL.md +484 -0
- package/skills/caching/SKILL.md +202 -24
- package/skills/composability/SKILL.md +197 -0
- package/skills/css/SKILL.md +76 -0
- package/skills/debug-manifest/SKILL.md +12 -8
- 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 +537 -70
- package/skills/host-router/SKILL.md +264 -0
- package/skills/i18n/SKILL.md +276 -0
- package/skills/intercept/SKILL.md +173 -8
- package/skills/layout/SKILL.md +123 -5
- package/skills/links/SKILL.md +304 -25
- package/skills/loader/SKILL.md +600 -54
- package/skills/middleware/SKILL.md +211 -37
- package/skills/migrate-nextjs/SKILL.md +562 -0
- package/skills/migrate-react-router/SKILL.md +769 -0
- package/skills/mime-routes/SKILL.md +41 -10
- package/skills/observability/SKILL.md +137 -0
- package/skills/parallel/SKILL.md +271 -3
- package/skills/prerender/SKILL.md +413 -52
- package/skills/rango/SKILL.md +301 -21
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +248 -120
- package/skills/route/SKILL.md +279 -21
- package/skills/router-setup/SKILL.md +211 -33
- package/skills/server-actions/SKILL.md +751 -0
- package/skills/streams-and-websockets/SKILL.md +283 -0
- package/skills/tailwind/SKILL.md +27 -3
- package/skills/theme/SKILL.md +9 -8
- package/skills/typesafety/SKILL.md +547 -107
- package/skills/use-cache/SKILL.md +353 -0
- package/skills/view-transitions/SKILL.md +294 -0
- package/src/__augment-tests__/augment.ts +81 -0
- package/src/__augment-tests__/augmented.check.ts +116 -0
- package/src/__internal.ts +102 -4
- package/src/bin/rango.ts +312 -15
- package/src/browser/action-coordinator.ts +114 -0
- package/src/browser/app-shell.ts +39 -0
- package/src/browser/app-version.ts +14 -0
- package/src/browser/event-controller.ts +172 -128
- 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/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 +309 -562
- package/src/browser/navigation-client.ts +206 -75
- package/src/browser/navigation-store.ts +80 -63
- package/src/browser/navigation-transaction.ts +279 -0
- package/src/browser/network-error-handler.ts +61 -0
- package/src/browser/partial-update.ts +355 -314
- package/src/browser/prefetch/cache.ts +363 -0
- package/src/browser/prefetch/fetch.ts +350 -0
- package/src/browser/prefetch/observer.ts +65 -0
- package/src/browser/prefetch/policy.ts +48 -0
- package/src/browser/prefetch/queue.ts +191 -0
- package/src/browser/prefetch/resource-ready.ts +77 -0
- package/src/browser/rango-state.ts +136 -0
- package/src/browser/react/Link.tsx +255 -71
- package/src/browser/react/NavigationProvider.tsx +153 -33
- package/src/browser/react/context.ts +11 -0
- package/src/browser/react/filter-segment-order.ts +55 -0
- package/src/browser/react/index.ts +15 -12
- package/src/browser/react/location-state-shared.ts +269 -56
- package/src/browser/react/location-state.ts +90 -19
- 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 +29 -51
- package/src/browser/react/use-client-cache.ts +5 -3
- package/src/browser/react/use-handle.ts +41 -123
- package/src/browser/react/use-link-status.ts +6 -5
- package/src/browser/react/use-navigation.ts +44 -65
- package/src/browser/react/use-params.ts +77 -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 +97 -0
- package/src/browser/react/use-search-params.ts +56 -0
- package/src/browser/react/use-segments.ts +85 -99
- package/src/browser/response-adapter.ts +124 -0
- package/src/browser/rsc-router.tsx +275 -72
- package/src/browser/scroll-restoration.ts +132 -49
- package/src/browser/segment-reconciler.ts +243 -0
- package/src/browser/segment-structure-assert.ts +17 -1
- package/src/browser/server-action-bridge.ts +508 -610
- package/src/browser/shallow.ts +6 -1
- package/src/browser/types.ts +149 -48
- package/src/browser/validate-redirect-origin.ts +29 -0
- package/src/build/collect-fallback-refs.ts +107 -0
- package/src/build/generate-manifest.ts +123 -56
- package/src/build/generate-route-types.ts +41 -1029
- package/src/build/index.ts +4 -0
- package/src/build/prefix-tree-utils.ts +123 -0
- package/src/build/route-trie.ts +127 -31
- package/src/build/route-types/ast-helpers.ts +25 -0
- package/src/build/route-types/ast-route-extraction.ts +98 -0
- package/src/build/route-types/codegen.ts +102 -0
- package/src/build/route-types/include-resolution.ts +418 -0
- package/src/build/route-types/param-extraction.ts +48 -0
- package/src/build/route-types/per-module-writer.ts +131 -0
- package/src/build/route-types/router-processing.ts +659 -0
- package/src/build/route-types/scan-filter.ts +85 -0
- package/src/build/route-types/source-scan.ts +118 -0
- package/src/build/runtime-discovery.ts +220 -0
- package/src/cache/background-task.ts +34 -0
- package/src/cache/cache-key-utils.ts +44 -0
- package/src/cache/cache-policy.ts +125 -0
- package/src/cache/cache-runtime.ts +354 -0
- package/src/cache/cache-scope.ts +170 -308
- package/src/cache/cf/cf-cache-store.ts +696 -30
- package/src/cache/cf/index.ts +13 -3
- package/src/cache/document-cache.ts +116 -77
- package/src/cache/handle-capture.ts +81 -0
- package/src/cache/handle-snapshot.ts +144 -0
- package/src/cache/index.ts +1 -15
- package/src/cache/memory-segment-store.ts +192 -13
- package/src/cache/profile-registry.ts +73 -0
- package/src/cache/read-through-swr.ts +134 -0
- package/src/cache/segment-codec.ts +256 -0
- package/src/cache/taint.ts +153 -0
- package/src/cache/types.ts +78 -124
- package/src/client.rsc.tsx +6 -1
- package/src/client.tsx +117 -322
- package/src/component-utils.ts +4 -4
- package/src/components/DefaultDocument.tsx +5 -1
- package/src/context-var.ts +156 -0
- package/src/debug.ts +19 -9
- package/src/decode-loader-results.ts +36 -0
- package/src/errors.ts +106 -10
- package/src/handle.ts +54 -11
- package/src/handles/MetaTags.tsx +73 -20
- package/src/handles/breadcrumbs.ts +66 -0
- package/src/handles/index.ts +1 -0
- package/src/handles/meta.ts +30 -13
- package/src/host/cookie-handler.ts +21 -15
- package/src/host/errors.ts +8 -8
- package/src/host/index.ts +6 -9
- package/src/host/pattern-matcher.ts +27 -27
- package/src/host/router.ts +176 -82
- package/src/host/testing.ts +8 -8
- package/src/host/types.ts +46 -9
- package/src/host/utils.ts +2 -2
- package/src/href-client.ts +196 -57
- package/src/index.rsc.ts +112 -42
- package/src/index.ts +178 -74
- package/src/internal-debug.ts +9 -3
- package/src/loader-store.ts +500 -0
- package/src/loader.rsc.ts +15 -93
- package/src/loader.ts +20 -10
- package/src/missing-id-error.ts +68 -0
- package/src/network-error-thrower.tsx +3 -1
- package/src/outlet-context.ts +1 -1
- package/src/outlet-provider.tsx +45 -0
- package/src/prerender/param-hash.ts +4 -2
- package/src/prerender/store.ts +125 -18
- package/src/prerender.ts +389 -23
- package/src/response-utils.ts +37 -0
- package/src/reverse.ts +198 -128
- package/src/root-error-boundary.tsx +41 -29
- package/src/route-content-wrapper.tsx +13 -32
- package/src/route-definition/dsl-helpers.ts +1109 -0
- package/src/route-definition/helper-factories.ts +90 -0
- package/src/route-definition/helpers-types.ts +506 -0
- package/src/route-definition/index.ts +55 -0
- package/src/route-definition/redirect.ts +101 -0
- package/src/route-definition/resolve-handler-use.ts +155 -0
- package/src/route-definition/use-item-types.ts +32 -0
- package/src/route-definition.ts +1 -1450
- package/src/route-map-builder.ts +87 -133
- package/src/route-name.ts +53 -0
- package/src/route-types.ts +72 -41
- package/src/router/content-negotiation.ts +228 -0
- package/src/router/debug-manifest.ts +72 -0
- package/src/router/error-handling.ts +10 -10
- package/src/router/find-match.ts +208 -0
- package/src/router/handler-context.ts +372 -125
- package/src/router/intercept-resolution.ts +24 -26
- package/src/router/lazy-includes.ts +256 -0
- package/src/router/loader-resolution.ts +367 -140
- package/src/router/logging.ts +112 -6
- package/src/router/manifest.ts +89 -28
- package/src/router/match-api.ts +175 -238
- package/src/router/match-context.ts +4 -2
- package/src/router/match-handlers.ts +441 -0
- package/src/router/match-middleware/background-revalidation.ts +97 -89
- package/src/router/match-middleware/cache-lookup.ts +289 -54
- package/src/router/match-middleware/cache-store.ts +78 -17
- package/src/router/match-middleware/intercept-resolution.ts +45 -22
- package/src/router/match-middleware/segment-resolution.ts +73 -9
- package/src/router/match-pipelines.ts +10 -45
- package/src/router/match-result.ts +146 -24
- package/src/router/metrics.ts +241 -16
- package/src/router/middleware-cookies.ts +55 -0
- package/src/router/middleware-types.ts +209 -0
- package/src/router/middleware.ts +354 -384
- package/src/router/navigation-snapshot.ts +182 -0
- package/src/router/pattern-matching.ts +279 -44
- package/src/router/prerender-match.ts +527 -0
- package/src/router/preview-match.ts +100 -0
- package/src/router/request-classification.ts +313 -0
- package/src/router/revalidation.ts +163 -16
- package/src/router/route-snapshot.ts +245 -0
- package/src/router/router-context.ts +41 -21
- package/src/router/router-interfaces.ts +500 -0
- package/src/router/router-options.ts +642 -0
- package/src/router/router-registry.ts +21 -0
- package/src/router/segment-resolution/fresh.ts +769 -0
- package/src/router/segment-resolution/helpers.ts +268 -0
- package/src/router/segment-resolution/loader-cache.ts +199 -0
- package/src/router/segment-resolution/revalidation.ts +1420 -0
- package/src/router/segment-resolution/static-store.ts +81 -0
- package/src/router/segment-resolution/view-transition-default.ts +36 -0
- package/src/router/segment-resolution.ts +21 -1354
- package/src/router/segment-wrappers.ts +291 -0
- package/src/router/substitute-pattern-params.ts +56 -0
- package/src/router/telemetry-otel.ts +299 -0
- package/src/router/telemetry.ts +300 -0
- package/src/router/timeout.ts +148 -0
- package/src/router/trie-matching.ts +133 -42
- package/src/router/types.ts +24 -9
- package/src/router/url-params.ts +49 -0
- package/src/router.ts +710 -2373
- package/src/rsc/handler-context.ts +45 -0
- package/src/rsc/handler.ts +821 -1128
- package/src/rsc/helpers.ts +182 -19
- package/src/rsc/index.ts +1 -21
- package/src/rsc/loader-fetch.ts +229 -0
- package/src/rsc/manifest-init.ts +77 -0
- package/src/rsc/nonce.ts +14 -0
- package/src/rsc/origin-guard.ts +161 -0
- package/src/rsc/progressive-enhancement.ts +395 -0
- package/src/rsc/response-error.ts +104 -0
- package/src/rsc/response-route-handler.ts +362 -0
- package/src/rsc/rsc-rendering.ts +240 -0
- package/src/rsc/runtime-warnings.ts +41 -0
- package/src/rsc/server-action.ts +350 -0
- package/src/rsc/ssr-setup.ts +144 -0
- package/src/rsc/types.ts +52 -11
- package/src/search-params.ts +70 -58
- package/src/segment-content-promise.ts +67 -0
- package/src/segment-loader-promise.ts +122 -0
- package/src/segment-system.tsx +237 -73
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +439 -85
- package/src/server/cookie-store.ts +214 -0
- package/src/server/fetchable-loader-store.ts +11 -6
- package/src/server/handle-store.ts +113 -15
- package/src/server/loader-registry.ts +24 -64
- package/src/server/request-context.ts +640 -107
- package/src/server.ts +26 -164
- package/src/ssr/index.tsx +107 -30
- package/src/static-handler.ts +39 -9
- package/src/theme/ThemeProvider.tsx +21 -15
- package/src/theme/ThemeScript.tsx +5 -5
- package/src/theme/constants.ts +5 -2
- package/src/theme/index.ts +4 -14
- package/src/theme/theme-context.ts +4 -30
- package/src/theme/theme-script.ts +21 -18
- package/src/types/boundaries.ts +158 -0
- package/src/types/cache-types.ts +198 -0
- package/src/types/error-types.ts +192 -0
- package/src/types/global-namespace.ts +113 -0
- package/src/types/handler-context.ts +809 -0
- package/src/types/index.ts +89 -0
- package/src/types/loader-types.ts +212 -0
- package/src/types/request-scope.ts +126 -0
- package/src/types/route-config.ts +170 -0
- package/src/types/route-entry.ts +120 -0
- package/src/types/segments.ts +184 -0
- package/src/types.ts +1 -1795
- package/src/urls/include-helper.ts +164 -0
- package/src/urls/index.ts +49 -0
- package/src/urls/path-helper-types.ts +386 -0
- package/src/urls/path-helper.ts +329 -0
- package/src/urls/pattern-types.ts +124 -0
- package/src/urls/response-types.ts +109 -0
- package/src/urls/type-extraction.ts +291 -0
- package/src/urls/urls-function.ts +94 -0
- package/src/urls.ts +1 -1323
- package/src/use-loader.tsx +559 -108
- package/src/vite/debug.ts +185 -0
- package/src/vite/discovery/bundle-postprocess.ts +181 -0
- package/src/vite/discovery/discover-routers.ts +379 -0
- package/src/vite/discovery/discovery-errors.ts +194 -0
- package/src/vite/discovery/gate-state.ts +171 -0
- package/src/vite/discovery/prerender-collection.ts +480 -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 +150 -0
- package/src/vite/discovery/virtual-module-codegen.ts +193 -0
- package/src/vite/index.ts +17 -2261
- package/src/vite/plugin-types.ts +170 -0
- package/src/vite/plugins/cjs-to-esm.ts +94 -0
- package/src/vite/plugins/client-ref-dedup.ts +131 -0
- package/src/vite/plugins/client-ref-hashing.ts +128 -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 +214 -0
- package/src/vite/{expose-action-id.ts → plugins/expose-action-id.ts} +109 -60
- package/src/vite/{expose-id-utils.ts → plugins/expose-id-utils.ts} +32 -51
- package/src/vite/plugins/expose-ids/export-analysis.ts +376 -0
- package/src/vite/plugins/expose-ids/handler-transform.ts +156 -0
- package/src/vite/plugins/expose-ids/loader-transform.ts +72 -0
- package/src/vite/plugins/expose-ids/router-transform.ts +127 -0
- package/src/vite/plugins/expose-ids/types.ts +45 -0
- package/src/vite/plugins/expose-internal-ids.ts +796 -0
- package/src/vite/plugins/performance-tracks.ts +92 -0
- package/src/vite/plugins/refresh-cmd.ts +127 -0
- package/src/vite/plugins/use-cache-transform.ts +338 -0
- package/src/vite/plugins/version-injector.ts +99 -0
- package/src/vite/plugins/version-plugin.ts +323 -0
- package/src/vite/plugins/virtual-entries.ts +123 -0
- package/src/vite/plugins/virtual-stub-plugin.ts +29 -0
- package/src/vite/rango.ts +549 -0
- package/src/vite/router-discovery.ts +1567 -0
- package/src/vite/{ast-handler-extract.ts → utils/ast-handler-extract.ts} +194 -22
- package/src/vite/utils/banner.ts +36 -0
- package/src/vite/utils/bundle-analysis.ts +139 -0
- package/src/vite/utils/client-chunks.ts +190 -0
- package/src/vite/utils/forward-user-plugins.ts +193 -0
- package/src/vite/utils/manifest-utils.ts +19 -0
- package/src/vite/utils/package-resolution.ts +161 -0
- package/src/vite/utils/prerender-utils.ts +222 -0
- package/src/vite/utils/shared-utils.ts +251 -0
- package/CLAUDE.md +0 -43
- package/src/browser/lru-cache.ts +0 -69
- package/src/browser/request-controller.ts +0 -164
- package/src/cache/memory-store.ts +0 -253
- 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/{version.d.ts → plugins/version.d.ts} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/// <reference path="../../vite/version.d.ts" />
|
|
1
|
+
/// <reference path="../../vite/plugins/version.d.ts" />
|
|
2
2
|
|
|
3
3
|
// Extend CacheStorage with Cloudflare's default cache property
|
|
4
4
|
declare global {
|
|
@@ -10,14 +10,21 @@ declare global {
|
|
|
10
10
|
/**
|
|
11
11
|
* Cloudflare Edge Cache Store
|
|
12
12
|
*
|
|
13
|
-
* Production cache store using Cloudflare's Cache API
|
|
14
|
-
*
|
|
13
|
+
* Production cache store using Cloudflare's Cache API (L1) with optional
|
|
14
|
+
* KV persistence (L2).
|
|
15
|
+
*
|
|
16
|
+
* L1 (Cache API): Per-colo, fast, ephemeral. Handles SWR atomically.
|
|
17
|
+
* L2 (KV): Global, persistent, ~50ms reads. Auto-warms cold colos.
|
|
18
|
+
*
|
|
19
|
+
* Read flow: L1 hit → serve | L1 miss → L2 hit → serve + promote to L1 | both miss → render
|
|
20
|
+
* Write flow: L1 write + L2 write (both via waitUntil)
|
|
15
21
|
*
|
|
16
22
|
* Features:
|
|
17
23
|
* - Extended TTL for SWR window (max-age = ttl + swr)
|
|
18
24
|
* - Staleness via x-edge-cache-stale-at header
|
|
19
|
-
* - Atomic REVALIDATING status for thundering herd prevention
|
|
25
|
+
* - Atomic REVALIDATING status for thundering herd prevention (L1 only)
|
|
20
26
|
* - Non-blocking writes via waitUntil
|
|
27
|
+
* - KV L2 for cross-colo cache persistence
|
|
21
28
|
*/
|
|
22
29
|
|
|
23
30
|
import type {
|
|
@@ -25,12 +32,19 @@ import type {
|
|
|
25
32
|
CachedEntryData,
|
|
26
33
|
CacheDefaults,
|
|
27
34
|
CacheGetResult,
|
|
35
|
+
CacheItemResult,
|
|
36
|
+
CacheItemOptions,
|
|
28
37
|
} from "../types.js";
|
|
29
38
|
import {
|
|
30
|
-
|
|
39
|
+
_getRequestContext,
|
|
31
40
|
type RequestContext,
|
|
32
41
|
} from "../../server/request-context.js";
|
|
33
42
|
import { VERSION } from "@rangojs/router:version";
|
|
43
|
+
import {
|
|
44
|
+
resolveTtl,
|
|
45
|
+
resolveSwrWindow,
|
|
46
|
+
DEFAULT_FUNCTION_TTL,
|
|
47
|
+
} from "../cache-policy.js";
|
|
34
48
|
|
|
35
49
|
// ============================================================================
|
|
36
50
|
// Constants
|
|
@@ -42,6 +56,15 @@ export const CACHE_STALE_AT_HEADER = "x-edge-cache-stale-at";
|
|
|
42
56
|
/** Header storing cache status: HIT | REVALIDATING */
|
|
43
57
|
export const CACHE_STATUS_HEADER = "x-edge-cache-status";
|
|
44
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Header stashing the route author's original Cache-Control on L1 document
|
|
61
|
+
* entries. putResponse/promoteResponseToL1 overwrite Cache-Control with a long
|
|
62
|
+
* `max-age` so the CF Cache API retains the entry across the whole SWR window;
|
|
63
|
+
* getResponse restores this original value before serving so the client and any
|
|
64
|
+
* upstream CDN see the author's intended directive, not the internal edge TTL.
|
|
65
|
+
*/
|
|
66
|
+
const CACHE_ORIG_CC_HEADER = "x-edge-cache-orig-cc";
|
|
67
|
+
|
|
45
68
|
/**
|
|
46
69
|
* Maximum age in seconds for REVALIDATING status before allowing new revalidation.
|
|
47
70
|
* After this period, a stale entry in REVALIDATING status will trigger revalidation again.
|
|
@@ -49,16 +72,84 @@ export const CACHE_STATUS_HEADER = "x-edge-cache-status";
|
|
|
49
72
|
*/
|
|
50
73
|
export const MAX_REVALIDATION_INTERVAL = 30;
|
|
51
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Maximum time (ms) to wait for an L1 edge cache (CF Cache API) read before
|
|
77
|
+
* giving up and treating it as a miss. The Cache API is normally sub-millisecond
|
|
78
|
+
* per-colo, so a slow `match` signals a degraded colo; we don't want it adding
|
|
79
|
+
* latency to the request. On timeout the lookup is abandoned, a warning is
|
|
80
|
+
* logged, and the read falls through to its normal miss path (L2/KV or render).
|
|
81
|
+
*/
|
|
82
|
+
export const EDGE_LOOKUP_TIMEOUT_MS = 10;
|
|
83
|
+
|
|
52
84
|
// ============================================================================
|
|
53
85
|
// Types
|
|
54
86
|
// ============================================================================
|
|
55
87
|
|
|
88
|
+
// Re-exported from the canonical home so cf-cache-store consumers keep
|
|
89
|
+
// importing `ExecutionContext` from this module without a second interface
|
|
90
|
+
// drifting over time.
|
|
91
|
+
export type { ExecutionContext } from "../../types/request-scope.js";
|
|
92
|
+
import type { ExecutionContext } from "../../types/request-scope.js";
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Minimal Cloudflare KV Namespace interface.
|
|
96
|
+
* Avoids hard dependency on @cloudflare/workers-types.
|
|
97
|
+
*/
|
|
98
|
+
export interface KVNamespace {
|
|
99
|
+
get(key: string, options?: { type?: string }): Promise<any>;
|
|
100
|
+
put(
|
|
101
|
+
key: string,
|
|
102
|
+
value: string,
|
|
103
|
+
options?: { expirationTtl?: number },
|
|
104
|
+
): Promise<void>;
|
|
105
|
+
delete(key: string): Promise<void>;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* KV envelope for segment cache entries.
|
|
110
|
+
* @internal
|
|
111
|
+
*/
|
|
112
|
+
interface KVSegmentEnvelope {
|
|
113
|
+
/** Cached segment data */
|
|
114
|
+
d: CachedEntryData;
|
|
115
|
+
/** When entry becomes stale (ms epoch) */
|
|
116
|
+
s: number;
|
|
117
|
+
/** When entry hard-expires (ms epoch) */
|
|
118
|
+
e: number;
|
|
119
|
+
}
|
|
120
|
+
|
|
56
121
|
/**
|
|
57
|
-
*
|
|
122
|
+
* KV envelope for function cache entries ("use cache").
|
|
123
|
+
* @internal
|
|
124
|
+
*/
|
|
125
|
+
interface KVItemEnvelope {
|
|
126
|
+
/** RSC-serialized return value */
|
|
127
|
+
v: string;
|
|
128
|
+
/** RSC-encoded handle data (see handle-snapshot.ts encodeHandles) */
|
|
129
|
+
h?: string;
|
|
130
|
+
/** When entry becomes stale (ms epoch) */
|
|
131
|
+
s: number;
|
|
132
|
+
/** When entry hard-expires (ms epoch) */
|
|
133
|
+
e: number;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* KV envelope for document cache entries.
|
|
138
|
+
* @internal
|
|
58
139
|
*/
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
140
|
+
interface KVResponseEnvelope {
|
|
141
|
+
/** Response body as base64-encoded string (safe for binary payloads) */
|
|
142
|
+
b: string;
|
|
143
|
+
/** HTTP status code */
|
|
144
|
+
st: number;
|
|
145
|
+
/** HTTP status text */
|
|
146
|
+
stx: string;
|
|
147
|
+
/** Serialized headers as key-value pairs */
|
|
148
|
+
hd: [string, string][];
|
|
149
|
+
/** When entry becomes stale (ms epoch) */
|
|
150
|
+
s: number;
|
|
151
|
+
/** When entry hard-expires (ms epoch) */
|
|
152
|
+
e: number;
|
|
62
153
|
}
|
|
63
154
|
|
|
64
155
|
export interface CFCacheStoreOptions<TEnv = unknown> {
|
|
@@ -91,11 +182,25 @@ export interface CFCacheStoreOptions<TEnv = unknown> {
|
|
|
91
182
|
*/
|
|
92
183
|
ctx: ExecutionContext;
|
|
93
184
|
|
|
185
|
+
/**
|
|
186
|
+
* Optional KV namespace for L2 cache persistence.
|
|
187
|
+
*
|
|
188
|
+
* When provided, KV acts as a global fallback behind the per-colo Cache API.
|
|
189
|
+
* On L1 miss, KV is checked and hits are promoted back to L1.
|
|
190
|
+
* On writes, data is persisted to both L1 and KV.
|
|
191
|
+
*
|
|
192
|
+
* @example
|
|
193
|
+
* ```typescript
|
|
194
|
+
* new CFCacheStore({ ctx: env.ctx, kv: env.CACHE_KV })
|
|
195
|
+
* ```
|
|
196
|
+
*/
|
|
197
|
+
kv?: KVNamespace;
|
|
198
|
+
|
|
94
199
|
/**
|
|
95
200
|
* Cache version string override. When this changes, all cached entries are
|
|
96
201
|
* effectively invalidated (new keys won't match old entries).
|
|
97
202
|
*
|
|
98
|
-
* Defaults to the auto-generated VERSION from
|
|
203
|
+
* Defaults to the auto-generated VERSION from the `@rangojs/router:version` virtual module.
|
|
99
204
|
* Only set this if you need a custom versioning strategy.
|
|
100
205
|
*/
|
|
101
206
|
version?: string;
|
|
@@ -124,7 +229,7 @@ export interface CFCacheStoreOptions<TEnv = unknown> {
|
|
|
124
229
|
* @example Using cookies for locale-aware caching
|
|
125
230
|
* ```typescript
|
|
126
231
|
* keyGenerator: (ctx, defaultKey) => {
|
|
127
|
-
* const locale =
|
|
232
|
+
* const locale = cookies().get('locale')?.value || 'en';
|
|
128
233
|
* return `${locale}:${defaultKey}`;
|
|
129
234
|
* }
|
|
130
235
|
* ```
|
|
@@ -153,9 +258,10 @@ export class CFCacheStore<TEnv = unknown> implements SegmentCacheStore<TEnv> {
|
|
|
153
258
|
) => string | Promise<string>;
|
|
154
259
|
|
|
155
260
|
private readonly namespace?: string;
|
|
156
|
-
private readonly
|
|
261
|
+
private readonly explicitBaseUrl?: string;
|
|
157
262
|
private readonly waitUntil?: (fn: () => Promise<void>) => void;
|
|
158
263
|
private readonly version?: string;
|
|
264
|
+
private readonly kv?: KVNamespace;
|
|
159
265
|
|
|
160
266
|
constructor(options: CFCacheStoreOptions<TEnv>) {
|
|
161
267
|
if (!options.ctx) {
|
|
@@ -167,22 +273,41 @@ export class CFCacheStore<TEnv = unknown> implements SegmentCacheStore<TEnv> {
|
|
|
167
273
|
}
|
|
168
274
|
|
|
169
275
|
this.namespace = options.namespace;
|
|
170
|
-
|
|
276
|
+
// Base URL is resolved lazily per cache operation (see resolveBaseUrl).
|
|
277
|
+
// The store is constructed before the per-request context ALS is entered
|
|
278
|
+
// (the cache factory runs ahead of runWithRequestContext in the handler),
|
|
279
|
+
// so deriving the host here would always miss the request and fall back to
|
|
280
|
+
// the internal host. Only the explicit override can be captured eagerly.
|
|
281
|
+
this.explicitBaseUrl = options.baseUrl;
|
|
171
282
|
this.defaults = options.defaults;
|
|
172
283
|
this.version = options.version ?? VERSION;
|
|
173
284
|
this.keyGenerator = options.keyGenerator;
|
|
174
285
|
this.waitUntil = (fn) => options.ctx.waitUntil(fn());
|
|
286
|
+
this.kv = options.kv;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Resolve the cache-key base URL for the current cache operation.
|
|
291
|
+
* Prefers an explicit `baseUrl` option; otherwise derives it from the live
|
|
292
|
+
* request. Called per operation (from keyToRequest), which runs inside the
|
|
293
|
+
* request-context ALS, so deriveBaseUrl sees the request and can use the
|
|
294
|
+
* production host instead of the internal fallback.
|
|
295
|
+
* @internal
|
|
296
|
+
*/
|
|
297
|
+
private resolveBaseUrl(): string {
|
|
298
|
+
return this.explicitBaseUrl ?? this.deriveBaseUrl();
|
|
175
299
|
}
|
|
176
300
|
|
|
177
301
|
/**
|
|
178
302
|
* Derive base URL from request hostname via requestContext.
|
|
179
|
-
* Uses internal fallback for dev/preview environments.
|
|
303
|
+
* Uses internal fallback for dev/preview environments and untrusted hostnames.
|
|
304
|
+
* Must run inside the request context (invoked lazily via resolveBaseUrl).
|
|
180
305
|
* @internal
|
|
181
306
|
*/
|
|
182
307
|
private deriveBaseUrl(): string {
|
|
183
|
-
const fallback = "https://rsc-
|
|
308
|
+
const fallback = "https://rsc-dummy-host-1.com/";
|
|
184
309
|
|
|
185
|
-
const ctx =
|
|
310
|
+
const ctx = _getRequestContext();
|
|
186
311
|
if (!ctx?.request) {
|
|
187
312
|
return fallback;
|
|
188
313
|
}
|
|
@@ -201,6 +326,12 @@ export class CFCacheStore<TEnv = unknown> implements SegmentCacheStore<TEnv> {
|
|
|
201
326
|
return fallback;
|
|
202
327
|
}
|
|
203
328
|
|
|
329
|
+
// Validate hostname: must be a valid domain (alphanumeric, hyphens, dots)
|
|
330
|
+
// to prevent host header injection into cache keys
|
|
331
|
+
if (!/^[a-zA-Z0-9.-]+$/.test(hostname) || hostname.length > 253) {
|
|
332
|
+
return fallback;
|
|
333
|
+
}
|
|
334
|
+
|
|
204
335
|
// Use actual hostname for production
|
|
205
336
|
return `https://${hostname}/`;
|
|
206
337
|
} catch {
|
|
@@ -219,6 +350,54 @@ export class CFCacheStore<TEnv = unknown> implements SegmentCacheStore<TEnv> {
|
|
|
219
350
|
return caches.default;
|
|
220
351
|
}
|
|
221
352
|
|
|
353
|
+
/**
|
|
354
|
+
* Read from the L1 edge cache with a latency budget. A `match` that takes
|
|
355
|
+
* longer than EDGE_LOOKUP_TIMEOUT_MS is abandoned and reported as a miss
|
|
356
|
+
* (undefined) so a degraded colo cannot stall the request; callers then fall
|
|
357
|
+
* through to their normal miss path (L2/KV or render). The slow `match` is
|
|
358
|
+
* left to settle in the background (errors swallowed) rather than aborted,
|
|
359
|
+
* since the Cache API exposes no cancellation.
|
|
360
|
+
* @internal
|
|
361
|
+
*/
|
|
362
|
+
private async matchWithTimeout(
|
|
363
|
+
cache: Cache,
|
|
364
|
+
request: Request,
|
|
365
|
+
): Promise<Response | undefined> {
|
|
366
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
367
|
+
const timeout = new Promise<{ timedOut: true }>((resolve) => {
|
|
368
|
+
timer = setTimeout(
|
|
369
|
+
() => resolve({ timedOut: true }),
|
|
370
|
+
EDGE_LOOKUP_TIMEOUT_MS,
|
|
371
|
+
);
|
|
372
|
+
});
|
|
373
|
+
try {
|
|
374
|
+
const matchPromise = cache.match(request);
|
|
375
|
+
// The losing branch keeps running; ensure a late rejection can't surface
|
|
376
|
+
// as an unhandled rejection once we've stopped awaiting it.
|
|
377
|
+
matchPromise.catch(() => {});
|
|
378
|
+
const result = await Promise.race([
|
|
379
|
+
matchPromise.then((response) => ({
|
|
380
|
+
timedOut: false as const,
|
|
381
|
+
response,
|
|
382
|
+
})),
|
|
383
|
+
timeout,
|
|
384
|
+
]);
|
|
385
|
+
if (result.timedOut) {
|
|
386
|
+
console.warn(
|
|
387
|
+
`[CFCacheStore] edge cache lookup exceeded ${EDGE_LOOKUP_TIMEOUT_MS}ms; treating as miss`,
|
|
388
|
+
);
|
|
389
|
+
return undefined;
|
|
390
|
+
}
|
|
391
|
+
return result.response;
|
|
392
|
+
} finally {
|
|
393
|
+
if (timer) clearTimeout(timer);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// ============================================================================
|
|
398
|
+
// Segment Cache Methods
|
|
399
|
+
// ============================================================================
|
|
400
|
+
|
|
222
401
|
/**
|
|
223
402
|
* Get cached entry data by key.
|
|
224
403
|
*
|
|
@@ -227,16 +406,17 @@ export class CFCacheStore<TEnv = unknown> implements SegmentCacheStore<TEnv> {
|
|
|
227
406
|
* - If already REVALIDATING (and recent), returns shouldRevalidate: false
|
|
228
407
|
* - If fresh, returns shouldRevalidate: false
|
|
229
408
|
*
|
|
230
|
-
*
|
|
409
|
+
* On L1 miss, falls back to KV (L2) if configured.
|
|
410
|
+
* KV hits are promoted to L1 in the background.
|
|
231
411
|
*/
|
|
232
412
|
async get(key: string): Promise<CacheGetResult | null> {
|
|
233
413
|
try {
|
|
234
414
|
const cache = await this.getCache();
|
|
235
415
|
const request = this.keyToRequest(key);
|
|
236
|
-
const response = await
|
|
416
|
+
const response = await this.matchWithTimeout(cache, request);
|
|
237
417
|
|
|
238
418
|
if (!response) {
|
|
239
|
-
return
|
|
419
|
+
return this.kvGetSegment(key);
|
|
240
420
|
}
|
|
241
421
|
|
|
242
422
|
// Read status headers
|
|
@@ -279,6 +459,7 @@ export class CFCacheStore<TEnv = unknown> implements SegmentCacheStore<TEnv> {
|
|
|
279
459
|
/**
|
|
280
460
|
* Store entry data with TTL and optional SWR window.
|
|
281
461
|
* Uses waitUntil for non-blocking write when available.
|
|
462
|
+
* When KV is configured, also persists to L2.
|
|
282
463
|
*/
|
|
283
464
|
async set(
|
|
284
465
|
key: string,
|
|
@@ -291,11 +472,12 @@ export class CFCacheStore<TEnv = unknown> implements SegmentCacheStore<TEnv> {
|
|
|
291
472
|
const request = this.keyToRequest(key);
|
|
292
473
|
|
|
293
474
|
// Extended TTL covers SWR window
|
|
294
|
-
const swrWindow = swr
|
|
475
|
+
const swrWindow = resolveSwrWindow(swr, this.defaults);
|
|
295
476
|
const totalTtl = ttl + swrWindow;
|
|
296
477
|
const staleAt = Date.now() + ttl * 1000;
|
|
297
478
|
|
|
298
|
-
const
|
|
479
|
+
const body = JSON.stringify(data);
|
|
480
|
+
const response = new Response(body, {
|
|
299
481
|
headers: {
|
|
300
482
|
"Content-Type": "application/json",
|
|
301
483
|
"Cache-Control": `public, max-age=${totalTtl}`,
|
|
@@ -315,18 +497,35 @@ export class CFCacheStore<TEnv = unknown> implements SegmentCacheStore<TEnv> {
|
|
|
315
497
|
// Blocking fallback
|
|
316
498
|
await putPromise;
|
|
317
499
|
}
|
|
500
|
+
|
|
501
|
+
// L2: persist to KV
|
|
502
|
+
this.kvSetSegment(key, data, staleAt, totalTtl, swrWindow);
|
|
318
503
|
} catch (error) {
|
|
319
504
|
console.error("[CFCacheStore] set failed:", error);
|
|
320
505
|
}
|
|
321
506
|
}
|
|
322
507
|
|
|
323
508
|
/**
|
|
324
|
-
* Delete a cached entry
|
|
509
|
+
* Delete a cached entry from L1 and L2.
|
|
325
510
|
*/
|
|
326
511
|
async delete(key: string): Promise<boolean> {
|
|
327
512
|
try {
|
|
328
513
|
const cache = await this.getCache();
|
|
329
|
-
|
|
514
|
+
const result = await cache.delete(this.keyToRequest(key));
|
|
515
|
+
|
|
516
|
+
// L2: delete from KV
|
|
517
|
+
if (this.kv && this.waitUntil) {
|
|
518
|
+
const kvKey = this.toKVKey(key);
|
|
519
|
+
this.waitUntil(async () => {
|
|
520
|
+
try {
|
|
521
|
+
await this.kv!.delete(kvKey);
|
|
522
|
+
} catch {
|
|
523
|
+
// KV delete failures are non-critical
|
|
524
|
+
}
|
|
525
|
+
});
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
return result;
|
|
330
529
|
} catch (error) {
|
|
331
530
|
console.error("[CFCacheStore] delete failed:", error);
|
|
332
531
|
return false;
|
|
@@ -340,6 +539,7 @@ export class CFCacheStore<TEnv = unknown> implements SegmentCacheStore<TEnv> {
|
|
|
340
539
|
/**
|
|
341
540
|
* Get a cached Response by key (for document-level caching).
|
|
342
541
|
* Returns the response and whether it should be revalidated (SWR).
|
|
542
|
+
* Falls back to KV (L2) on L1 miss.
|
|
343
543
|
*/
|
|
344
544
|
async getResponse(
|
|
345
545
|
key: string,
|
|
@@ -347,10 +547,10 @@ export class CFCacheStore<TEnv = unknown> implements SegmentCacheStore<TEnv> {
|
|
|
347
547
|
try {
|
|
348
548
|
const cache = await this.getCache();
|
|
349
549
|
const request = this.keyToRequest(`doc:${key}`);
|
|
350
|
-
const response = await
|
|
550
|
+
const response = await this.matchWithTimeout(cache, request);
|
|
351
551
|
|
|
352
552
|
if (!response || response.status !== 200) {
|
|
353
|
-
return
|
|
553
|
+
return this.kvGetResponse(key);
|
|
354
554
|
}
|
|
355
555
|
|
|
356
556
|
// Check staleness
|
|
@@ -358,7 +558,7 @@ export class CFCacheStore<TEnv = unknown> implements SegmentCacheStore<TEnv> {
|
|
|
358
558
|
const isStale = staleAt > 0 && Date.now() > staleAt;
|
|
359
559
|
|
|
360
560
|
return {
|
|
361
|
-
response,
|
|
561
|
+
response: this.toClientResponse(response),
|
|
362
562
|
shouldRevalidate: isStale,
|
|
363
563
|
};
|
|
364
564
|
} catch (error) {
|
|
@@ -367,8 +567,33 @@ export class CFCacheStore<TEnv = unknown> implements SegmentCacheStore<TEnv> {
|
|
|
367
567
|
}
|
|
368
568
|
}
|
|
369
569
|
|
|
570
|
+
/**
|
|
571
|
+
* Strip internal edge headers and restore the author's Cache-Control before a
|
|
572
|
+
* cached document Response is served to a client. L1 entries carry the
|
|
573
|
+
* internal staleness/status headers and a rewritten Cache-Control; none of
|
|
574
|
+
* those should reach the browser or an upstream CDN.
|
|
575
|
+
*/
|
|
576
|
+
private toClientResponse(response: Response): Response {
|
|
577
|
+
const headers = new Headers(response.headers);
|
|
578
|
+
const originalCacheControl = headers.get(CACHE_ORIG_CC_HEADER);
|
|
579
|
+
if (originalCacheControl !== null) {
|
|
580
|
+
headers.set("Cache-Control", originalCacheControl);
|
|
581
|
+
} else {
|
|
582
|
+
headers.delete("Cache-Control");
|
|
583
|
+
}
|
|
584
|
+
headers.delete(CACHE_ORIG_CC_HEADER);
|
|
585
|
+
headers.delete(CACHE_STALE_AT_HEADER);
|
|
586
|
+
headers.delete(CACHE_STATUS_HEADER);
|
|
587
|
+
return new Response(response.body, {
|
|
588
|
+
status: response.status,
|
|
589
|
+
statusText: response.statusText,
|
|
590
|
+
headers,
|
|
591
|
+
});
|
|
592
|
+
}
|
|
593
|
+
|
|
370
594
|
/**
|
|
371
595
|
* Store a Response with TTL and optional SWR window (for document-level caching).
|
|
596
|
+
* When KV is configured, also persists to L2.
|
|
372
597
|
*/
|
|
373
598
|
async putResponse(
|
|
374
599
|
key: string,
|
|
@@ -381,16 +606,29 @@ export class CFCacheStore<TEnv = unknown> implements SegmentCacheStore<TEnv> {
|
|
|
381
606
|
const request = this.keyToRequest(`doc:${key}`);
|
|
382
607
|
|
|
383
608
|
// Extended TTL covers SWR window
|
|
384
|
-
const swrWindow = swr
|
|
609
|
+
const swrWindow = resolveSwrWindow(swr, this.defaults);
|
|
385
610
|
const totalTtl = ttl + swrWindow;
|
|
386
611
|
const staleAt = Date.now() + ttl * 1000;
|
|
387
612
|
|
|
388
|
-
// Clone
|
|
613
|
+
// Clone body for potential KV write before consuming it for L1
|
|
614
|
+
const [l1Body, kvBody] = this.kv
|
|
615
|
+
? response.body
|
|
616
|
+
? response.body.tee()
|
|
617
|
+
: [null, null]
|
|
618
|
+
: [response.body, null];
|
|
619
|
+
|
|
620
|
+
// Clone and add cache headers. The author's Cache-Control is stashed and
|
|
621
|
+
// replaced with a long max-age so the CF Cache API holds the entry across
|
|
622
|
+
// the SWR window; getResponse restores the original before serving.
|
|
389
623
|
const headers = new Headers(response.headers);
|
|
624
|
+
const originalCacheControl = response.headers.get("Cache-Control");
|
|
625
|
+
if (originalCacheControl !== null) {
|
|
626
|
+
headers.set(CACHE_ORIG_CC_HEADER, originalCacheControl);
|
|
627
|
+
}
|
|
390
628
|
headers.set("Cache-Control", `public, max-age=${totalTtl}`);
|
|
391
629
|
headers.set(CACHE_STALE_AT_HEADER, String(staleAt));
|
|
392
630
|
|
|
393
|
-
const toCache = new Response(
|
|
631
|
+
const toCache = new Response(l1Body, {
|
|
394
632
|
status: response.status,
|
|
395
633
|
statusText: response.statusText,
|
|
396
634
|
headers,
|
|
@@ -407,11 +645,166 @@ export class CFCacheStore<TEnv = unknown> implements SegmentCacheStore<TEnv> {
|
|
|
407
645
|
// Blocking fallback
|
|
408
646
|
await putPromise;
|
|
409
647
|
}
|
|
648
|
+
|
|
649
|
+
// L2: persist to KV (KV requires expirationTtl >= 60s)
|
|
650
|
+
if (this.kv && this.waitUntil && totalTtl >= 60) {
|
|
651
|
+
const kvKey = this.toKVKey(`doc:${key}`);
|
|
652
|
+
const headersArray: [string, string][] = [];
|
|
653
|
+
response.headers.forEach((v, k) => headersArray.push([k, v]));
|
|
654
|
+
// Read body as ArrayBuffer and encode to base64 to preserve binary payloads
|
|
655
|
+
const bodyBuf = kvBody
|
|
656
|
+
? await new Response(kvBody).arrayBuffer()
|
|
657
|
+
: new ArrayBuffer(0);
|
|
658
|
+
const bodyBase64 = bufferToBase64(bodyBuf);
|
|
659
|
+
|
|
660
|
+
this.waitUntil(async () => {
|
|
661
|
+
try {
|
|
662
|
+
const envelope: KVResponseEnvelope = {
|
|
663
|
+
b: bodyBase64,
|
|
664
|
+
st: response.status,
|
|
665
|
+
stx: response.statusText,
|
|
666
|
+
hd: headersArray,
|
|
667
|
+
s: staleAt,
|
|
668
|
+
e: staleAt + swrWindow * 1000,
|
|
669
|
+
};
|
|
670
|
+
await this.kv!.put(kvKey, JSON.stringify(envelope), {
|
|
671
|
+
expirationTtl: totalTtl,
|
|
672
|
+
});
|
|
673
|
+
} catch (error) {
|
|
674
|
+
console.error("[CFCacheStore] KV putResponse failed:", error);
|
|
675
|
+
}
|
|
676
|
+
});
|
|
677
|
+
}
|
|
410
678
|
} catch (error) {
|
|
411
679
|
console.error("[CFCacheStore] putResponse failed:", error);
|
|
412
680
|
}
|
|
413
681
|
}
|
|
414
682
|
|
|
683
|
+
// ============================================================================
|
|
684
|
+
// Function Cache Methods (for "use cache" directive)
|
|
685
|
+
// ============================================================================
|
|
686
|
+
|
|
687
|
+
/**
|
|
688
|
+
* Get a cached function result by key.
|
|
689
|
+
* Follows the same SWR pattern as get() for segment caching.
|
|
690
|
+
* Falls back to KV (L2) on L1 miss.
|
|
691
|
+
*/
|
|
692
|
+
async getItem(key: string): Promise<CacheItemResult | null> {
|
|
693
|
+
try {
|
|
694
|
+
const cache = await this.getCache();
|
|
695
|
+
const request = this.keyToRequest(`fn:${key}`);
|
|
696
|
+
const response = await this.matchWithTimeout(cache, request);
|
|
697
|
+
|
|
698
|
+
if (!response) return this.kvGetItem(key);
|
|
699
|
+
|
|
700
|
+
const staleAt = Number(
|
|
701
|
+
response.headers.get(CACHE_STALE_AT_HEADER) ?? "0",
|
|
702
|
+
);
|
|
703
|
+
const status = response.headers.get(CACHE_STATUS_HEADER);
|
|
704
|
+
const age = Number(response.headers.get("age") ?? "0");
|
|
705
|
+
|
|
706
|
+
const isStale = staleAt > 0 && Date.now() > staleAt;
|
|
707
|
+
const isRevalidating =
|
|
708
|
+
status === "REVALIDATING" && age < MAX_REVALIDATION_INTERVAL;
|
|
709
|
+
|
|
710
|
+
const data = (await response.json()) as {
|
|
711
|
+
value: string;
|
|
712
|
+
handles?: string;
|
|
713
|
+
};
|
|
714
|
+
|
|
715
|
+
if (!isStale || isRevalidating) {
|
|
716
|
+
return {
|
|
717
|
+
value: data.value,
|
|
718
|
+
handles: data.handles,
|
|
719
|
+
shouldRevalidate: false,
|
|
720
|
+
};
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
// Stale and needs revalidation — mark REVALIDATING atomically
|
|
724
|
+
const headers = new Headers(response.headers);
|
|
725
|
+
headers.set(CACHE_STATUS_HEADER, "REVALIDATING");
|
|
726
|
+
await cache.put(
|
|
727
|
+
request,
|
|
728
|
+
new Response(JSON.stringify(data), { status: 200, headers }),
|
|
729
|
+
);
|
|
730
|
+
|
|
731
|
+
return {
|
|
732
|
+
value: data.value,
|
|
733
|
+
handles: data.handles,
|
|
734
|
+
shouldRevalidate: true,
|
|
735
|
+
};
|
|
736
|
+
} catch (error) {
|
|
737
|
+
console.error("[CFCacheStore] getItem failed:", error);
|
|
738
|
+
return null;
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
/**
|
|
743
|
+
* Store a function result with TTL and optional SWR window.
|
|
744
|
+
* When KV is configured, also persists to L2.
|
|
745
|
+
*/
|
|
746
|
+
async setItem(
|
|
747
|
+
key: string,
|
|
748
|
+
value: string,
|
|
749
|
+
options?: CacheItemOptions,
|
|
750
|
+
): Promise<void> {
|
|
751
|
+
try {
|
|
752
|
+
const cache = await this.getCache();
|
|
753
|
+
const request = this.keyToRequest(`fn:${key}`);
|
|
754
|
+
|
|
755
|
+
const ttl = resolveTtl(options?.ttl, this.defaults, DEFAULT_FUNCTION_TTL);
|
|
756
|
+
const swrWindow = resolveSwrWindow(options?.swr, this.defaults);
|
|
757
|
+
const totalTtl = ttl + swrWindow;
|
|
758
|
+
const staleAt = Date.now() + ttl * 1000;
|
|
759
|
+
|
|
760
|
+
const body = JSON.stringify({ value, handles: options?.handles });
|
|
761
|
+
const response = new Response(body, {
|
|
762
|
+
headers: {
|
|
763
|
+
"Content-Type": "application/json",
|
|
764
|
+
"Cache-Control": `public, max-age=${totalTtl}`,
|
|
765
|
+
[CACHE_STALE_AT_HEADER]: String(staleAt),
|
|
766
|
+
[CACHE_STATUS_HEADER]: "HIT",
|
|
767
|
+
},
|
|
768
|
+
});
|
|
769
|
+
|
|
770
|
+
const putPromise = cache.put(request, response);
|
|
771
|
+
|
|
772
|
+
if (this.waitUntil) {
|
|
773
|
+
this.waitUntil(async () => {
|
|
774
|
+
await putPromise;
|
|
775
|
+
});
|
|
776
|
+
} else {
|
|
777
|
+
await putPromise;
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
// L2: persist to KV (KV requires expirationTtl >= 60s)
|
|
781
|
+
if (this.kv && this.waitUntil && totalTtl >= 60) {
|
|
782
|
+
const kvKey = this.toKVKey(`fn:${key}`);
|
|
783
|
+
this.waitUntil(async () => {
|
|
784
|
+
try {
|
|
785
|
+
const envelope: KVItemEnvelope = {
|
|
786
|
+
v: value,
|
|
787
|
+
h: options?.handles,
|
|
788
|
+
s: staleAt,
|
|
789
|
+
e: staleAt + swrWindow * 1000,
|
|
790
|
+
};
|
|
791
|
+
await this.kv!.put(kvKey, JSON.stringify(envelope), {
|
|
792
|
+
expirationTtl: totalTtl,
|
|
793
|
+
});
|
|
794
|
+
} catch (error) {
|
|
795
|
+
console.error("[CFCacheStore] KV setItem failed:", error);
|
|
796
|
+
}
|
|
797
|
+
});
|
|
798
|
+
}
|
|
799
|
+
} catch (error) {
|
|
800
|
+
console.error("[CFCacheStore] setItem failed:", error);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
// ============================================================================
|
|
805
|
+
// Key Helpers
|
|
806
|
+
// ============================================================================
|
|
807
|
+
|
|
415
808
|
/**
|
|
416
809
|
* Convert string key to Request object for CF Cache API.
|
|
417
810
|
* Includes version in URL if specified (for cache invalidation on code changes).
|
|
@@ -421,8 +814,281 @@ export class CFCacheStore<TEnv = unknown> implements SegmentCacheStore<TEnv> {
|
|
|
421
814
|
const encodedKey = encodeURIComponent(key);
|
|
422
815
|
// Include version in URL path to invalidate cache when version changes
|
|
423
816
|
const versionPath = this.version ? `v/${this.version}/` : "";
|
|
424
|
-
return new Request(`${this.
|
|
817
|
+
return new Request(`${this.resolveBaseUrl()}${versionPath}${encodedKey}`, {
|
|
425
818
|
method: "GET",
|
|
426
819
|
});
|
|
427
820
|
}
|
|
821
|
+
|
|
822
|
+
/**
|
|
823
|
+
* Convert string key to KV key string.
|
|
824
|
+
* Uses same version prefix as Cache API for consistent invalidation.
|
|
825
|
+
* @internal
|
|
826
|
+
*/
|
|
827
|
+
private toKVKey(key: string): string {
|
|
828
|
+
const versionPath = this.version ? `v/${this.version}/` : "";
|
|
829
|
+
return `${versionPath}${key}`;
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
// ============================================================================
|
|
833
|
+
// KV L2 Helpers
|
|
834
|
+
// ============================================================================
|
|
835
|
+
|
|
836
|
+
/**
|
|
837
|
+
* KV fallback for segment cache reads.
|
|
838
|
+
* Returns null if KV is not configured, entry is missing, or expired.
|
|
839
|
+
* Promotes hits to L1 via waitUntil.
|
|
840
|
+
* @internal
|
|
841
|
+
*/
|
|
842
|
+
private async kvGetSegment(key: string): Promise<CacheGetResult | null> {
|
|
843
|
+
if (!this.kv) return null;
|
|
844
|
+
|
|
845
|
+
try {
|
|
846
|
+
const kvKey = this.toKVKey(key);
|
|
847
|
+
const raw = await this.kv.get(kvKey, { type: "json" });
|
|
848
|
+
if (!raw) return null;
|
|
849
|
+
|
|
850
|
+
const envelope = raw as KVSegmentEnvelope;
|
|
851
|
+
const now = Date.now();
|
|
852
|
+
|
|
853
|
+
// Hard-expired — treat as miss
|
|
854
|
+
if (now > envelope.e) return null;
|
|
855
|
+
|
|
856
|
+
const shouldRevalidate = now > envelope.s;
|
|
857
|
+
|
|
858
|
+
// Promote to L1 in background
|
|
859
|
+
this.promoteSegmentToL1(key, envelope);
|
|
860
|
+
|
|
861
|
+
return { data: envelope.d, shouldRevalidate };
|
|
862
|
+
} catch (error) {
|
|
863
|
+
console.error("[CFCacheStore] KV get failed:", error);
|
|
864
|
+
return null;
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
/**
|
|
869
|
+
* Write segment data to KV.
|
|
870
|
+
* @internal
|
|
871
|
+
*/
|
|
872
|
+
private kvSetSegment(
|
|
873
|
+
key: string,
|
|
874
|
+
data: CachedEntryData,
|
|
875
|
+
staleAt: number,
|
|
876
|
+
totalTtl: number,
|
|
877
|
+
swrWindow: number,
|
|
878
|
+
): void {
|
|
879
|
+
// KV requires expirationTtl >= 60s. Skip write for short-lived entries.
|
|
880
|
+
if (!this.kv || !this.waitUntil || totalTtl < 60) return;
|
|
881
|
+
|
|
882
|
+
const kvKey = this.toKVKey(key);
|
|
883
|
+
const expiresAt = staleAt + swrWindow * 1000;
|
|
884
|
+
|
|
885
|
+
this.waitUntil(async () => {
|
|
886
|
+
try {
|
|
887
|
+
const envelope: KVSegmentEnvelope = {
|
|
888
|
+
d: data,
|
|
889
|
+
s: staleAt,
|
|
890
|
+
e: expiresAt,
|
|
891
|
+
};
|
|
892
|
+
await this.kv!.put(kvKey, JSON.stringify(envelope), {
|
|
893
|
+
expirationTtl: totalTtl,
|
|
894
|
+
});
|
|
895
|
+
} catch (error) {
|
|
896
|
+
console.error("[CFCacheStore] KV set failed:", error);
|
|
897
|
+
}
|
|
898
|
+
});
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
/**
|
|
902
|
+
* Promote segment data from KV to L1 Cache API.
|
|
903
|
+
* @internal
|
|
904
|
+
*/
|
|
905
|
+
private promoteSegmentToL1(key: string, envelope: KVSegmentEnvelope): void {
|
|
906
|
+
if (!this.waitUntil) return;
|
|
907
|
+
|
|
908
|
+
this.waitUntil(async () => {
|
|
909
|
+
try {
|
|
910
|
+
const now = Date.now();
|
|
911
|
+
const remainingTtl = Math.max(1, Math.floor((envelope.e - now) / 1000));
|
|
912
|
+
const cache = await this.getCache();
|
|
913
|
+
const request = this.keyToRequest(key);
|
|
914
|
+
|
|
915
|
+
const response = new Response(JSON.stringify(envelope.d), {
|
|
916
|
+
headers: {
|
|
917
|
+
"Content-Type": "application/json",
|
|
918
|
+
"Cache-Control": `public, max-age=${remainingTtl}`,
|
|
919
|
+
[CACHE_STALE_AT_HEADER]: String(envelope.s),
|
|
920
|
+
[CACHE_STATUS_HEADER]: "HIT",
|
|
921
|
+
},
|
|
922
|
+
});
|
|
923
|
+
|
|
924
|
+
await cache.put(request, response);
|
|
925
|
+
} catch (error) {
|
|
926
|
+
console.error("[CFCacheStore] L1 promote failed:", error);
|
|
927
|
+
}
|
|
928
|
+
});
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
/**
|
|
932
|
+
* KV fallback for function cache reads.
|
|
933
|
+
* @internal
|
|
934
|
+
*/
|
|
935
|
+
private async kvGetItem(key: string): Promise<CacheItemResult | null> {
|
|
936
|
+
if (!this.kv) return null;
|
|
937
|
+
|
|
938
|
+
try {
|
|
939
|
+
const kvKey = this.toKVKey(`fn:${key}`);
|
|
940
|
+
const raw = await this.kv.get(kvKey, { type: "json" });
|
|
941
|
+
if (!raw) return null;
|
|
942
|
+
|
|
943
|
+
const envelope = raw as KVItemEnvelope;
|
|
944
|
+
const now = Date.now();
|
|
945
|
+
|
|
946
|
+
if (now > envelope.e) return null;
|
|
947
|
+
|
|
948
|
+
const shouldRevalidate = now > envelope.s;
|
|
949
|
+
|
|
950
|
+
// Promote to L1
|
|
951
|
+
this.promoteItemToL1(key, envelope);
|
|
952
|
+
|
|
953
|
+
return {
|
|
954
|
+
value: envelope.v,
|
|
955
|
+
handles: envelope.h,
|
|
956
|
+
shouldRevalidate,
|
|
957
|
+
};
|
|
958
|
+
} catch (error) {
|
|
959
|
+
console.error("[CFCacheStore] KV getItem failed:", error);
|
|
960
|
+
return null;
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
/**
|
|
965
|
+
* Promote function cache data from KV to L1.
|
|
966
|
+
* @internal
|
|
967
|
+
*/
|
|
968
|
+
private promoteItemToL1(key: string, envelope: KVItemEnvelope): void {
|
|
969
|
+
if (!this.waitUntil) return;
|
|
970
|
+
|
|
971
|
+
this.waitUntil(async () => {
|
|
972
|
+
try {
|
|
973
|
+
const now = Date.now();
|
|
974
|
+
const remainingTtl = Math.max(1, Math.floor((envelope.e - now) / 1000));
|
|
975
|
+
const cache = await this.getCache();
|
|
976
|
+
const request = this.keyToRequest(`fn:${key}`);
|
|
977
|
+
|
|
978
|
+
const body = JSON.stringify({ value: envelope.v, handles: envelope.h });
|
|
979
|
+
const response = new Response(body, {
|
|
980
|
+
headers: {
|
|
981
|
+
"Content-Type": "application/json",
|
|
982
|
+
"Cache-Control": `public, max-age=${remainingTtl}`,
|
|
983
|
+
[CACHE_STALE_AT_HEADER]: String(envelope.s),
|
|
984
|
+
[CACHE_STATUS_HEADER]: "HIT",
|
|
985
|
+
},
|
|
986
|
+
});
|
|
987
|
+
|
|
988
|
+
await cache.put(request, response);
|
|
989
|
+
} catch (error) {
|
|
990
|
+
console.error("[CFCacheStore] L1 item promote failed:", error);
|
|
991
|
+
}
|
|
992
|
+
});
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
/**
|
|
996
|
+
* KV fallback for document cache reads.
|
|
997
|
+
* @internal
|
|
998
|
+
*/
|
|
999
|
+
private async kvGetResponse(
|
|
1000
|
+
key: string,
|
|
1001
|
+
): Promise<{ response: Response; shouldRevalidate: boolean } | null> {
|
|
1002
|
+
if (!this.kv) return null;
|
|
1003
|
+
|
|
1004
|
+
try {
|
|
1005
|
+
const kvKey = this.toKVKey(`doc:${key}`);
|
|
1006
|
+
const raw = await this.kv.get(kvKey, { type: "json" });
|
|
1007
|
+
if (!raw) return null;
|
|
1008
|
+
|
|
1009
|
+
const envelope = raw as KVResponseEnvelope;
|
|
1010
|
+
const now = Date.now();
|
|
1011
|
+
|
|
1012
|
+
if (now > envelope.e) return null;
|
|
1013
|
+
|
|
1014
|
+
const shouldRevalidate = now > envelope.s;
|
|
1015
|
+
|
|
1016
|
+
// Reconstruct Response (decode base64 → binary)
|
|
1017
|
+
const headers = new Headers(envelope.hd);
|
|
1018
|
+
const bodyBuffer = base64ToBuffer(envelope.b);
|
|
1019
|
+
const response = new Response(bodyBuffer, {
|
|
1020
|
+
status: envelope.st,
|
|
1021
|
+
statusText: envelope.stx,
|
|
1022
|
+
headers,
|
|
1023
|
+
});
|
|
1024
|
+
|
|
1025
|
+
// Promote to L1
|
|
1026
|
+
this.promoteResponseToL1(key, envelope);
|
|
1027
|
+
|
|
1028
|
+
return { response, shouldRevalidate };
|
|
1029
|
+
} catch (error) {
|
|
1030
|
+
console.error("[CFCacheStore] KV getResponse failed:", error);
|
|
1031
|
+
return null;
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
/**
|
|
1036
|
+
* Promote document cache data from KV to L1.
|
|
1037
|
+
* @internal
|
|
1038
|
+
*/
|
|
1039
|
+
private promoteResponseToL1(key: string, envelope: KVResponseEnvelope): void {
|
|
1040
|
+
if (!this.waitUntil) return;
|
|
1041
|
+
|
|
1042
|
+
this.waitUntil(async () => {
|
|
1043
|
+
try {
|
|
1044
|
+
const now = Date.now();
|
|
1045
|
+
const remainingTtl = Math.max(1, Math.floor((envelope.e - now) / 1000));
|
|
1046
|
+
const cache = await this.getCache();
|
|
1047
|
+
const request = this.keyToRequest(`doc:${key}`);
|
|
1048
|
+
|
|
1049
|
+
const headers = new Headers(envelope.hd);
|
|
1050
|
+
const originalCacheControl = headers.get("Cache-Control");
|
|
1051
|
+
if (originalCacheControl !== null) {
|
|
1052
|
+
headers.set(CACHE_ORIG_CC_HEADER, originalCacheControl);
|
|
1053
|
+
}
|
|
1054
|
+
headers.set("Cache-Control", `public, max-age=${remainingTtl}`);
|
|
1055
|
+
headers.set(CACHE_STALE_AT_HEADER, String(envelope.s));
|
|
1056
|
+
|
|
1057
|
+
const bodyBuffer = base64ToBuffer(envelope.b);
|
|
1058
|
+
const response = new Response(bodyBuffer, {
|
|
1059
|
+
status: envelope.st,
|
|
1060
|
+
statusText: envelope.stx,
|
|
1061
|
+
headers,
|
|
1062
|
+
});
|
|
1063
|
+
|
|
1064
|
+
await cache.put(request, response);
|
|
1065
|
+
} catch (error) {
|
|
1066
|
+
console.error("[CFCacheStore] L1 response promote failed:", error);
|
|
1067
|
+
}
|
|
1068
|
+
});
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
// ============================================================================
|
|
1073
|
+
// Base64 Helpers (binary-safe response body encoding for KV)
|
|
1074
|
+
// ============================================================================
|
|
1075
|
+
|
|
1076
|
+
/** Encode ArrayBuffer to base64 string. */
|
|
1077
|
+
function bufferToBase64(buffer: ArrayBuffer): string {
|
|
1078
|
+
const bytes = new Uint8Array(buffer);
|
|
1079
|
+
let binary = "";
|
|
1080
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
1081
|
+
binary += String.fromCharCode(bytes[i]!);
|
|
1082
|
+
}
|
|
1083
|
+
return btoa(binary);
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
/** Decode base64 string to ArrayBuffer. */
|
|
1087
|
+
function base64ToBuffer(base64: string): ArrayBuffer {
|
|
1088
|
+
const binary = atob(base64);
|
|
1089
|
+
const bytes = new Uint8Array(binary.length);
|
|
1090
|
+
for (let i = 0; i < binary.length; i++) {
|
|
1091
|
+
bytes[i] = binary.charCodeAt(i);
|
|
1092
|
+
}
|
|
1093
|
+
return bytes.buffer;
|
|
428
1094
|
}
|