@timber-js/app 0.2.0-alpha.15 → 0.2.0-alpha.150
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/LICENSE +8 -0
- package/dist/_chunks/actions-a0RczDnB.js +1106 -0
- package/dist/_chunks/actions-a0RczDnB.js.map +1 -0
- package/dist/_chunks/build-output-helper-B20ZuTSA.js +102 -0
- package/dist/_chunks/build-output-helper-B20ZuTSA.js.map +1 -0
- package/dist/_chunks/cache-api-Co-yI-gP.js +424 -0
- package/dist/_chunks/cache-api-Co-yI-gP.js.map +1 -0
- package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js → canonicalize-P41GR6tY.js} +94 -18
- package/dist/_chunks/canonicalize-P41GR6tY.js.map +1 -0
- package/dist/_chunks/cli-schema-sync-DJDdyEae.js +629 -0
- package/dist/_chunks/cli-schema-sync-DJDdyEae.js.map +1 -0
- package/dist/_chunks/cli-schema-sync-D_IhHEUW.js +2 -0
- package/dist/_chunks/codec-registry-oOUxugz3.js +21 -0
- package/dist/_chunks/codec-registry-oOUxugz3.js.map +1 -0
- package/dist/_chunks/define-Bssfp6ot.js +82 -0
- package/dist/_chunks/define-Bssfp6ot.js.map +1 -0
- package/dist/_chunks/define-CFmvb4Bt.js +203 -0
- package/dist/_chunks/define-CFmvb4Bt.js.map +1 -0
- package/dist/_chunks/fast-hash-D6hIVt1Y.js +36 -0
- package/dist/_chunks/fast-hash-D6hIVt1Y.js.map +1 -0
- package/dist/_chunks/format-CfwjgPz9.js +14 -0
- package/dist/_chunks/format-CfwjgPz9.js.map +1 -0
- package/dist/_chunks/href-validation-FiA_rToW.js +141 -0
- package/dist/_chunks/href-validation-FiA_rToW.js.map +1 -0
- package/dist/_chunks/logger-CM0clugc.js +645 -0
- package/dist/_chunks/logger-CM0clugc.js.map +1 -0
- package/dist/_chunks/navigation-root-bUDZLw74.js +124 -0
- package/dist/_chunks/navigation-root-bUDZLw74.js.map +1 -0
- package/dist/_chunks/plugin-context-DurqFBuY.js +2 -0
- package/dist/_chunks/plugin-context-GfDWsdd2.js +268 -0
- package/dist/_chunks/plugin-context-GfDWsdd2.js.map +1 -0
- package/dist/_chunks/registry-DbJPKoBp.js +20 -0
- package/dist/_chunks/registry-DbJPKoBp.js.map +1 -0
- package/dist/_chunks/resolve-schema-3iUvBV5T.js +50 -0
- package/dist/_chunks/resolve-schema-3iUvBV5T.js.map +1 -0
- package/dist/_chunks/router-ref-CtmF-aPv.js +28 -0
- package/dist/_chunks/router-ref-CtmF-aPv.js.map +1 -0
- package/dist/_chunks/schema-bridge-BY3QLBL7.js +119 -0
- package/dist/_chunks/schema-bridge-BY3QLBL7.js.map +1 -0
- package/dist/_chunks/segment-classify-CDDRVKs7.js +137 -0
- package/dist/_chunks/segment-classify-CDDRVKs7.js.map +1 -0
- package/dist/_chunks/segment-context-ZDnXDkbz.js +34 -0
- package/dist/_chunks/segment-context-ZDnXDkbz.js.map +1 -0
- package/dist/_chunks/{ssr-data-MjmprTmO.js → ssr-data-BOWsq18U.js} +1 -1
- package/dist/_chunks/ssr-data-BOWsq18U.js.map +1 -0
- package/dist/_chunks/tree-match-D2l830j2.js +102 -0
- package/dist/_chunks/tree-match-D2l830j2.js.map +1 -0
- package/dist/_chunks/{use-query-states-D5KaffOK.js → use-query-states-CbeQmext.js} +7 -20
- package/dist/_chunks/use-query-states-CbeQmext.js.map +1 -0
- package/dist/_chunks/use-segment-params-D1CzlgBo.js +151 -0
- package/dist/_chunks/use-segment-params-D1CzlgBo.js.map +1 -0
- package/dist/_chunks/validation-taUkvA4Q.js +113 -0
- package/dist/_chunks/validation-taUkvA4Q.js.map +1 -0
- package/dist/_chunks/walkers-DvWDj453.js +790 -0
- package/dist/_chunks/walkers-DvWDj453.js.map +1 -0
- package/dist/adapters/build-output-helper.d.ts +28 -0
- package/dist/adapters/build-output-helper.d.ts.map +1 -0
- package/dist/adapters/cloudflare-dev.d.ts +109 -0
- package/dist/adapters/cloudflare-dev.d.ts.map +1 -0
- package/dist/adapters/cloudflare-dev.js +73 -0
- package/dist/adapters/cloudflare-dev.js.map +1 -0
- package/dist/adapters/cloudflare-kv-cache.d.ts +64 -0
- package/dist/adapters/cloudflare-kv-cache.d.ts.map +1 -0
- package/dist/adapters/cloudflare-kv-cache.js +117 -0
- package/dist/adapters/cloudflare-kv-cache.js.map +1 -0
- package/dist/adapters/cloudflare.d.ts +142 -20
- package/dist/adapters/cloudflare.d.ts.map +1 -1
- package/dist/adapters/cloudflare.js +150 -64
- package/dist/adapters/cloudflare.js.map +1 -1
- package/dist/adapters/compress-module.d.ts +5 -4
- package/dist/adapters/compress-module.d.ts.map +1 -1
- package/dist/adapters/nitro.d.ts +17 -3
- package/dist/adapters/nitro.d.ts.map +1 -1
- package/dist/adapters/nitro.js +146 -147
- package/dist/adapters/nitro.js.map +1 -1
- package/dist/adapters/shared.d.ts +16 -0
- package/dist/adapters/shared.d.ts.map +1 -0
- package/dist/cache/cache-api.d.ts +24 -0
- package/dist/cache/cache-api.d.ts.map +1 -0
- package/dist/cache/handler-store.d.ts +31 -0
- package/dist/cache/handler-store.d.ts.map +1 -0
- package/dist/cache/index.d.ts +25 -7
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +100 -240
- package/dist/cache/index.js.map +1 -1
- package/dist/cache/invalidation-epoch.d.ts +43 -0
- package/dist/cache/invalidation-epoch.d.ts.map +1 -0
- package/dist/cache/redis-handler.d.ts +85 -8
- package/dist/cache/redis-handler.d.ts.map +1 -1
- package/dist/cache/singleflight.d.ts +18 -1
- package/dist/cache/singleflight.d.ts.map +1 -1
- package/dist/cache/sizeof.d.ts +22 -0
- package/dist/cache/sizeof.d.ts.map +1 -0
- package/dist/cache/stable-stringify.d.ts +9 -0
- package/dist/cache/stable-stringify.d.ts.map +1 -1
- package/dist/cache/timber-cache.d.ts +20 -10
- package/dist/cache/timber-cache.d.ts.map +1 -1
- package/dist/cli-schema-sync.d.ts +59 -0
- package/dist/cli-schema-sync.d.ts.map +1 -0
- package/dist/cli.d.ts +26 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +70 -33
- package/dist/cli.js.map +1 -1
- package/dist/client/browser-dev.d.ts +34 -1
- package/dist/client/browser-dev.d.ts.map +1 -1
- package/dist/client/browser-entry/action-dispatch.d.ts +17 -0
- package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -0
- package/dist/client/browser-entry/hmr.d.ts +21 -0
- package/dist/client/browser-entry/hmr.d.ts.map +1 -0
- package/dist/client/browser-entry/hydrate.d.ts +46 -0
- package/dist/client/browser-entry/hydrate.d.ts.map +1 -0
- package/dist/client/browser-entry/index.d.ts +29 -0
- package/dist/client/browser-entry/index.d.ts.map +1 -0
- package/dist/client/browser-entry/post-hydration.d.ts +26 -0
- package/dist/client/browser-entry/post-hydration.d.ts.map +1 -0
- package/dist/client/browser-entry/router-init.d.ts +26 -0
- package/dist/client/browser-entry/router-init.d.ts.map +1 -0
- package/dist/client/browser-entry/rsc-stream.d.ts +24 -0
- package/dist/client/browser-entry/rsc-stream.d.ts.map +1 -0
- package/dist/client/browser-entry/scroll.d.ts +28 -0
- package/dist/client/browser-entry/scroll.d.ts.map +1 -0
- package/dist/client/error-boundary.d.ts +12 -5
- package/dist/client/error-boundary.d.ts.map +1 -1
- package/dist/client/error-boundary.js +47 -10
- package/dist/client/error-boundary.js.map +1 -1
- package/dist/client/error-reconstituter.d.ts +61 -0
- package/dist/client/error-reconstituter.d.ts.map +1 -0
- package/dist/client/form.d.ts +16 -27
- package/dist/client/form.d.ts.map +1 -1
- package/dist/client/history.d.ts +11 -3
- package/dist/client/history.d.ts.map +1 -1
- package/dist/client/index.d.ts +10 -24
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +183 -1134
- package/dist/client/index.js.map +1 -1
- package/dist/client/internal.d.ts +19 -0
- package/dist/client/internal.d.ts.map +1 -0
- package/dist/client/internal.js +900 -0
- package/dist/client/internal.js.map +1 -0
- package/dist/client/link.d.ts +69 -60
- package/dist/client/link.d.ts.map +1 -1
- package/dist/client/navigation-api-types.d.ts +90 -0
- package/dist/client/navigation-api-types.d.ts.map +1 -0
- package/dist/client/navigation-api.d.ts +122 -0
- package/dist/client/navigation-api.d.ts.map +1 -0
- package/dist/client/navigation-context.d.ts +3 -2
- package/dist/client/navigation-context.d.ts.map +1 -1
- package/dist/client/navigation-root.d.ts +119 -0
- package/dist/client/navigation-root.d.ts.map +1 -0
- package/dist/client/nuqs-adapter.d.ts +1 -1
- package/dist/client/nuqs-adapter.d.ts.map +1 -1
- package/dist/client/router-ref.d.ts +1 -1
- package/dist/client/router.d.ts +86 -10
- package/dist/client/router.d.ts.map +1 -1
- package/dist/client/rsc-fetch.d.ts +46 -3
- package/dist/client/rsc-fetch.d.ts.map +1 -1
- package/dist/client/segment-cache.d.ts +3 -1
- package/dist/client/segment-cache.d.ts.map +1 -1
- package/dist/client/segment-outlet.d.ts +49 -0
- package/dist/client/segment-outlet.d.ts.map +1 -0
- package/dist/client/segment-update-context.d.ts +21 -0
- package/dist/client/segment-update-context.d.ts.map +1 -0
- package/dist/client/shallow-url.d.ts +10 -0
- package/dist/client/shallow-url.d.ts.map +1 -0
- package/dist/client/ssr-data.d.ts +13 -4
- package/dist/client/ssr-data.d.ts.map +1 -1
- package/dist/client/state.d.ts +1 -1
- package/dist/client/top-loader.d.ts +5 -5
- package/dist/client/top-loader.d.ts.map +1 -1
- package/dist/client/use-cookie.d.ts +12 -0
- package/dist/client/use-cookie.d.ts.map +1 -1
- package/dist/client/use-link-status.d.ts +5 -5
- package/dist/client/use-link-status.d.ts.map +1 -1
- package/dist/client/use-pathname.d.ts.map +1 -1
- package/dist/client/use-pending-navigation.d.ts +23 -0
- package/dist/client/use-pending-navigation.d.ts.map +1 -0
- package/dist/client/use-query-states.d.ts +1 -1
- package/dist/client/use-query-states.d.ts.map +1 -1
- package/dist/client/use-router.d.ts +1 -1
- package/dist/client/use-router.d.ts.map +1 -1
- package/dist/client/use-search-params.d.ts +12 -5
- package/dist/client/use-search-params.d.ts.map +1 -1
- package/dist/client/{use-params.d.ts → use-segment-params.d.ts} +8 -6
- package/dist/client/use-segment-params.d.ts.map +1 -0
- package/dist/codec.d.ts +69 -0
- package/dist/codec.d.ts.map +1 -0
- package/dist/codec.js +75 -0
- package/dist/codec.js.map +1 -0
- package/dist/config-types.d.ts +294 -0
- package/dist/config-types.d.ts.map +1 -0
- package/dist/config-validation.d.ts +51 -0
- package/dist/config-validation.d.ts.map +1 -0
- package/dist/content/index.d.ts +1 -10
- package/dist/content/index.d.ts.map +1 -1
- package/dist/content/index.js +0 -2
- package/dist/cookies/define-cookie.d.ts +58 -25
- package/dist/cookies/define-cookie.d.ts.map +1 -1
- package/dist/cookies/index.d.ts +2 -1
- package/dist/cookies/index.d.ts.map +1 -1
- package/dist/cookies/index.js +249 -36
- package/dist/cookies/index.js.map +1 -1
- package/dist/cookies/json-cookie.d.ts +64 -0
- package/dist/cookies/json-cookie.d.ts.map +1 -0
- package/dist/cookies/validation.d.ts +34 -0
- package/dist/cookies/validation.d.ts.map +1 -0
- package/dist/dev-tools/404-page.d.ts +50 -0
- package/dist/dev-tools/404-page.d.ts.map +1 -0
- package/dist/dev-tools/browser-logs.d.ts +84 -0
- package/dist/dev-tools/browser-logs.d.ts.map +1 -0
- package/dist/dev-tools/dev-page-shell.d.ts +78 -0
- package/dist/dev-tools/dev-page-shell.d.ts.map +1 -0
- package/dist/dev-tools/error-page.d.ts +32 -0
- package/dist/dev-tools/error-page.d.ts.map +1 -0
- package/dist/dev-tools/holding-server.d.ts +54 -0
- package/dist/dev-tools/holding-server.d.ts.map +1 -0
- package/dist/dev-tools/hydration-overlay.d.ts +11 -0
- package/dist/dev-tools/hydration-overlay.d.ts.map +1 -0
- package/dist/dev-tools/index.d.ts +31 -0
- package/dist/dev-tools/index.d.ts.map +1 -0
- package/dist/dev-tools/instrumentation.d.ts +59 -0
- package/dist/dev-tools/instrumentation.d.ts.map +1 -0
- package/dist/{server/dev-logger.d.ts → dev-tools/logger.d.ts} +1 -1
- package/dist/dev-tools/logger.d.ts.map +1 -0
- package/dist/{plugins/dev-logs.d.ts → dev-tools/logs.d.ts} +2 -2
- package/dist/dev-tools/logs.d.ts.map +1 -0
- package/dist/dev-tools/overlay.d.ts +91 -0
- package/dist/dev-tools/overlay.d.ts.map +1 -0
- package/dist/dev-tools/stack-classifier.d.ts +34 -0
- package/dist/dev-tools/stack-classifier.d.ts.map +1 -0
- package/dist/dev-tools/terminal.d.ts +28 -0
- package/dist/dev-tools/terminal.d.ts.map +1 -0
- package/dist/fonts/ast-walk.d.ts +68 -0
- package/dist/fonts/ast-walk.d.ts.map +1 -0
- package/dist/fonts/ast.d.ts +110 -6
- package/dist/fonts/ast.d.ts.map +1 -1
- package/dist/fonts/bundle.d.ts +50 -0
- package/dist/fonts/bundle.d.ts.map +1 -0
- package/dist/fonts/dev-middleware.d.ts +22 -0
- package/dist/fonts/dev-middleware.d.ts.map +1 -0
- package/dist/fonts/fallbacks.d.ts +0 -7
- package/dist/fonts/fallbacks.d.ts.map +1 -1
- package/dist/fonts/google.d.ts +4 -2
- package/dist/fonts/google.d.ts.map +1 -1
- package/dist/fonts/local.d.ts +4 -4
- package/dist/fonts/local.d.ts.map +1 -1
- package/dist/fonts/paths.d.ts +43 -0
- package/dist/fonts/paths.d.ts.map +1 -0
- package/dist/fonts/pipeline.d.ts +158 -0
- package/dist/fonts/pipeline.d.ts.map +1 -0
- package/dist/fonts/transform.d.ts +78 -0
- package/dist/fonts/transform.d.ts.map +1 -0
- package/dist/fonts/types.d.ts +47 -1
- package/dist/fonts/types.d.ts.map +1 -1
- package/dist/fonts/virtual-modules.d.ts +77 -0
- package/dist/fonts/virtual-modules.d.ts.map +1 -0
- package/dist/index.d.ts +46 -180
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6432 -13423
- package/dist/index.js.map +1 -1
- package/dist/params/codec-registry.d.ts +26 -0
- package/dist/params/codec-registry.d.ts.map +1 -0
- package/dist/params/define-schema.d.ts +81 -0
- package/dist/params/define-schema.d.ts.map +1 -0
- package/dist/params/index.d.ts +5 -0
- package/dist/params/index.d.ts.map +1 -0
- package/dist/params/index.js +34 -0
- package/dist/params/index.js.map +1 -0
- package/dist/params/resolve-schema.d.ts +34 -0
- package/dist/params/resolve-schema.d.ts.map +1 -0
- package/dist/plugin-context.d.ts +137 -0
- package/dist/plugin-context.d.ts.map +1 -0
- package/dist/plugins/adapter-build.d.ts +20 -1
- package/dist/plugins/adapter-build.d.ts.map +1 -1
- package/dist/plugins/build-manifest.d.ts +7 -3
- package/dist/plugins/build-manifest.d.ts.map +1 -1
- package/dist/plugins/build-report.d.ts +9 -7
- package/dist/plugins/build-report.d.ts.map +1 -1
- package/dist/plugins/cache.d.ts +73 -0
- package/dist/plugins/cache.d.ts.map +1 -0
- package/dist/plugins/client-chunks.d.ts +39 -0
- package/dist/plugins/client-chunks.d.ts.map +1 -0
- package/dist/plugins/cloudflare-wasm.d.ts +21 -0
- package/dist/plugins/cloudflare-wasm.d.ts.map +1 -0
- package/dist/plugins/content.d.ts +1 -1
- package/dist/plugins/content.d.ts.map +1 -1
- package/dist/plugins/dev-server.d.ts +17 -1
- package/dist/plugins/dev-server.d.ts.map +1 -1
- package/dist/plugins/entries.d.ts +1 -1
- package/dist/plugins/entries.d.ts.map +1 -1
- package/dist/plugins/fonts.d.ts +16 -73
- package/dist/plugins/fonts.d.ts.map +1 -1
- package/dist/plugins/mdx.d.ts +1 -1
- package/dist/plugins/mdx.d.ts.map +1 -1
- package/dist/plugins/routing.d.ts +1 -1
- package/dist/plugins/routing.d.ts.map +1 -1
- package/dist/plugins/server-bundle.d.ts.map +1 -1
- package/dist/plugins/shims.d.ts +29 -5
- package/dist/plugins/shims.d.ts.map +1 -1
- package/dist/plugins/static-build.d.ts +5 -26
- package/dist/plugins/static-build.d.ts.map +1 -1
- package/dist/routing/codegen-shared.d.ts +67 -0
- package/dist/routing/codegen-shared.d.ts.map +1 -0
- package/dist/routing/codegen-types.d.ts +64 -0
- package/dist/routing/codegen-types.d.ts.map +1 -0
- package/dist/routing/codegen.d.ts +7 -2
- package/dist/routing/codegen.d.ts.map +1 -1
- package/dist/routing/convention-lint.d.ts +41 -0
- package/dist/routing/convention-lint.d.ts.map +1 -0
- package/dist/routing/file-cache.d.ts +8 -0
- package/dist/routing/file-cache.d.ts.map +1 -0
- package/dist/routing/index.d.ts +7 -1
- package/dist/routing/index.d.ts.map +1 -1
- package/dist/routing/index.js +4 -2
- package/dist/routing/interception.d.ts +0 -5
- package/dist/routing/interception.d.ts.map +1 -1
- package/dist/routing/link-codegen.d.ts +90 -0
- package/dist/routing/link-codegen.d.ts.map +1 -0
- package/dist/routing/manifest-codegen.d.ts +32 -0
- package/dist/routing/manifest-codegen.d.ts.map +1 -0
- package/dist/routing/scanner.d.ts +1 -10
- package/dist/routing/scanner.d.ts.map +1 -1
- package/dist/routing/schema-validation.d.ts +35 -0
- package/dist/routing/schema-validation.d.ts.map +1 -0
- package/dist/routing/segment-classify.d.ts +75 -0
- package/dist/routing/segment-classify.d.ts.map +1 -0
- package/dist/routing/segment-codegen.d.ts +38 -0
- package/dist/routing/segment-codegen.d.ts.map +1 -0
- package/dist/routing/types.d.ts +77 -25
- package/dist/routing/types.d.ts.map +1 -1
- package/dist/routing/walkers.d.ts +51 -0
- package/dist/routing/walkers.d.ts.map +1 -0
- package/dist/rsc-runtime/rsc.d.ts +1 -1
- package/dist/rsc-runtime/rsc.d.ts.map +1 -1
- package/dist/rsc-runtime/ssr.d.ts +12 -0
- package/dist/rsc-runtime/ssr.d.ts.map +1 -1
- package/dist/schema-bridge.d.ts +91 -0
- package/dist/schema-bridge.d.ts.map +1 -0
- package/dist/search-params/define.d.ts +157 -0
- package/dist/search-params/define.d.ts.map +1 -0
- package/dist/search-params/index.d.ts +4 -7
- package/dist/search-params/index.d.ts.map +1 -1
- package/dist/search-params/index.js +37 -440
- package/dist/search-params/index.js.map +1 -1
- package/dist/search-params/registry.d.ts +2 -2
- package/dist/search-params/registry.d.ts.map +1 -1
- package/dist/search-params/wrappers.d.ts +53 -0
- package/dist/search-params/wrappers.d.ts.map +1 -0
- package/dist/segment-params/define.d.ts +89 -0
- package/dist/segment-params/define.d.ts.map +1 -0
- package/dist/segment-params/index.d.ts +3 -0
- package/dist/segment-params/index.d.ts.map +1 -0
- package/dist/segment-params/index.js +2 -0
- package/dist/server/access-gate.d.ts +8 -3
- package/dist/server/access-gate.d.ts.map +1 -1
- package/dist/server/action-client.d.ts +41 -6
- package/dist/server/action-client.d.ts.map +1 -1
- package/dist/server/action-encryption.d.ts +76 -0
- package/dist/server/action-encryption.d.ts.map +1 -0
- package/dist/server/action-handler.d.ts +35 -1
- package/dist/server/action-handler.d.ts.map +1 -1
- package/dist/server/actions.d.ts +9 -30
- package/dist/server/actions.d.ts.map +1 -1
- package/dist/server/als-registry.d.ts +70 -11
- package/dist/server/als-registry.d.ts.map +1 -1
- package/dist/server/asset-headers.d.ts +1 -15
- package/dist/server/asset-headers.d.ts.map +1 -1
- package/dist/server/body-limits.d.ts.map +1 -1
- package/dist/server/build-manifest.d.ts +6 -29
- package/dist/server/build-manifest.d.ts.map +1 -1
- package/dist/server/canonicalize.d.ts +10 -0
- package/dist/server/canonicalize.d.ts.map +1 -1
- package/dist/server/coalesce-tick.d.ts +40 -0
- package/dist/server/coalesce-tick.d.ts.map +1 -0
- package/dist/server/cookie-context.d.ts +170 -0
- package/dist/server/cookie-context.d.ts.map +1 -0
- package/dist/server/cookie-parsing.d.ts +51 -0
- package/dist/server/cookie-parsing.d.ts.map +1 -0
- package/dist/server/csrf.d.ts +3 -2
- package/dist/server/csrf.d.ts.map +1 -1
- package/dist/server/default-logger.d.ts +22 -0
- package/dist/server/default-logger.d.ts.map +1 -0
- package/dist/server/deny-boundary.d.ts +115 -0
- package/dist/server/deny-boundary.d.ts.map +1 -0
- package/dist/server/deny-renderer.d.ts +2 -2
- package/dist/server/deny-renderer.d.ts.map +1 -1
- package/dist/server/dev-source-map.d.ts +22 -0
- package/dist/server/dev-source-map.d.ts.map +1 -0
- package/dist/server/early-hints-sender.d.ts.map +1 -1
- package/dist/server/early-hints.d.ts +13 -11
- package/dist/server/early-hints.d.ts.map +1 -1
- package/dist/server/error-boundary-wrapper.d.ts +7 -1
- package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
- package/dist/server/fallback-error.d.ts +12 -7
- package/dist/server/fallback-error.d.ts.map +1 -1
- package/dist/server/flight-injection-state.d.ts +66 -0
- package/dist/server/flight-injection-state.d.ts.map +1 -0
- package/dist/server/flight-scripts.d.ts +42 -0
- package/dist/server/flight-scripts.d.ts.map +1 -0
- package/dist/server/form-data.d.ts +29 -0
- package/dist/server/form-data.d.ts.map +1 -1
- package/dist/server/html-injector-core.d.ts +221 -0
- package/dist/server/html-injector-core.d.ts.map +1 -0
- package/dist/server/html-injectors.d.ts +81 -41
- package/dist/server/html-injectors.d.ts.map +1 -1
- package/dist/server/index.d.ts +10 -46
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +170 -2911
- package/dist/server/index.js.map +1 -1
- package/dist/server/internal.d.ts +44 -0
- package/dist/server/internal.d.ts.map +1 -0
- package/dist/server/internal.js +3015 -0
- package/dist/server/internal.js.map +1 -0
- package/dist/server/logger.d.ts +39 -7
- package/dist/server/logger.d.ts.map +1 -1
- package/dist/server/metadata-routes.d.ts +23 -7
- package/dist/server/metadata-routes.d.ts.map +1 -1
- package/dist/server/middleware-runner.d.ts +36 -4
- package/dist/server/middleware-runner.d.ts.map +1 -1
- package/dist/server/node-stream-transforms.d.ts +119 -0
- package/dist/server/node-stream-transforms.d.ts.map +1 -0
- package/dist/server/param-coercion.d.ts +54 -0
- package/dist/server/param-coercion.d.ts.map +1 -0
- package/dist/server/pipeline-helpers.d.ts +95 -0
- package/dist/server/pipeline-helpers.d.ts.map +1 -0
- package/dist/server/pipeline-interception.d.ts +1 -1
- package/dist/server/pipeline-interception.d.ts.map +1 -1
- package/dist/server/pipeline-metadata.d.ts +6 -0
- package/dist/server/pipeline-metadata.d.ts.map +1 -1
- package/dist/server/pipeline-outcome.d.ts +49 -0
- package/dist/server/pipeline-outcome.d.ts.map +1 -0
- package/dist/server/pipeline-phases.d.ts +56 -0
- package/dist/server/pipeline-phases.d.ts.map +1 -0
- package/dist/server/pipeline.d.ts +122 -19
- package/dist/server/pipeline.d.ts.map +1 -1
- package/dist/server/port-resolution.d.ts +117 -0
- package/dist/server/port-resolution.d.ts.map +1 -0
- package/dist/server/primitives.d.ts +75 -31
- package/dist/server/primitives.d.ts.map +1 -1
- package/dist/server/render-timeout.d.ts +51 -0
- package/dist/server/render-timeout.d.ts.map +1 -0
- package/dist/server/render-utils.d.ts +25 -0
- package/dist/server/render-utils.d.ts.map +1 -0
- package/dist/server/request-context.d.ts +62 -107
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/route-element-builder.d.ts +30 -18
- package/dist/server/route-element-builder.d.ts.map +1 -1
- package/dist/server/route-handler.d.ts.map +1 -1
- package/dist/server/route-matcher.d.ts +25 -36
- package/dist/server/route-matcher.d.ts.map +1 -1
- package/dist/server/rsc-entry/action-middleware-runner.d.ts +66 -0
- package/dist/server/rsc-entry/action-middleware-runner.d.ts.map +1 -0
- package/dist/server/rsc-entry/api-handler.d.ts +12 -3
- package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
- package/dist/server/rsc-entry/error-renderer.d.ts +26 -13
- package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/helpers.d.ts +51 -23
- package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
- package/dist/server/rsc-entry/index.d.ts +19 -8
- package/dist/server/rsc-entry/index.d.ts.map +1 -1
- package/dist/server/rsc-entry/render-route.d.ts +50 -0
- package/dist/server/rsc-entry/render-route.d.ts.map +1 -0
- package/dist/server/rsc-entry/revalidate-renderer.d.ts +108 -0
- package/dist/server/rsc-entry/revalidate-renderer.d.ts.map +1 -0
- package/dist/server/rsc-entry/rsc-payload.d.ts +3 -3
- package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
- package/dist/server/rsc-entry/rsc-stream.d.ts +17 -1
- package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-bridge.d.ts +5 -1
- package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-renderer.d.ts +34 -4
- package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/wrap-action-dispatch.d.ts +119 -0
- package/dist/server/rsc-entry/wrap-action-dispatch.d.ts.map +1 -0
- package/dist/server/safe-load.d.ts +46 -0
- package/dist/server/safe-load.d.ts.map +1 -0
- package/dist/server/sensitive-fields.d.ts +74 -0
- package/dist/server/sensitive-fields.d.ts.map +1 -0
- package/dist/server/sitemap-generator.d.ts +129 -0
- package/dist/server/sitemap-generator.d.ts.map +1 -0
- package/dist/server/sitemap-handler.d.ts +22 -0
- package/dist/server/sitemap-handler.d.ts.map +1 -0
- package/dist/server/slot-resolver.d.ts +7 -5
- package/dist/server/slot-resolver.d.ts.map +1 -1
- package/dist/server/ssr-bridge-types.d.ts +121 -0
- package/dist/server/ssr-bridge-types.d.ts.map +1 -0
- package/dist/server/ssr-entry.d.ts +2 -43
- package/dist/server/ssr-entry.d.ts.map +1 -1
- package/dist/server/ssr-render.d.ts +64 -21
- package/dist/server/ssr-render.d.ts.map +1 -1
- package/dist/server/ssr-wrappers.d.ts +50 -0
- package/dist/server/ssr-wrappers.d.ts.map +1 -0
- package/dist/server/state-tree-diff.d.ts +12 -5
- package/dist/server/state-tree-diff.d.ts.map +1 -1
- package/dist/server/status-code-resolver.d.ts +22 -11
- package/dist/server/status-code-resolver.d.ts.map +1 -1
- package/dist/server/stream-utils.d.ts +36 -0
- package/dist/server/stream-utils.d.ts.map +1 -0
- package/dist/server/tracing.d.ts +7 -6
- package/dist/server/tracing.d.ts.map +1 -1
- package/dist/server/tree-builder.d.ts +62 -30
- package/dist/server/tree-builder.d.ts.map +1 -1
- package/dist/server/tree-match.d.ts +49 -0
- package/dist/server/tree-match.d.ts.map +1 -0
- package/dist/server/types.d.ts +71 -6
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/utils/escape-html.d.ts +14 -0
- package/dist/server/utils/escape-html.d.ts.map +1 -0
- package/dist/server/utils/mdx-file.d.ts +15 -0
- package/dist/server/utils/mdx-file.d.ts.map +1 -0
- package/dist/server/version-skew.d.ts +61 -0
- package/dist/server/version-skew.d.ts.map +1 -0
- package/dist/shared/head-header.d.ts +54 -0
- package/dist/shared/head-header.d.ts.map +1 -0
- package/dist/shared/href-validation.d.ts +49 -0
- package/dist/shared/href-validation.d.ts.map +1 -0
- package/dist/shared/merge-search-params.d.ts +22 -0
- package/dist/shared/merge-search-params.d.ts.map +1 -0
- package/dist/shared/redirect-type.d.ts +17 -0
- package/dist/shared/redirect-type.d.ts.map +1 -0
- package/dist/shims/font-google.d.ts +1 -1
- package/dist/shims/font-google.d.ts.map +1 -1
- package/dist/shims/font-google.js +42 -0
- package/dist/shims/font-google.js.map +1 -0
- package/dist/shims/font-local.d.ts +26 -0
- package/dist/shims/font-local.d.ts.map +1 -0
- package/dist/shims/font-local.js +20 -0
- package/dist/shims/font-local.js.map +1 -0
- package/dist/shims/headers.d.ts +53 -1
- package/dist/shims/headers.d.ts.map +1 -1
- package/dist/shims/image.d.ts +16 -16
- package/dist/shims/navigation-client.d.ts +35 -11
- package/dist/shims/navigation-client.d.ts.map +1 -1
- package/dist/shims/navigation.d.ts +11 -5
- package/dist/shims/navigation.d.ts.map +1 -1
- package/dist/utils/state-machine.d.ts +80 -0
- package/dist/utils/state-machine.d.ts.map +1 -0
- package/package.json +63 -24
- package/src/adapters/build-output-helper.ts +139 -0
- package/src/adapters/cloudflare-dev.ts +177 -0
- package/src/adapters/cloudflare-kv-cache.ts +179 -0
- package/src/adapters/cloudflare.ts +356 -116
- package/src/adapters/compress-module.ts +27 -92
- package/src/adapters/nitro.ts +155 -99
- package/src/adapters/raw-imports.d.ts +5 -0
- package/src/adapters/shared.ts +40 -0
- package/src/adapters/wrangler.d.ts +7 -0
- package/src/cache/cache-api.ts +47 -0
- package/src/cache/handler-store.ts +68 -0
- package/src/cache/index.ts +84 -18
- package/src/cache/invalidation-epoch.ts +93 -0
- package/src/cache/redis-handler.ts +110 -15
- package/src/cache/singleflight.ts +62 -4
- package/src/cache/sizeof.ts +33 -0
- package/src/cache/stable-stringify.ts +65 -2
- package/src/cache/timber-cache.ts +132 -36
- package/src/cli-schema-sync.ts +388 -0
- package/src/cli.ts +98 -34
- package/src/client/browser-dev.ts +153 -1
- package/src/client/browser-entry/action-dispatch.ts +119 -0
- package/src/client/browser-entry/hmr.ts +70 -0
- package/src/client/browser-entry/hydrate.ts +187 -0
- package/src/client/browser-entry/index.ts +111 -0
- package/src/client/browser-entry/post-hydration.ts +104 -0
- package/src/client/browser-entry/router-init.ts +292 -0
- package/src/client/browser-entry/rsc-stream.ts +157 -0
- package/src/client/browser-entry/scroll.ts +50 -0
- package/src/client/error-boundary.tsx +127 -22
- package/src/client/error-reconstituter.tsx +79 -0
- package/src/client/form.tsx +31 -32
- package/src/client/history.ts +11 -3
- package/src/client/index.ts +67 -45
- package/src/client/internal.ts +58 -0
- package/src/client/link.tsx +346 -150
- package/src/client/navigation-api-types.ts +112 -0
- package/src/client/navigation-api.ts +347 -0
- package/src/client/navigation-context.ts +15 -7
- package/src/client/navigation-root.tsx +355 -0
- package/src/client/nuqs-adapter.tsx +16 -3
- package/src/client/router-ref.ts +1 -1
- package/src/client/router.ts +490 -140
- package/src/client/rsc-fetch.ts +220 -17
- package/src/client/segment-cache.ts +6 -3
- package/src/client/segment-outlet.tsx +77 -0
- package/src/client/segment-update-context.ts +42 -0
- package/src/client/shallow-url.ts +22 -0
- package/src/client/ssr-data.ts +13 -5
- package/src/client/state.ts +2 -2
- package/src/client/top-loader.tsx +11 -9
- package/src/client/use-cookie.ts +31 -2
- package/src/client/use-link-status.ts +7 -7
- package/src/client/use-pathname.ts +1 -0
- package/src/client/use-pending-navigation.ts +40 -0
- package/src/client/use-query-states.ts +9 -3
- package/src/client/use-router.ts +4 -1
- package/src/client/use-search-params.ts +31 -44
- package/src/client/{use-params.ts → use-segment-params.ts} +9 -6
- package/src/codec.ts +147 -0
- package/src/config-types.ts +292 -0
- package/src/config-validation.ts +311 -0
- package/src/content/index.ts +5 -13
- package/src/cookies/define-cookie.ts +217 -53
- package/src/cookies/index.ts +12 -1
- package/src/cookies/json-cookie.ts +105 -0
- package/src/cookies/validation.ts +192 -0
- package/src/dev-tools/404-page.ts +286 -0
- package/src/dev-tools/browser-logs.ts +291 -0
- package/src/dev-tools/dev-page-shell.ts +260 -0
- package/src/dev-tools/error-page.ts +331 -0
- package/src/dev-tools/holding-server.ts +187 -0
- package/src/dev-tools/hydration-overlay.ts +158 -0
- package/src/dev-tools/index.ts +83 -0
- package/src/dev-tools/instrumentation.ts +213 -0
- package/src/{plugins/dev-logs.ts → dev-tools/logs.ts} +9 -5
- package/src/dev-tools/overlay.ts +469 -0
- package/src/dev-tools/stack-classifier.ts +75 -0
- package/src/dev-tools/terminal.ts +183 -0
- package/src/fonts/ast-walk.ts +235 -0
- package/src/fonts/ast.ts +477 -126
- package/src/fonts/bundle.ts +138 -0
- package/src/fonts/dev-middleware.ts +85 -0
- package/src/fonts/fallbacks.ts +0 -23
- package/src/fonts/google.ts +7 -3
- package/src/fonts/local.ts +9 -8
- package/src/fonts/paths.ts +58 -0
- package/src/fonts/pipeline.ts +316 -0
- package/src/fonts/transform.ts +344 -0
- package/src/fonts/types.ts +52 -1
- package/src/fonts/virtual-modules.ts +179 -0
- package/src/index.ts +417 -346
- package/src/params/codec-registry.ts +34 -0
- package/src/params/define-schema.ts +115 -0
- package/src/params/index.ts +17 -0
- package/src/params/resolve-schema.ts +84 -0
- package/src/plugin-context.ts +325 -0
- package/src/plugins/adapter-build.ts +98 -4
- package/src/plugins/build-manifest.ts +168 -23
- package/src/plugins/build-report.ts +16 -25
- package/src/plugins/cache.ts +285 -0
- package/src/plugins/client-chunks.ts +113 -0
- package/src/plugins/cloudflare-wasm.ts +141 -0
- package/src/plugins/content.ts +1 -1
- package/src/plugins/dev-server.ts +264 -46
- package/src/plugins/entries.ts +110 -8
- package/src/plugins/fonts.ts +170 -663
- package/src/plugins/mdx.ts +47 -10
- package/src/plugins/routing.ts +237 -241
- package/src/plugins/server-bundle.ts +85 -12
- package/src/plugins/shims.ts +207 -64
- package/src/plugins/static-build.ts +15 -89
- package/src/routing/codegen-shared.ts +115 -0
- package/src/routing/codegen-types.ts +65 -0
- package/src/routing/codegen.ts +380 -178
- package/src/routing/convention-lint.ts +358 -0
- package/src/routing/file-cache.ts +23 -0
- package/src/routing/index.ts +10 -1
- package/src/routing/interception.ts +3 -22
- package/src/routing/link-codegen.ts +310 -0
- package/src/routing/manifest-codegen.ts +290 -0
- package/src/routing/scanner.ts +248 -188
- package/src/routing/schema-validation.ts +149 -0
- package/src/routing/segment-classify.ts +188 -0
- package/src/routing/segment-codegen.ts +98 -0
- package/src/routing/types.ts +78 -25
- package/src/routing/walkers.ts +90 -0
- package/src/rsc-runtime/rsc.ts +2 -0
- package/src/rsc-runtime/ssr.ts +50 -0
- package/src/rsc-runtime/vendor-types.d.ts +7 -0
- package/src/schema-bridge.ts +252 -0
- package/src/search-params/define.ts +570 -0
- package/src/search-params/index.ts +14 -20
- package/src/search-params/registry.ts +2 -2
- package/src/search-params/wrappers.ts +110 -0
- package/src/segment-params/define.ts +249 -0
- package/src/segment-params/index.ts +9 -0
- package/src/server/access-gate.tsx +84 -34
- package/src/server/action-client.ts +119 -28
- package/src/server/action-encryption.ts +144 -0
- package/src/server/action-handler.ts +122 -16
- package/src/server/actions.ts +39 -53
- package/src/server/als-registry.ts +108 -20
- package/src/server/asset-headers.ts +8 -34
- package/src/server/body-limits.ts +10 -2
- package/src/server/build-manifest.ts +13 -56
- package/src/server/canonicalize.ts +6 -3
- package/src/server/coalesce-tick.ts +75 -0
- package/src/server/compress.ts +34 -7
- package/src/server/cookie-context.ts +484 -0
- package/src/server/cookie-parsing.ts +147 -0
- package/src/server/csrf.ts +39 -6
- package/src/server/default-logger.ts +99 -0
- package/src/server/deny-boundary.ts +311 -0
- package/src/server/deny-renderer.ts +80 -64
- package/src/server/dev-source-map.ts +31 -0
- package/src/server/early-hints-sender.ts +3 -2
- package/src/server/early-hints.ts +37 -27
- package/src/server/error-boundary-wrapper.ts +61 -22
- package/src/server/fallback-error.ts +79 -102
- package/src/server/flight-injection-state.ts +113 -0
- package/src/server/flight-scripts.ts +62 -0
- package/src/server/form-data.ts +101 -5
- package/src/server/html-injector-core.ts +437 -0
- package/src/server/html-injectors.ts +256 -251
- package/src/server/index.ts +29 -183
- package/src/server/internal.ts +165 -0
- package/src/server/logger.ts +67 -36
- package/src/server/metadata-routes.ts +44 -19
- package/src/server/middleware-runner.ts +75 -4
- package/src/server/node-stream-transforms.ts +331 -0
- package/src/server/param-coercion.ts +206 -0
- package/src/server/pipeline-helpers.ts +204 -0
- package/src/server/pipeline-interception.ts +32 -18
- package/src/server/pipeline-metadata.ts +13 -0
- package/src/server/pipeline-outcome.ts +197 -0
- package/src/server/pipeline-phases.ts +527 -0
- package/src/server/pipeline.ts +213 -382
- package/src/server/port-resolution.ts +215 -0
- package/src/server/primitives.ts +126 -63
- package/src/server/render-timeout.ts +108 -0
- package/src/server/render-utils.ts +31 -0
- package/src/server/request-context.ts +168 -337
- package/src/server/route-element-builder.ts +481 -222
- package/src/server/route-handler.ts +31 -4
- package/src/server/route-matcher.ts +144 -277
- package/src/server/rsc-entry/action-middleware-runner.ts +167 -0
- package/src/server/rsc-entry/api-handler.ts +69 -32
- package/src/server/rsc-entry/error-renderer.ts +306 -89
- package/src/server/rsc-entry/helpers.ts +160 -59
- package/src/server/rsc-entry/index.ts +299 -329
- package/src/server/rsc-entry/render-route.ts +311 -0
- package/src/server/rsc-entry/revalidate-renderer.ts +344 -0
- package/src/server/rsc-entry/rsc-payload.ts +71 -26
- package/src/server/rsc-entry/rsc-stream.ts +85 -13
- package/src/server/rsc-entry/ssr-bridge.ts +18 -5
- package/src/server/rsc-entry/ssr-renderer.ts +273 -43
- package/src/server/rsc-entry/wrap-action-dispatch.ts +449 -0
- package/src/server/safe-load.ts +60 -0
- package/src/server/sensitive-fields.ts +230 -0
- package/src/server/sitemap-generator.ts +338 -0
- package/src/server/sitemap-handler.ts +148 -0
- package/src/server/slot-resolver.ts +258 -257
- package/src/server/ssr-bridge-types.ts +124 -0
- package/src/server/ssr-entry.ts +206 -78
- package/src/server/ssr-render.ts +345 -82
- package/src/server/ssr-wrappers.tsx +141 -0
- package/src/server/state-tree-diff.ts +30 -23
- package/src/server/status-code-resolver.ts +115 -130
- package/src/server/stream-utils.ts +213 -0
- package/src/server/tracing.ts +38 -11
- package/src/server/tree-builder.ts +204 -90
- package/src/server/tree-match.ts +220 -0
- package/src/server/types.ts +78 -9
- package/src/server/utils/escape-html.ts +20 -0
- package/src/server/utils/mdx-file.ts +22 -0
- package/src/server/version-skew.ts +104 -0
- package/src/shared/head-header.ts +69 -0
- package/src/shared/href-validation.ts +159 -0
- package/src/shared/merge-search-params.ts +55 -0
- package/src/shared/redirect-type.ts +17 -0
- package/src/shims/font-google.ts +1 -1
- package/src/shims/font-local.ts +34 -0
- package/src/shims/headers.ts +122 -1
- package/src/shims/navigation-client.ts +51 -29
- package/src/shims/navigation.ts +14 -7
- package/src/utils/state-machine.ts +111 -0
- package/dist/_chunks/als-registry-B7DbZ2hS.js +0 -41
- package/dist/_chunks/als-registry-B7DbZ2hS.js.map +0 -1
- package/dist/_chunks/debug-B3Gypr3D.js +0 -108
- package/dist/_chunks/debug-B3Gypr3D.js.map +0 -1
- package/dist/_chunks/format-RyoGQL74.js +0 -164
- package/dist/_chunks/format-RyoGQL74.js.map +0 -1
- package/dist/_chunks/interception-BOoWmLUA.js +0 -676
- package/dist/_chunks/interception-BOoWmLUA.js.map +0 -1
- package/dist/_chunks/metadata-routes-Cjmvi3rQ.js.map +0 -1
- package/dist/_chunks/request-context-BQUC8PHn.js +0 -330
- package/dist/_chunks/request-context-BQUC8PHn.js.map +0 -1
- package/dist/_chunks/ssr-data-MjmprTmO.js.map +0 -1
- package/dist/_chunks/tracing-CemImE6h.js +0 -187
- package/dist/_chunks/tracing-CemImE6h.js.map +0 -1
- package/dist/_chunks/use-cookie-DX-l1_5E.js +0 -91
- package/dist/_chunks/use-cookie-DX-l1_5E.js.map +0 -1
- package/dist/_chunks/use-query-states-D5KaffOK.js.map +0 -1
- package/dist/cache/register-cached-function.d.ts +0 -17
- package/dist/cache/register-cached-function.d.ts.map +0 -1
- package/dist/client/browser-entry.d.ts +0 -21
- package/dist/client/browser-entry.d.ts.map +0 -1
- package/dist/client/link-status-provider.d.ts +0 -11
- package/dist/client/link-status-provider.d.ts.map +0 -1
- package/dist/client/segment-merger.d.ts +0 -119
- package/dist/client/segment-merger.d.ts.map +0 -1
- package/dist/client/stale-reload.d.ts +0 -44
- package/dist/client/stale-reload.d.ts.map +0 -1
- package/dist/client/transition-root.d.ts +0 -74
- package/dist/client/transition-root.d.ts.map +0 -1
- package/dist/client/use-navigation-pending.d.ts +0 -26
- package/dist/client/use-navigation-pending.d.ts.map +0 -1
- package/dist/client/use-params.d.ts.map +0 -1
- package/dist/plugins/cache-transform.d.ts +0 -36
- package/dist/plugins/cache-transform.d.ts.map +0 -1
- package/dist/plugins/dev-error-overlay.d.ts +0 -60
- package/dist/plugins/dev-error-overlay.d.ts.map +0 -1
- package/dist/plugins/dev-logs.d.ts.map +0 -1
- package/dist/plugins/dynamic-transform.d.ts +0 -72
- package/dist/plugins/dynamic-transform.d.ts.map +0 -1
- package/dist/plugins/server-action-exports.d.ts +0 -26
- package/dist/plugins/server-action-exports.d.ts.map +0 -1
- package/dist/routing/status-file-lint.d.ts +0 -33
- package/dist/routing/status-file-lint.d.ts.map +0 -1
- package/dist/search-params/analyze.d.ts +0 -54
- package/dist/search-params/analyze.d.ts.map +0 -1
- package/dist/search-params/builtin-codecs.d.ts +0 -105
- package/dist/search-params/builtin-codecs.d.ts.map +0 -1
- package/dist/search-params/codecs.d.ts +0 -53
- package/dist/search-params/codecs.d.ts.map +0 -1
- package/dist/search-params/create.d.ts +0 -106
- package/dist/search-params/create.d.ts.map +0 -1
- package/dist/server/dev-fetch-instrumentation.d.ts +0 -22
- package/dist/server/dev-fetch-instrumentation.d.ts.map +0 -1
- package/dist/server/dev-logger.d.ts.map +0 -1
- package/dist/server/dev-span-processor.d.ts +0 -29
- package/dist/server/dev-span-processor.d.ts.map +0 -1
- package/dist/server/dev-warnings.d.ts +0 -129
- package/dist/server/dev-warnings.d.ts.map +0 -1
- package/dist/server/flush.d.ts +0 -74
- package/dist/server/flush.d.ts.map +0 -1
- package/dist/server/manifest-status-resolver.d.ts +0 -58
- package/dist/server/manifest-status-resolver.d.ts.map +0 -1
- package/dist/server/prerender.d.ts +0 -77
- package/dist/server/prerender.d.ts.map +0 -1
- package/dist/utils/directive-parser.d.ts +0 -70
- package/dist/utils/directive-parser.d.ts.map +0 -1
- package/src/cache/register-cached-function.ts +0 -103
- package/src/client/browser-entry.ts +0 -678
- package/src/client/link-status-provider.tsx +0 -30
- package/src/client/segment-merger.ts +0 -339
- package/src/client/stale-reload.ts +0 -87
- package/src/client/transition-root.tsx +0 -166
- package/src/client/use-navigation-pending.ts +0 -38
- package/src/plugins/cache-transform.ts +0 -199
- package/src/plugins/dev-error-overlay.ts +0 -230
- package/src/plugins/dynamic-transform.ts +0 -161
- package/src/plugins/server-action-exports.ts +0 -220
- package/src/routing/status-file-lint.ts +0 -112
- package/src/search-params/analyze.ts +0 -192
- package/src/search-params/builtin-codecs.ts +0 -228
- package/src/search-params/codecs.ts +0 -153
- package/src/search-params/create.ts +0 -321
- package/src/server/dev-fetch-instrumentation.ts +0 -96
- package/src/server/dev-span-processor.ts +0 -78
- package/src/server/dev-warnings.ts +0 -283
- package/src/server/flush.ts +0 -182
- package/src/server/manifest-status-resolver.ts +0 -215
- package/src/server/prerender.ts +0 -139
- package/src/utils/directive-parser.ts +0 -529
- /package/src/{server/dev-logger.ts → dev-tools/logger.ts} +0 -0
package/src/cache/index.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// @timber-js/app/cache — Caching primitives
|
|
2
2
|
|
|
3
|
+
import { estimateByteSize } from './sizeof.js';
|
|
4
|
+
|
|
3
5
|
export interface CacheHandler {
|
|
4
6
|
get(key: string): Promise<{ value: unknown; stale: boolean } | null>;
|
|
5
7
|
set(key: string, value: unknown, opts: { ttl: number; tags: string[] }): Promise<void>;
|
|
@@ -12,19 +14,42 @@ export interface CacheOptions<Fn extends (...args: any[]) => any> {
|
|
|
12
14
|
key?: (...args: Parameters<Fn>) => string;
|
|
13
15
|
staleWhileRevalidate?: boolean;
|
|
14
16
|
tags?: string[] | ((...args: Parameters<Fn>) => string[]);
|
|
17
|
+
/** Timeout (ms) for singleflight-coalesced calls. Prevents hung fn() from
|
|
18
|
+
* permanently blocking all future callers for the same cache key. See TIM-518. */
|
|
19
|
+
timeoutMs?: number;
|
|
15
20
|
}
|
|
16
21
|
|
|
17
22
|
export interface MemoryCacheHandlerOptions {
|
|
18
23
|
/** Maximum number of entries. Oldest accessed entries are evicted first. Default: 1000. */
|
|
24
|
+
maxEntries?: number;
|
|
25
|
+
/**
|
|
26
|
+
* @deprecated Use `maxEntries` instead. Will be removed in a future release.
|
|
27
|
+
* Alias for `maxEntries` — maximum number of entries (not bytes).
|
|
28
|
+
*/
|
|
19
29
|
maxSize?: number;
|
|
30
|
+
/** Maximum total byte budget for all cached values. Oldest entries are evicted when exceeded. Default: no limit. */
|
|
31
|
+
maxBytes?: number;
|
|
32
|
+
/** Maximum byte size for a single cache entry. Entries exceeding this are silently dropped. Default: no limit. */
|
|
33
|
+
maxEntryBytes?: number;
|
|
20
34
|
}
|
|
21
35
|
|
|
22
36
|
export class MemoryCacheHandler implements CacheHandler {
|
|
23
|
-
private store = new Map<
|
|
24
|
-
|
|
37
|
+
private store = new Map<
|
|
38
|
+
string,
|
|
39
|
+
{ value: unknown; expiresAt: number; tags: string[]; byteSize: number }
|
|
40
|
+
>();
|
|
41
|
+
private maxEntries: number;
|
|
42
|
+
private maxBytes: number | undefined;
|
|
43
|
+
private maxEntryBytes: number | undefined;
|
|
44
|
+
private currentBytes = 0;
|
|
45
|
+
private readonly _trackBytes: boolean;
|
|
25
46
|
|
|
26
47
|
constructor(opts?: MemoryCacheHandlerOptions) {
|
|
27
|
-
|
|
48
|
+
// maxEntries takes precedence over deprecated maxSize
|
|
49
|
+
this.maxEntries = opts?.maxEntries ?? opts?.maxSize ?? 1000;
|
|
50
|
+
this.maxBytes = opts?.maxBytes;
|
|
51
|
+
this.maxEntryBytes = opts?.maxEntryBytes;
|
|
52
|
+
this._trackBytes = this.maxBytes !== undefined || this.maxEntryBytes !== undefined;
|
|
28
53
|
}
|
|
29
54
|
|
|
30
55
|
async get(key: string) {
|
|
@@ -40,18 +65,33 @@ export class MemoryCacheHandler implements CacheHandler {
|
|
|
40
65
|
}
|
|
41
66
|
|
|
42
67
|
async set(key: string, value: unknown, opts: { ttl: number; tags: string[] }) {
|
|
43
|
-
|
|
68
|
+
const byteSize = this._trackBytes ? estimateByteSize(value) : 0;
|
|
69
|
+
|
|
70
|
+
// Reject entries exceeding per-entry byte limit
|
|
71
|
+
if (this.maxEntryBytes !== undefined && byteSize > this.maxEntryBytes) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// If key already exists, delete first to refresh insertion order and reclaim bytes
|
|
44
76
|
if (this.store.has(key)) {
|
|
77
|
+
const existing = this.store.get(key)!;
|
|
78
|
+
this.currentBytes -= existing.byteSize;
|
|
45
79
|
this.store.delete(key);
|
|
46
80
|
}
|
|
47
81
|
|
|
48
|
-
// Evict oldest entries (front of Map) if at capacity
|
|
49
|
-
while (this.store.size >= this.
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
82
|
+
// Evict oldest entries (front of Map) if at entry count capacity
|
|
83
|
+
while (this.store.size >= this.maxEntries) {
|
|
84
|
+
this.evictOldest();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Evict oldest entries if byte budget would be exceeded
|
|
88
|
+
if (this.maxBytes !== undefined) {
|
|
89
|
+
while (this.currentBytes + byteSize > this.maxBytes && this.store.size > 0) {
|
|
90
|
+
this.evictOldest();
|
|
91
|
+
}
|
|
92
|
+
// If the single entry exceeds the total byte budget, don't store it
|
|
93
|
+
if (this.currentBytes + byteSize > this.maxBytes) {
|
|
94
|
+
return;
|
|
55
95
|
}
|
|
56
96
|
}
|
|
57
97
|
|
|
@@ -59,16 +99,23 @@ export class MemoryCacheHandler implements CacheHandler {
|
|
|
59
99
|
value,
|
|
60
100
|
expiresAt: Date.now() + opts.ttl * 1000,
|
|
61
101
|
tags: opts.tags,
|
|
102
|
+
byteSize,
|
|
62
103
|
});
|
|
104
|
+
this.currentBytes += byteSize;
|
|
63
105
|
}
|
|
64
106
|
|
|
65
107
|
async invalidate(opts: { key?: string; tag?: string }) {
|
|
66
108
|
if (opts.key) {
|
|
67
|
-
this.store.
|
|
109
|
+
const entry = this.store.get(opts.key);
|
|
110
|
+
if (entry) {
|
|
111
|
+
this.currentBytes -= entry.byteSize;
|
|
112
|
+
this.store.delete(opts.key);
|
|
113
|
+
}
|
|
68
114
|
}
|
|
69
115
|
if (opts.tag) {
|
|
70
116
|
for (const [key, entry] of this.store) {
|
|
71
117
|
if (entry.tags.includes(opts.tag)) {
|
|
118
|
+
this.currentBytes -= entry.byteSize;
|
|
72
119
|
this.store.delete(key);
|
|
73
120
|
}
|
|
74
121
|
}
|
|
@@ -79,13 +126,32 @@ export class MemoryCacheHandler implements CacheHandler {
|
|
|
79
126
|
get size(): number {
|
|
80
127
|
return this.store.size;
|
|
81
128
|
}
|
|
129
|
+
|
|
130
|
+
/** Estimated total byte size of all cached values. Only tracked when maxBytes or maxEntryBytes is configured; returns 0 otherwise. */
|
|
131
|
+
get bytes(): number {
|
|
132
|
+
return this.currentBytes;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** Evict the oldest entry (front of Map). */
|
|
136
|
+
private evictOldest(): void {
|
|
137
|
+
const oldest = this.store.keys().next().value;
|
|
138
|
+
if (oldest !== undefined) {
|
|
139
|
+
const entry = this.store.get(oldest)!;
|
|
140
|
+
this.currentBytes -= entry.byteSize;
|
|
141
|
+
this.store.delete(oldest);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
82
144
|
}
|
|
83
145
|
|
|
84
146
|
export { RedisCacheHandler } from './redis-handler';
|
|
85
147
|
export type { RedisClient } from './redis-handler';
|
|
86
|
-
export {
|
|
87
|
-
export {
|
|
88
|
-
export
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
export
|
|
148
|
+
export { cache } from './cache-api';
|
|
149
|
+
export { setCacheHandler, getCacheHandler } from './handler-store';
|
|
150
|
+
export { setDefaultSingleflightTimeout } from './timber-cache';
|
|
151
|
+
// NOTE: registerCachedFunction (runtime for 'use cache' directive) removed.
|
|
152
|
+
// Future feature pending design doc. See design/06-caching.md.
|
|
153
|
+
export { estimateByteSize } from './sizeof';
|
|
154
|
+
// stableStringify, createSingleflight, and SingleflightTimeoutError are
|
|
155
|
+
// internal utilities used by the cache implementation. They are not
|
|
156
|
+
// re-exported here — import directly from the source files if needed
|
|
157
|
+
// within the package. See TIM-720.
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-process invalidation epoch tracking for timber.cache (TIM-1028).
|
|
3
|
+
*
|
|
4
|
+
* handler.set for a cache miss runs after `fn()` resolves. An explicit
|
|
5
|
+
* `cache.invalidate({ tag })` / `revalidateTag` that lands while fn is in
|
|
6
|
+
* flight would otherwise be silently undone — the just-invalidated value
|
|
7
|
+
* re-stored as fresh for the full TTL, resurrecting pre-mutation data.
|
|
8
|
+
*
|
|
9
|
+
* Every invalidation bumps a monotonic epoch and records it against the
|
|
10
|
+
* invalidated key/tag. Before storing a result, the cache wrapper checks
|
|
11
|
+
* whether its key or any of its tags were invalidated after fn started and
|
|
12
|
+
* skips the write if so. Skipping is always safe: the only cost is one
|
|
13
|
+
* extra cache miss on the next call.
|
|
14
|
+
*
|
|
15
|
+
* Scope: per-process, like the singleflight map. An invalidation issued by
|
|
16
|
+
* another instance against a shared handler (Redis/KV) during fn flight is
|
|
17
|
+
* not observable here — closing that window fully would require store-level
|
|
18
|
+
* versioning, which no CacheHandler backend offers.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
let epoch = 0;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Last-invalidated epoch per `key:<k>` / `tag:<t>` entry. Insertion order is
|
|
25
|
+
* epoch order (entries are re-inserted on update), so the oldest entry is
|
|
26
|
+
* always first — pruning evicts lowest epochs.
|
|
27
|
+
*/
|
|
28
|
+
const lastInvalidated = new Map<string, number>();
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Bound on tracked entries so high-cardinality tag invalidation (e.g.
|
|
32
|
+
* per-user tags) cannot grow this map without limit.
|
|
33
|
+
*/
|
|
34
|
+
const MAX_TRACKED_ENTRIES = 10_000;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Highest epoch evicted from the map. Any execution that started at or
|
|
38
|
+
* before this epoch conservatively counts as invalidated — history was
|
|
39
|
+
* truncated, so we can no longer prove it wasn't.
|
|
40
|
+
*/
|
|
41
|
+
let evictedEpochFloor = 0;
|
|
42
|
+
|
|
43
|
+
/** The current epoch. Capture before running fn(), pass to wasInvalidatedSince. */
|
|
44
|
+
export function currentInvalidationEpoch(): number {
|
|
45
|
+
return epoch;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Record an invalidation. Call BEFORE handler.invalidate() so an execution
|
|
50
|
+
* whose set-check races the invalidation errs toward skipping the write.
|
|
51
|
+
*/
|
|
52
|
+
export function recordInvalidation(opts: { key?: string; tag?: string }): void {
|
|
53
|
+
epoch++;
|
|
54
|
+
if (opts.key) track(`key:${opts.key}`);
|
|
55
|
+
if (opts.tag) track(`tag:${opts.tag}`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function track(entry: string): void {
|
|
59
|
+
lastInvalidated.delete(entry);
|
|
60
|
+
lastInvalidated.set(entry, epoch);
|
|
61
|
+
while (lastInvalidated.size > MAX_TRACKED_ENTRIES) {
|
|
62
|
+
const oldest = lastInvalidated.entries().next().value;
|
|
63
|
+
if (oldest === undefined) break;
|
|
64
|
+
evictedEpochFloor = Math.max(evictedEpochFloor, oldest[1]);
|
|
65
|
+
lastInvalidated.delete(oldest[0]);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Whether the key or any tag was invalidated after `startEpoch` (the epoch
|
|
71
|
+
* captured when fn started executing).
|
|
72
|
+
*/
|
|
73
|
+
export function wasInvalidatedSince(startEpoch: number, key: string, tags: string[]): boolean {
|
|
74
|
+
return lastInvalidationEpochFor(key, tags) > startEpoch;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* The highest epoch at which the key or any of the tags was invalidated
|
|
79
|
+
* (0 if never). Used to scope the singleflight key: callers arriving after
|
|
80
|
+
* an invalidation must not coalesce onto a flight that started before it —
|
|
81
|
+
* they would receive the pre-invalidation result the invalidation was
|
|
82
|
+
* issued to discard.
|
|
83
|
+
*/
|
|
84
|
+
export function lastInvalidationEpochFor(key: string, tags: string[]): number {
|
|
85
|
+
let last = evictedEpochFloor;
|
|
86
|
+
const keyEpoch = lastInvalidated.get(`key:${key}`);
|
|
87
|
+
if (keyEpoch !== undefined && keyEpoch > last) last = keyEpoch;
|
|
88
|
+
for (const tag of tags) {
|
|
89
|
+
const tagEpoch = lastInvalidated.get(`tag:${tag}`);
|
|
90
|
+
if (tagEpoch !== undefined && tagEpoch > last) last = tagEpoch;
|
|
91
|
+
}
|
|
92
|
+
return last;
|
|
93
|
+
}
|
|
@@ -1,16 +1,92 @@
|
|
|
1
1
|
import type { CacheHandler } from './index';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Minimal Redis client
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Minimal Redis client contract for `RedisCacheHandler`.
|
|
5
|
+
*
|
|
6
|
+
* This is deliberately NOT the native shape of any client library. ioredis,
|
|
7
|
+
* node-redis v4, and @upstash/redis all disagree on TTL argument shapes
|
|
8
|
+
* (positional `'EX'` vs `{ EX }` vs `{ ex }`), method casing (`sadd` vs
|
|
9
|
+
* `sAdd`), and array handling in `del` — a contract that pattern-matches one
|
|
10
|
+
* client lets another silently drop the expiry (TIM-1030: node-redis ignored
|
|
11
|
+
* the positional `'EX'` and wrote keys with no TTL). Instead, TTL semantics
|
|
12
|
+
* are explicit in the signature and you adapt your client with a thin
|
|
13
|
+
* wrapper, so a mismatch is a type error rather than silent unbounded
|
|
14
|
+
* keyspace growth.
|
|
15
|
+
*
|
|
16
|
+
* @example ioredis
|
|
17
|
+
* ```ts
|
|
18
|
+
* import Redis from 'ioredis';
|
|
19
|
+
* const redis = new Redis(process.env.REDIS_URL);
|
|
20
|
+
* const client: RedisClient = {
|
|
21
|
+
* get: (k) => redis.get(k),
|
|
22
|
+
* set: (k, v, ttl) => redis.set(k, v, 'EX', ttl),
|
|
23
|
+
* expire: (k, s) => redis.expire(k, s),
|
|
24
|
+
* del: (k) => redis.del(k),
|
|
25
|
+
* sadd: (k, ...m) => redis.sadd(k, ...m),
|
|
26
|
+
* srem: (k, ...m) => redis.srem(k, ...m),
|
|
27
|
+
* smembers: (k) => redis.smembers(k),
|
|
28
|
+
* ttl: (k) => redis.ttl(k),
|
|
29
|
+
* };
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* @example node-redis v4
|
|
33
|
+
* ```ts
|
|
34
|
+
* import { createClient } from 'redis';
|
|
35
|
+
* const redis = createClient({ url: process.env.REDIS_URL });
|
|
36
|
+
* await redis.connect();
|
|
37
|
+
* const client: RedisClient = {
|
|
38
|
+
* get: (k) => redis.get(k),
|
|
39
|
+
* set: (k, v, ttl) => redis.set(k, v, { EX: ttl }),
|
|
40
|
+
* expire: (k, s) => redis.expire(k, s),
|
|
41
|
+
* del: (k) => redis.del(k),
|
|
42
|
+
* sadd: (k, ...m) => redis.sAdd(k, m),
|
|
43
|
+
* srem: (k, ...m) => redis.sRem(k, m),
|
|
44
|
+
* smembers: (k) => redis.sMembers(k),
|
|
45
|
+
* ttl: (k) => redis.ttl(k),
|
|
46
|
+
* };
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* @example @upstash/redis
|
|
50
|
+
* ```ts
|
|
51
|
+
* import { Redis } from '@upstash/redis';
|
|
52
|
+
* // automaticDeserialization must be off: the handler stores JSON strings
|
|
53
|
+
* // and parses them itself — auto-parsing would hand back objects.
|
|
54
|
+
* const redis = new Redis({ url, token, automaticDeserialization: false });
|
|
55
|
+
* const client: RedisClient = {
|
|
56
|
+
* get: (k) => redis.get(k),
|
|
57
|
+
* set: (k, v, ttl) => redis.set(k, v, { ex: ttl }),
|
|
58
|
+
* expire: (k, s) => redis.expire(k, s),
|
|
59
|
+
* del: (k) => redis.del(k),
|
|
60
|
+
* sadd: (k, ...m) => redis.sadd(k, m[0], ...m.slice(1)),
|
|
61
|
+
* srem: (k, ...m) => redis.srem(k, m[0], ...m.slice(1)),
|
|
62
|
+
* smembers: (k) => redis.smembers(k),
|
|
63
|
+
* ttl: (k) => redis.ttl(k),
|
|
64
|
+
* };
|
|
65
|
+
* ```
|
|
7
66
|
*/
|
|
8
67
|
export interface RedisClient {
|
|
68
|
+
/** `GET key` — the stored string, or null when absent. */
|
|
9
69
|
get(key: string): Promise<string | null>;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
70
|
+
/**
|
|
71
|
+
* `SET key value EX ttlSeconds` — store with an expiry. The TTL is a
|
|
72
|
+
* required positional argument so no adapter can forget it.
|
|
73
|
+
*/
|
|
74
|
+
set(key: string, value: string, ttlSeconds: number): Promise<unknown>;
|
|
75
|
+
/** `EXPIRE key seconds` — set/refresh a key's TTL (used for tag sets). */
|
|
76
|
+
expire(key: string, seconds: number): Promise<unknown>;
|
|
77
|
+
/** `DEL key` — delete a single key. Multi-key deletes loop per key. */
|
|
78
|
+
del(key: string): Promise<unknown>;
|
|
79
|
+
/** `SADD key member [member ...]` — add members to a set. */
|
|
80
|
+
sadd(key: string, ...members: string[]): Promise<unknown>;
|
|
81
|
+
/** `SREM key member [member ...]` — remove members from a set. */
|
|
82
|
+
srem(key: string, ...members: string[]): Promise<unknown>;
|
|
83
|
+
/** `SMEMBERS key` — all members of a set. */
|
|
13
84
|
smembers(key: string): Promise<string[]>;
|
|
85
|
+
/**
|
|
86
|
+
* `TTL key` — remaining time-to-live in seconds. Returns -2 if the key does
|
|
87
|
+
* not exist, -1 if the key exists but has no expiry.
|
|
88
|
+
*/
|
|
89
|
+
ttl(key: string): Promise<number>;
|
|
14
90
|
}
|
|
15
91
|
|
|
16
92
|
const KEY_PREFIX = 'timber:cache:';
|
|
@@ -23,8 +99,9 @@ const TAG_PREFIX = 'timber:tag:';
|
|
|
23
99
|
* invalidations. Tag-based invalidation uses Redis Sets to track which keys
|
|
24
100
|
* belong to which tags.
|
|
25
101
|
*
|
|
26
|
-
* Bring your own Redis client
|
|
27
|
-
* interface
|
|
102
|
+
* Bring your own Redis client wrapped to the {@link RedisClient} contract —
|
|
103
|
+
* see the adapter examples on the interface for ioredis, node-redis v4, and
|
|
104
|
+
* @upstash/redis.
|
|
28
105
|
*/
|
|
29
106
|
export class RedisCacheHandler implements CacheHandler {
|
|
30
107
|
private client: RedisClient;
|
|
@@ -55,23 +132,41 @@ export class RedisCacheHandler implements CacheHandler {
|
|
|
55
132
|
async set(key: string, value: unknown, opts: { ttl: number; tags: string[] }): Promise<void> {
|
|
56
133
|
const ck = this.cacheKey(key);
|
|
57
134
|
const expiresAt = Date.now() + opts.ttl * 1000;
|
|
58
|
-
const payload = JSON.stringify({ value, expiresAt });
|
|
135
|
+
const payload = JSON.stringify({ value, expiresAt, tags: opts.tags });
|
|
59
136
|
|
|
60
137
|
// Redis TTL with generous margin beyond the logical TTL to allow SWR reads
|
|
61
138
|
// on stale entries. The logical staleness is determined by expiresAt.
|
|
62
139
|
// We use 2x TTL + 60s as the Redis expiry so stale entries remain
|
|
63
140
|
// available for SWR background refetches.
|
|
64
141
|
const redisTtlSeconds = Math.max(opts.ttl * 2 + 60, 120);
|
|
65
|
-
await this.client.set(ck, payload,
|
|
142
|
+
await this.client.set(ck, payload, redisTtlSeconds);
|
|
66
143
|
|
|
67
|
-
// Track key membership in each tag set
|
|
144
|
+
// Track key membership in each tag set, and expire the set so it doesn't
|
|
145
|
+
// outlive all its members. Only extend the TTL, never shorten — a short-TTL
|
|
146
|
+
// entry must not shrink a tag set that already contains long-TTL entries,
|
|
147
|
+
// otherwise invalidate({tag}) would miss the long-lived entries.
|
|
68
148
|
for (const tag of opts.tags) {
|
|
69
149
|
await this.client.sadd(this.tagKey(tag), key);
|
|
150
|
+
const currentTtl = await this.client.ttl(this.tagKey(tag));
|
|
151
|
+
// Only extend, never shorten. -2 = key doesn't exist (rare race after
|
|
152
|
+
// sadd), -1 = no expiry (new set or legacy — set initial TTL), positive
|
|
153
|
+
// but shorter = extend. A longer current TTL means a longer-lived entry
|
|
154
|
+
// set it first — don't shorten.
|
|
155
|
+
if (currentTtl < redisTtlSeconds) {
|
|
156
|
+
await this.client.expire(this.tagKey(tag), redisTtlSeconds);
|
|
157
|
+
}
|
|
70
158
|
}
|
|
71
159
|
}
|
|
72
160
|
|
|
73
161
|
async invalidate(opts: { key?: string; tag?: string }): Promise<void> {
|
|
74
162
|
if (opts.key) {
|
|
163
|
+
const raw = await this.client.get(this.cacheKey(opts.key));
|
|
164
|
+
if (raw !== null) {
|
|
165
|
+
const entry = JSON.parse(raw) as { tags?: string[] };
|
|
166
|
+
if (entry.tags) {
|
|
167
|
+
await Promise.all(entry.tags.map((tag) => this.client.srem(this.tagKey(tag), opts.key!)));
|
|
168
|
+
}
|
|
169
|
+
}
|
|
75
170
|
await this.client.del(this.cacheKey(opts.key));
|
|
76
171
|
}
|
|
77
172
|
|
|
@@ -79,10 +174,10 @@ export class RedisCacheHandler implements CacheHandler {
|
|
|
79
174
|
const tk = this.tagKey(opts.tag);
|
|
80
175
|
const keys = await this.client.smembers(tk);
|
|
81
176
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
177
|
+
// One del per key: the only multi-key shape every client accepts.
|
|
178
|
+
// ioredis takes del(...keys), node-redis takes del(key | key[]), and
|
|
179
|
+
// @upstash/redis takes del(...keys) but breaks on an array argument.
|
|
180
|
+
await Promise.all(keys.map((k) => this.client.del(this.cacheKey(k))));
|
|
86
181
|
|
|
87
182
|
// Clean up the tag set itself
|
|
88
183
|
await this.client.del(tk);
|
|
@@ -3,24 +3,82 @@
|
|
|
3
3
|
* execution. All callers receive the same result (or error).
|
|
4
4
|
*
|
|
5
5
|
* Per-process, in-memory. Each process coalesces independently.
|
|
6
|
+
*
|
|
7
|
+
* An optional `timeoutMs` prevents hung `fn()` calls from permanently
|
|
8
|
+
* blocking all future callers for that key. When set, `fn()` is raced
|
|
9
|
+
* against a timeout — if the timeout fires first, the promise rejects
|
|
10
|
+
* with `SingleflightTimeoutError`, `finally` cleans up the key, and
|
|
11
|
+
* subsequent callers can retry. See TIM-518.
|
|
6
12
|
*/
|
|
13
|
+
|
|
14
|
+
export interface SingleflightOptions {
|
|
15
|
+
/** Maximum time (ms) a coalesced call may run before being rejected. */
|
|
16
|
+
timeoutMs?: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
7
19
|
export interface Singleflight {
|
|
8
20
|
do<T>(key: string, fn: () => Promise<T>): Promise<T>;
|
|
9
21
|
}
|
|
10
22
|
|
|
11
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Error thrown when a singleflight call exceeds `timeoutMs`.
|
|
25
|
+
* Exported so callers can distinguish timeout from other errors.
|
|
26
|
+
*/
|
|
27
|
+
export class SingleflightTimeoutError extends Error {
|
|
28
|
+
constructor(key: string, timeoutMs: number) {
|
|
29
|
+
super(`Singleflight timeout: key "${key}" exceeded ${timeoutMs}ms`);
|
|
30
|
+
this.name = 'SingleflightTimeoutError';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function createSingleflight(opts?: SingleflightOptions): Singleflight {
|
|
12
35
|
const inflight = new Map<string, Promise<unknown>>();
|
|
36
|
+
const timeoutMs = opts?.timeoutMs;
|
|
13
37
|
|
|
14
38
|
return {
|
|
15
39
|
do<T>(key: string, fn: () => Promise<T>): Promise<T> {
|
|
16
40
|
const existing = inflight.get(key);
|
|
17
41
|
if (existing) return existing as Promise<T>;
|
|
18
42
|
|
|
19
|
-
|
|
43
|
+
let promise: Promise<T>;
|
|
44
|
+
|
|
45
|
+
if (timeoutMs != null && timeoutMs > 0) {
|
|
46
|
+
// Race fn() against a timeout to prevent hung calls from
|
|
47
|
+
// permanently blocking the key. See TIM-518.
|
|
48
|
+
promise = new Promise<T>((resolve, reject) => {
|
|
49
|
+
const timer = setTimeout(
|
|
50
|
+
() => reject(new SingleflightTimeoutError(key, timeoutMs)),
|
|
51
|
+
timeoutMs
|
|
52
|
+
);
|
|
53
|
+
// Wrap in try/catch so a synchronous throw from fn()
|
|
54
|
+
// (e.g. argument validation) still clears the timer.
|
|
55
|
+
// Without this, the timer leaks until expiry.
|
|
56
|
+
try {
|
|
57
|
+
fn().then(
|
|
58
|
+
(value) => {
|
|
59
|
+
clearTimeout(timer);
|
|
60
|
+
resolve(value);
|
|
61
|
+
},
|
|
62
|
+
(err) => {
|
|
63
|
+
clearTimeout(timer);
|
|
64
|
+
reject(err);
|
|
65
|
+
}
|
|
66
|
+
);
|
|
67
|
+
} catch (err) {
|
|
68
|
+
clearTimeout(timer);
|
|
69
|
+
reject(err);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
} else {
|
|
73
|
+
promise = fn();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const tracked = promise.finally(() => {
|
|
20
77
|
inflight.delete(key);
|
|
21
78
|
});
|
|
22
|
-
|
|
23
|
-
|
|
79
|
+
|
|
80
|
+
inflight.set(key, tracked);
|
|
81
|
+
return tracked as Promise<T>;
|
|
24
82
|
},
|
|
25
83
|
};
|
|
26
84
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight byte-size estimation for cache entries.
|
|
3
|
+
*
|
|
4
|
+
* Estimates the in-memory byte cost of a JavaScript value using
|
|
5
|
+
* JSON.stringify().length * 2 (UTF-16 char width). This is a rough
|
|
6
|
+
* approximation — it doesn't account for V8 object overhead, Map
|
|
7
|
+
* metadata, or non-serializable values — but it's fast and good
|
|
8
|
+
* enough for cache budget enforcement.
|
|
9
|
+
*
|
|
10
|
+
* Values that fail JSON serialization (circular references, BigInt,
|
|
11
|
+
* etc.) return 0, allowing the entry to be cached without counting
|
|
12
|
+
* toward the byte budget. This is a conservative choice: it's better
|
|
13
|
+
* to cache and undercount than to reject the entry.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Estimate the byte size of a value.
|
|
18
|
+
*
|
|
19
|
+
* Uses `JSON.stringify(value).length * 2` to approximate UTF-16
|
|
20
|
+
* in-memory size. Returns 0 if the value is not serializable.
|
|
21
|
+
*/
|
|
22
|
+
export function estimateByteSize(value: unknown): number {
|
|
23
|
+
try {
|
|
24
|
+
const json = JSON.stringify(value);
|
|
25
|
+
if (json === undefined) return 0;
|
|
26
|
+
// Each JS string character is 2 bytes (UTF-16)
|
|
27
|
+
return json.length * 2;
|
|
28
|
+
} catch (e) {
|
|
29
|
+
// Circular reference or non-serializable value
|
|
30
|
+
console.debug('[timber] sizeof estimation failed:', e instanceof Error ? e.message : e);
|
|
31
|
+
return 0;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -2,20 +2,83 @@
|
|
|
2
2
|
* Deterministic JSON serialization with sorted object keys.
|
|
3
3
|
* Used for cache key generation — ensures { a: 1, b: 2 } and { b: 2, a: 1 }
|
|
4
4
|
* produce the same string.
|
|
5
|
+
*
|
|
6
|
+
* Matches JSON.stringify semantics for toJSON: Date serializes to its ISO
|
|
7
|
+
* string, URL to its href, and class instances with a custom toJSON use it.
|
|
8
|
+
* Map and Set serialize their entries explicitly (insertion-order
|
|
9
|
+
* independent). Values that would serialize lossily — functions, symbols,
|
|
10
|
+
* and non-plain objects with no enumerable own state (RegExp, class
|
|
11
|
+
* instances holding data behind getters or internal slots) — throw instead:
|
|
12
|
+
* every such value would collapse to the same cache key, silently returning
|
|
13
|
+
* one argument's cached data for another (TIM-1020).
|
|
5
14
|
*/
|
|
6
15
|
export function stableStringify(value: unknown): string {
|
|
7
|
-
if (value === null || value === undefined) return
|
|
8
|
-
|
|
16
|
+
if (value === null || value === undefined) return String(value);
|
|
17
|
+
|
|
18
|
+
const type = typeof value;
|
|
19
|
+
if (type === 'function' || type === 'symbol') {
|
|
20
|
+
throw new TypeError(
|
|
21
|
+
`stableStringify: cannot serialize a ${type} into a stable cache key — ` +
|
|
22
|
+
'all such values would collide. Provide an explicit `key` option to cache().'
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
if (type !== 'object') return JSON.stringify(value);
|
|
26
|
+
|
|
9
27
|
if (Array.isArray(value)) {
|
|
10
28
|
return '[' + value.map((item) => stableStringify(item)).join(',') + ']';
|
|
11
29
|
}
|
|
12
30
|
|
|
31
|
+
// Honor toJSON like JSON.stringify does (Date → ISO string, URL → href,
|
|
32
|
+
// custom class serialization). JSON.stringify does not re-invoke toJSON
|
|
33
|
+
// on the value it returns, so a toJSON that returns `this` falls through
|
|
34
|
+
// to plain own-property serialization instead of recursing forever.
|
|
35
|
+
const withToJSON = value as { toJSON?: () => unknown };
|
|
36
|
+
if (typeof withToJSON.toJSON === 'function') {
|
|
37
|
+
const json = withToJSON.toJSON();
|
|
38
|
+
if (json !== value) return stableStringify(json);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Map/Set have no enumerable own properties — serialize entries explicitly.
|
|
42
|
+
// Entries are sorted after serialization so insertion order doesn't change
|
|
43
|
+
// the key. The Map(/Set( prefixes can't collide with object ('{'), array
|
|
44
|
+
// ('['), or string ('"') output.
|
|
45
|
+
if (value instanceof Map) {
|
|
46
|
+
const entries = [...value.entries()].map(
|
|
47
|
+
([k, v]) => stableStringify(k) + '=>' + stableStringify(v)
|
|
48
|
+
);
|
|
49
|
+
return 'Map(' + entries.sort().join(',') + ')';
|
|
50
|
+
}
|
|
51
|
+
if (value instanceof Set) {
|
|
52
|
+
const members = [...value].map((member) => stableStringify(member));
|
|
53
|
+
return 'Set(' + members.sort().join(',') + ')';
|
|
54
|
+
}
|
|
55
|
+
|
|
13
56
|
const obj = value as Record<string, unknown>;
|
|
14
57
|
const keys = Object.keys(obj).sort();
|
|
15
58
|
const pairs: string[] = [];
|
|
16
59
|
for (const key of keys) {
|
|
17
60
|
if (obj[key] === undefined) continue;
|
|
61
|
+
// A callable own toJSON only reaches this loop via the returns-`this`
|
|
62
|
+
// fall-through above. It's the serialization protocol, not data —
|
|
63
|
+
// JSON.stringify omits it too.
|
|
64
|
+
if (key === 'toJSON' && typeof obj[key] === 'function') continue;
|
|
18
65
|
pairs.push(JSON.stringify(key) + ':' + stableStringify(obj[key]));
|
|
19
66
|
}
|
|
67
|
+
|
|
68
|
+
// A non-plain object that serializes to '{}' carries its state behind
|
|
69
|
+
// getters or internal slots (RegExp, sessions, ORM entities). Serializing
|
|
70
|
+
// it would give every instance the same cache key.
|
|
71
|
+
if (pairs.length === 0) {
|
|
72
|
+
const proto = Object.getPrototypeOf(value);
|
|
73
|
+
if (proto !== Object.prototype && proto !== null) {
|
|
74
|
+
const name = (value as object).constructor?.name || 'Object';
|
|
75
|
+
throw new TypeError(
|
|
76
|
+
`stableStringify: ${name} instance has no serializable own state — ` +
|
|
77
|
+
'all instances would share one cache key. Provide an explicit `key` ' +
|
|
78
|
+
'option to cache(), or add a toJSON() method.'
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
20
83
|
return '{' + pairs.join(',') + '}';
|
|
21
84
|
}
|