@timber-js/app 0.2.0-alpha.12 → 0.2.0-alpha.121
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks/actions-Dy8vOjFt.js +1101 -0
- package/dist/_chunks/actions-Dy8vOjFt.js.map +1 -0
- package/dist/_chunks/build-output-helper-B1n0sUqj.js +61 -0
- package/dist/_chunks/build-output-helper-B1n0sUqj.js.map +1 -0
- package/dist/_chunks/cli-schema-sync-ByZPGGmS.js +724 -0
- package/dist/_chunks/cli-schema-sync-ByZPGGmS.js.map +1 -0
- package/dist/_chunks/cli-schema-sync-DHQLjFu3.js +2 -0
- package/dist/_chunks/codec-registry-G9hD5LOq.js +21 -0
- package/dist/_chunks/codec-registry-G9hD5LOq.js.map +1 -0
- package/dist/_chunks/define-CPVQaWbx.js +124 -0
- package/dist/_chunks/define-CPVQaWbx.js.map +1 -0
- package/dist/_chunks/define-jeHDXZGq.js +195 -0
- package/dist/_chunks/define-jeHDXZGq.js.map +1 -0
- package/dist/_chunks/format-BjN9HLu9.js +14 -0
- package/dist/_chunks/format-BjN9HLu9.js.map +1 -0
- package/dist/_chunks/handler-store-CcwNX-gk.js +54 -0
- package/dist/_chunks/handler-store-CcwNX-gk.js.map +1 -0
- package/dist/_chunks/logger-DDmK5skc.js +291 -0
- package/dist/_chunks/logger-DDmK5skc.js.map +1 -0
- package/dist/_chunks/merge-search-params-az6ZiBeU.js +41 -0
- package/dist/_chunks/merge-search-params-az6ZiBeU.js.map +1 -0
- package/dist/_chunks/navigation-root-DoRTeBm5.js +96 -0
- package/dist/_chunks/navigation-root-DoRTeBm5.js.map +1 -0
- package/dist/_chunks/registry-BI9cgCt7.js +20 -0
- package/dist/_chunks/registry-BI9cgCt7.js.map +1 -0
- package/dist/_chunks/resolve-schema-Bf8eC6q6.js +73 -0
- package/dist/_chunks/resolve-schema-Bf8eC6q6.js.map +1 -0
- package/dist/_chunks/router-ref-CpvjBqdu.js +28 -0
- package/dist/_chunks/router-ref-CpvjBqdu.js.map +1 -0
- package/dist/_chunks/schema-bridge-o0SwFtXW.js +86 -0
- package/dist/_chunks/schema-bridge-o0SwFtXW.js.map +1 -0
- package/dist/_chunks/segment-classify-CnfLLvir.js +137 -0
- package/dist/_chunks/segment-classify-CnfLLvir.js.map +1 -0
- package/dist/_chunks/segment-context-EsfQpS--.js +34 -0
- package/dist/_chunks/segment-context-EsfQpS--.js.map +1 -0
- package/dist/_chunks/{ssr-data-MjmprTmO.js → ssr-data-m9-cNEIw.js} +1 -1
- package/dist/_chunks/ssr-data-m9-cNEIw.js.map +1 -0
- package/dist/_chunks/stale-reload-BN2kcE06.js +64 -0
- package/dist/_chunks/stale-reload-BN2kcE06.js.map +1 -0
- package/dist/_chunks/tracing-DvKLzCFa.js +329 -0
- package/dist/_chunks/tracing-DvKLzCFa.js.map +1 -0
- package/dist/_chunks/{use-query-states-D5KaffOK.js → use-query-states-C9G6LP0F.js} +7 -20
- package/dist/_chunks/use-query-states-C9G6LP0F.js.map +1 -0
- package/dist/_chunks/use-segment-params-CtIAjqK0.js +185 -0
- package/dist/_chunks/use-segment-params-CtIAjqK0.js.map +1 -0
- package/dist/_chunks/validation-BMU5MPzP.js +84 -0
- package/dist/_chunks/validation-BMU5MPzP.js.map +1 -0
- package/dist/_chunks/walkers-DNp9tHyV.js +719 -0
- package/dist/_chunks/walkers-DNp9tHyV.js.map +1 -0
- package/dist/_chunks/{format-DviM89f0.js → warnings-B30wpfaS.js} +6 -45
- package/dist/_chunks/warnings-B30wpfaS.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 +95 -0
- package/dist/adapters/cloudflare-kv-cache.js.map +1 -0
- package/dist/adapters/cloudflare.d.ts +148 -12
- package/dist/adapters/cloudflare.d.ts.map +1 -1
- package/dist/adapters/cloudflare.js +142 -38
- package/dist/adapters/cloudflare.js.map +1 -1
- package/dist/adapters/compress-module.d.ts.map +1 -1
- package/dist/adapters/nitro.d.ts +17 -1
- package/dist/adapters/nitro.d.ts.map +1 -1
- package/dist/adapters/nitro.js +143 -45
- 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 +23 -7
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +151 -81
- package/dist/cache/index.js.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/timber-cache.d.ts +1 -1
- package/dist/cache/timber-cache.d.ts.map +1 -1
- package/dist/cli-schema-sync.d.ts +37 -0
- package/dist/cli-schema-sync.d.ts.map +1 -0
- package/dist/cli.d.ts +14 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +42 -6
- 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 +30 -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 +23 -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 +19 -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 +29 -6
- package/dist/client/error-boundary.js.map +1 -1
- package/dist/client/error-reconstituter.d.ts +54 -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 +19 -4
- package/dist/client/history.d.ts.map +1 -1
- package/dist/client/index.d.ts +9 -24
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +172 -1100
- 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 +964 -0
- package/dist/client/internal.js.map +1 -0
- package/dist/client/link-pending-store.d.ts +63 -0
- package/dist/client/link-pending-store.d.ts.map +1 -0
- package/dist/client/link.d.ts +62 -55
- package/dist/client/link.d.ts.map +1 -1
- package/dist/client/nav-link-store.d.ts +36 -0
- package/dist/client/nav-link-store.d.ts.map +1 -0
- 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 +115 -0
- package/dist/client/navigation-api.d.ts.map +1 -0
- package/dist/client/navigation-context.d.ts +13 -2
- package/dist/client/navigation-context.d.ts.map +1 -1
- package/dist/client/{transition-root.d.ts → navigation-root.d.ts} +42 -8
- package/dist/client/navigation-root.d.ts.map +1 -0
- 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 +70 -4
- package/dist/client/router.d.ts.map +1 -1
- package/dist/client/rsc-fetch.d.ts +38 -3
- package/dist/client/rsc-fetch.d.ts.map +1 -1
- package/dist/client/segment-cache.d.ts +1 -1
- package/dist/client/segment-cache.d.ts.map +1 -1
- package/dist/client/segment-outlet.d.ts +63 -0
- package/dist/client/segment-outlet.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/stale-reload.d.ts +15 -0
- package/dist/client/stale-reload.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-navigation-pending.d.ts → use-pending-navigation.d.ts} +4 -4
- 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-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 +251 -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 +46 -0
- package/dist/cookies/validation.d.ts.map +1 -0
- package/dist/dev-tools/404-page.d.ts +46 -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/error-page.d.ts +58 -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/index.d.ts +31 -0
- package/dist/dev-tools/index.d.ts.map +1 -0
- package/dist/{server/dev-span-processor.d.ts → dev-tools/instrumentation.d.ts} +26 -6
- 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/{server/dev-warnings.d.ts → dev-tools/warnings.d.ts} +2 -22
- package/dist/dev-tools/warnings.d.ts.map +1 -0
- package/dist/fonts/ast.d.ts +98 -6
- package/dist/fonts/ast.d.ts.map +1 -1
- package/dist/fonts/bundle.d.ts +48 -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/local.d.ts +1 -1
- package/dist/fonts/pipeline.d.ts +167 -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 +45 -1
- package/dist/fonts/types.d.ts.map +1 -1
- package/dist/fonts/virtual-modules.d.ts +94 -0
- package/dist/fonts/virtual-modules.d.ts.map +1 -0
- package/dist/index.d.ts +46 -190
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4807 -12729
- 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 +107 -0
- package/dist/plugin-context.d.ts.map +1 -0
- package/dist/plugins/adapter-build.d.ts +1 -1
- package/dist/plugins/adapter-build.d.ts.map +1 -1
- package/dist/plugins/build-manifest.d.ts +2 -2
- 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/client-chunks.d.ts +32 -0
- package/dist/plugins/client-chunks.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 +1 -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 +17 -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 +6 -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 +63 -0
- package/dist/routing/codegen-shared.d.ts.map +1 -0
- package/dist/routing/codegen-types.d.ts +60 -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/index.d.ts +7 -1
- package/dist/routing/index.d.ts.map +1 -1
- package/dist/routing/index.js +4 -2
- package/dist/routing/link-codegen.d.ts +90 -0
- package/dist/routing/link-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 +76 -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 +34 -441
- 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 +95 -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 +3 -6
- package/dist/server/actions.d.ts.map +1 -1
- package/dist/server/als-registry.d.ts +53 -5
- 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/build-manifest.d.ts +2 -2
- package/dist/server/build-manifest.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/debug.d.ts +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 +90 -0
- package/dist/server/deny-boundary.d.ts.map +1 -0
- 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 -5
- 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/flush.d.ts.map +1 -1
- 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 +213 -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 +155 -2905
- package/dist/server/index.js.map +1 -1
- package/dist/server/internal.d.ts +48 -0
- package/dist/server/internal.d.ts.map +1 -0
- package/dist/server/internal.js +2947 -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/middleware-runner.d.ts +36 -4
- package/dist/server/middleware-runner.d.ts.map +1 -1
- package/dist/server/node-stream-transforms.d.ts +112 -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 +52 -0
- package/dist/server/pipeline-phases.d.ts.map +1 -0
- package/dist/server/pipeline.d.ts +118 -23
- 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 +69 -18
- 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/request-context.d.ts +62 -107
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/route-element-builder.d.ts +27 -1
- 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 +21 -34
- 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 +2 -2
- 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 +49 -6
- 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/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 +1 -1
- package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-renderer.d.ts +19 -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 +1 -1
- package/dist/server/slot-resolver.d.ts.map +1 -1
- package/dist/server/ssr-entry.d.ts +30 -0
- package/dist/server/ssr-entry.d.ts.map +1 -1
- package/dist/server/ssr-render.d.ts +39 -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.map +1 -1
- package/dist/server/status-code-resolver.d.ts +16 -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 +5 -5
- 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 +41 -0
- package/dist/server/tree-match.d.ts.map +1 -0
- package/dist/server/types.d.ts +49 -4
- 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/version-skew.d.ts +61 -0
- package/dist/server/version-skew.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/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 +2 -1
- package/dist/shims/headers.d.ts.map +1 -1
- package/dist/shims/navigation-client.d.ts +3 -1
- 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 +62 -21
- package/src/adapters/build-output-helper.ts +77 -0
- package/src/adapters/cloudflare-dev.ts +177 -0
- package/src/adapters/cloudflare-kv-cache.ts +142 -0
- package/src/adapters/cloudflare.ts +350 -76
- package/src/adapters/compress-module.ts +24 -4
- package/src/adapters/nitro.ts +142 -59
- package/src/adapters/shared.ts +40 -0
- package/src/adapters/wrangler.d.ts +7 -0
- package/src/cache/cache-api.ts +38 -0
- package/src/cache/handler-store.ts +68 -0
- package/src/cache/index.ts +81 -18
- package/src/cache/singleflight.ts +62 -4
- package/src/cache/sizeof.ts +33 -0
- package/src/cache/timber-cache.ts +25 -20
- package/src/cli-schema-sync.ts +207 -0
- package/src/cli.ts +65 -8
- package/src/client/browser-dev.ts +153 -1
- package/src/client/browser-entry/action-dispatch.ts +126 -0
- package/src/client/browser-entry/hmr.ts +81 -0
- package/src/client/browser-entry/hydrate.ts +145 -0
- package/src/client/browser-entry/index.ts +149 -0
- package/src/client/browser-entry/post-hydration.ts +119 -0
- package/src/client/browser-entry/router-init.ts +193 -0
- package/src/client/browser-entry/rsc-stream.ts +157 -0
- package/src/client/browser-entry/scroll.ts +27 -0
- package/src/client/error-boundary.tsx +99 -22
- package/src/client/error-reconstituter.tsx +65 -0
- package/src/client/form.tsx +31 -32
- package/src/client/history.ts +26 -4
- package/src/client/index.ts +69 -44
- package/src/client/internal.ts +58 -0
- package/src/client/link-pending-store.ts +111 -0
- package/src/client/link.tsx +366 -113
- package/src/client/nav-link-store.ts +47 -0
- package/src/client/navigation-api-types.ts +112 -0
- package/src/client/navigation-api.ts +332 -0
- package/src/client/navigation-context.ts +31 -6
- package/src/client/navigation-root.tsx +342 -0
- package/src/client/nuqs-adapter.tsx +16 -3
- package/src/client/router-ref.ts +1 -1
- package/src/client/router.ts +300 -73
- package/src/client/rsc-fetch.ts +112 -8
- package/src/client/segment-cache.ts +1 -1
- package/src/client/segment-outlet.tsx +86 -0
- package/src/client/ssr-data.ts +13 -5
- package/src/client/stale-reload.ts +72 -3
- package/src/client/state.ts +2 -2
- package/src/client/top-loader.tsx +18 -6
- package/src/client/use-cookie.ts +31 -2
- package/src/client/use-link-status.ts +7 -7
- package/src/client/{use-navigation-pending.ts → use-pending-navigation.ts} +6 -6
- package/src/client/use-query-states.ts +9 -3
- package/src/client/use-router.ts +1 -1
- package/src/client/{use-params.ts → use-segment-params.ts} +8 -6
- package/src/codec.ts +147 -0
- package/src/config-types.ts +292 -0
- package/src/config-validation.ts +303 -0
- package/src/content/index.ts +5 -13
- package/src/cookies/define-cookie.ts +233 -53
- package/src/cookies/index.ts +12 -1
- package/src/cookies/json-cookie.ts +105 -0
- package/src/cookies/validation.ts +134 -0
- package/src/dev-tools/404-page.ts +387 -0
- package/src/dev-tools/browser-logs.ts +291 -0
- package/src/dev-tools/error-page.ts +506 -0
- package/src/dev-tools/holding-server.ts +187 -0
- package/src/dev-tools/index.ts +90 -0
- package/src/dev-tools/instrumentation.ts +176 -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/{server/dev-warnings.ts → dev-tools/warnings.ts} +5 -50
- package/src/fonts/ast.ts +525 -16
- package/src/fonts/bundle.ts +142 -0
- package/src/fonts/dev-middleware.ts +74 -0
- package/src/fonts/local.ts +1 -1
- package/src/fonts/pipeline.ts +314 -0
- package/src/fonts/transform.ts +317 -0
- package/src/fonts/types.ts +50 -1
- package/src/fonts/virtual-modules.ts +233 -0
- package/src/index.ts +409 -357
- package/src/params/codec-registry.ts +34 -0
- package/src/params/define-schema.ts +114 -0
- package/src/params/index.ts +17 -0
- package/src/params/resolve-schema.ts +101 -0
- package/src/plugin-context.ts +240 -0
- package/src/plugins/adapter-build.ts +12 -4
- package/src/plugins/build-manifest.ts +13 -2
- package/src/plugins/build-report.ts +16 -25
- package/src/plugins/client-chunks.ts +65 -0
- package/src/plugins/content.ts +1 -1
- package/src/plugins/dev-server.ts +175 -35
- package/src/plugins/entries.ts +111 -9
- package/src/plugins/fonts.ts +157 -654
- package/src/plugins/mdx.ts +47 -10
- package/src/plugins/routing.ts +371 -45
- package/src/plugins/server-bundle.ts +32 -1
- package/src/plugins/shims.ts +136 -35
- package/src/plugins/static-build.ts +15 -89
- package/src/routing/codegen-shared.ts +109 -0
- package/src/routing/codegen-types.ts +61 -0
- package/src/routing/codegen.ts +316 -177
- package/src/routing/convention-lint.ts +357 -0
- package/src/routing/index.ts +10 -1
- package/src/routing/interception.ts +1 -1
- package/src/routing/link-codegen.ts +308 -0
- package/src/routing/scanner.ts +165 -110
- 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/{search-params/codecs.ts → schema-bridge.ts} +57 -20
- package/src/search-params/define.ts +538 -0
- package/src/search-params/index.ts +14 -20
- package/src/search-params/registry.ts +2 -2
- package/src/search-params/wrappers.ts +92 -0
- package/src/segment-params/define.ts +336 -0
- package/src/segment-params/index.ts +9 -0
- package/src/server/access-gate.tsx +76 -34
- package/src/server/action-client.ts +88 -15
- package/src/server/action-encryption.ts +144 -0
- package/src/server/action-handler.ts +112 -14
- package/src/server/actions.ts +10 -9
- package/src/server/als-registry.ts +55 -7
- package/src/server/asset-headers.ts +8 -34
- package/src/server/build-manifest.ts +10 -4
- package/src/server/coalesce-tick.ts +75 -0
- package/src/server/compress.ts +25 -7
- package/src/server/cookie-context.ts +468 -0
- package/src/server/cookie-parsing.ts +135 -0
- package/src/server/debug.ts +1 -1
- package/src/server/default-logger.ts +99 -0
- package/src/server/deny-boundary.ts +218 -0
- package/src/server/deny-renderer.ts +31 -50
- package/src/server/dev-source-map.ts +31 -0
- package/src/server/early-hints-sender.ts +3 -2
- package/src/server/early-hints.ts +36 -15
- package/src/server/error-boundary-wrapper.ts +74 -22
- package/src/server/fallback-error.ts +74 -102
- package/src/server/flight-injection-state.ts +113 -0
- package/src/server/flight-scripts.ts +62 -0
- package/src/server/flush.ts +2 -1
- package/src/server/form-data.ts +76 -0
- package/src/server/html-injector-core.ts +417 -0
- package/src/server/html-injectors.ts +235 -223
- package/src/server/index.ts +29 -183
- package/src/server/internal.ts +176 -0
- package/src/server/logger.ts +67 -36
- package/src/server/middleware-runner.ts +75 -4
- package/src/server/node-stream-transforms.ts +361 -0
- package/src/server/param-coercion.ts +206 -0
- package/src/server/pipeline-helpers.ts +204 -0
- package/src/server/pipeline-interception.ts +17 -16
- package/src/server/pipeline-metadata.ts +13 -0
- package/src/server/pipeline-outcome.ts +176 -0
- package/src/server/pipeline-phases.ts +460 -0
- package/src/server/pipeline.ts +154 -394
- package/src/server/port-resolution.ts +215 -0
- package/src/server/primitives.ts +111 -28
- package/src/server/render-timeout.ts +108 -0
- package/src/server/request-context.ts +168 -333
- package/src/server/route-element-builder.ts +309 -195
- package/src/server/route-handler.ts +24 -4
- package/src/server/route-matcher.ts +50 -231
- package/src/server/rsc-entry/action-middleware-runner.ts +167 -0
- package/src/server/rsc-entry/api-handler.ts +16 -17
- package/src/server/rsc-entry/error-renderer.ts +305 -89
- package/src/server/rsc-entry/helpers.ts +137 -12
- package/src/server/rsc-entry/index.ts +316 -352
- package/src/server/rsc-entry/render-route.ts +307 -0
- package/src/server/rsc-entry/rsc-payload.ts +65 -18
- package/src/server/rsc-entry/rsc-stream.ts +85 -13
- package/src/server/rsc-entry/ssr-bridge.ts +14 -5
- package/src/server/rsc-entry/ssr-renderer.ts +187 -38
- 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 +126 -0
- package/src/server/slot-resolver.ts +228 -246
- package/src/server/ssr-entry.ts +229 -32
- package/src/server/ssr-render.ts +289 -67
- package/src/server/ssr-wrappers.tsx +139 -0
- package/src/server/state-tree-diff.ts +4 -1
- package/src/server/status-code-resolver.ts +112 -128
- package/src/server/stream-utils.ts +213 -0
- package/src/server/tracing.ts +21 -10
- package/src/server/tree-builder.ts +202 -90
- package/src/server/tree-match.ts +198 -0
- package/src/server/types.ts +55 -6
- package/src/server/utils/escape-html.ts +20 -0
- package/src/server/version-skew.ts +104 -0
- package/src/shared/merge-search-params.ts +55 -0
- package/src/shims/font-google.ts +1 -1
- package/src/shims/font-local.ts +34 -0
- package/src/shims/headers.ts +5 -1
- package/src/shims/navigation-client.ts +4 -3
- package/src/shims/navigation.ts +14 -7
- package/src/utils/state-machine.ts +111 -0
- package/LICENSE +0 -8
- package/dist/_chunks/als-registry-B7DbZ2hS.js +0 -41
- package/dist/_chunks/als-registry-B7DbZ2hS.js.map +0 -1
- package/dist/_chunks/debug-gwlJkDuf.js +0 -108
- package/dist/_chunks/debug-gwlJkDuf.js.map +0 -1
- package/dist/_chunks/format-DviM89f0.js.map +0 -1
- package/dist/_chunks/interception-BOoWmLUA.js +0 -676
- package/dist/_chunks/interception-BOoWmLUA.js.map +0 -1
- package/dist/_chunks/request-context-DIkVh_jG.js +0 -330
- package/dist/_chunks/request-context-DIkVh_jG.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/transition-root.d.ts.map +0 -1
- 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.map +0 -1
- package/dist/server/dev-warnings.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/server/response-cache.d.ts +0 -54
- package/dist/server/response-cache.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/transition-root.tsx +0 -166
- 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/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/manifest-status-resolver.ts +0 -215
- package/src/server/prerender.ts +0 -139
- package/src/server/response-cache.ts +0 -410
- package/src/utils/directive-parser.ts +0 -529
- /package/src/{server/dev-logger.ts → dev-tools/logger.ts} +0 -0
package/src/client/rsc-fetch.ts
CHANGED
|
@@ -23,7 +23,7 @@ export interface FetchResult {
|
|
|
23
23
|
headElements: HeadElement[] | null;
|
|
24
24
|
/** Segment metadata from X-Timber-Segments header for populating the segment cache. */
|
|
25
25
|
segmentInfo: SegmentInfo[] | null;
|
|
26
|
-
/** Route params from X-Timber-Params header for populating
|
|
26
|
+
/** Route params from X-Timber-Params header for populating useSegmentParams(). */
|
|
27
27
|
params: Record<string, string | string[]> | null;
|
|
28
28
|
/** Segment paths that were skipped by the server (for client-side merging). */
|
|
29
29
|
skippedSegments: string[] | null;
|
|
@@ -58,6 +58,43 @@ function appendRscParam(url: string): string {
|
|
|
58
58
|
return `${url}${separator}_rsc=${generateCacheBustId()}`;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
// ─── Deployment ID ───────────────────────────────────────────────
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* The client's deployment ID, set at bootstrap from the runtime config.
|
|
65
|
+
* Sent with every RSC/action request for version skew detection.
|
|
66
|
+
* Null in dev mode. See TIM-446.
|
|
67
|
+
*/
|
|
68
|
+
let clientDeploymentId: string | null = null;
|
|
69
|
+
|
|
70
|
+
/** Set the client deployment ID. Called once at bootstrap. */
|
|
71
|
+
export function setClientDeploymentId(id: string | null): void {
|
|
72
|
+
clientDeploymentId = id;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Get the client deployment ID. */
|
|
76
|
+
export function getClientDeploymentId(): string | null {
|
|
77
|
+
return clientDeploymentId;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// ─── Reload Signal ───────────────────────────────────────────────
|
|
81
|
+
|
|
82
|
+
/** Header name used by the server to signal a version skew reload. */
|
|
83
|
+
export const RELOAD_HEADER = 'X-Timber-Reload';
|
|
84
|
+
|
|
85
|
+
/** Header name for the client's deployment ID. */
|
|
86
|
+
export const DEPLOYMENT_ID_HEADER = 'X-Timber-Deployment-Id';
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Check if a response signals a version skew reload.
|
|
90
|
+
* Triggers a full page reload if the server indicates the client is stale.
|
|
91
|
+
*/
|
|
92
|
+
export function checkReloadSignal(response: Response): boolean {
|
|
93
|
+
return response.headers.get(RELOAD_HEADER) === '1';
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// ─── Header Builder ──────────────────────────────────────────────
|
|
97
|
+
|
|
61
98
|
export function buildRscHeaders(
|
|
62
99
|
stateTree: { segments: string[] } | undefined,
|
|
63
100
|
currentUrl?: string
|
|
@@ -75,11 +112,29 @@ export function buildRscHeaders(
|
|
|
75
112
|
if (currentUrl) {
|
|
76
113
|
headers['X-Timber-URL'] = currentUrl;
|
|
77
114
|
}
|
|
115
|
+
// Send deployment ID for version skew detection (TIM-446).
|
|
116
|
+
// The server compares this against the current build's ID.
|
|
117
|
+
// On mismatch, the server signals a reload instead of returning
|
|
118
|
+
// an RSC payload with mismatched module references.
|
|
119
|
+
if (clientDeploymentId) {
|
|
120
|
+
headers[DEPLOYMENT_ID_HEADER] = clientDeploymentId;
|
|
121
|
+
}
|
|
78
122
|
return headers;
|
|
79
123
|
}
|
|
80
124
|
|
|
81
125
|
// ─── Response Header Extraction ──────────────────────────────────
|
|
82
126
|
|
|
127
|
+
/** Dev-only warning for malformed framework headers. Tree-shaken in production. */
|
|
128
|
+
function warnMalformedHeader(headerName: string, raw: string): void {
|
|
129
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
130
|
+
const preview = raw.length > 200 ? raw.slice(0, 200) + '…' : raw;
|
|
131
|
+
console.warn(
|
|
132
|
+
`[timber] Malformed ${headerName} header \u2014 JSON.parse failed. ` +
|
|
133
|
+
`This indicates a framework bug or header corruption. Raw (first 200 chars): ${preview}`
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
83
138
|
/**
|
|
84
139
|
* Extract head elements from the X-Timber-Head response header.
|
|
85
140
|
* Returns null if the header is missing or malformed.
|
|
@@ -90,6 +145,7 @@ export function extractHeadElements(response: Response): HeadElement[] | null {
|
|
|
90
145
|
try {
|
|
91
146
|
return JSON.parse(decodeURIComponent(header));
|
|
92
147
|
} catch {
|
|
148
|
+
warnMalformedHeader('X-Timber-Head', header);
|
|
93
149
|
return null;
|
|
94
150
|
}
|
|
95
151
|
}
|
|
@@ -108,6 +164,7 @@ export function extractSegmentInfo(response: Response): SegmentInfo[] | null {
|
|
|
108
164
|
try {
|
|
109
165
|
return JSON.parse(header);
|
|
110
166
|
} catch {
|
|
167
|
+
warnMalformedHeader('X-Timber-Segments', header);
|
|
111
168
|
return null;
|
|
112
169
|
}
|
|
113
170
|
}
|
|
@@ -127,6 +184,7 @@ export function extractSkippedSegments(response: Response): string[] | null {
|
|
|
127
184
|
const parsed = JSON.parse(header);
|
|
128
185
|
return Array.isArray(parsed) ? parsed : null;
|
|
129
186
|
} catch {
|
|
187
|
+
warnMalformedHeader('X-Timber-Skipped-Segments', header);
|
|
130
188
|
return null;
|
|
131
189
|
}
|
|
132
190
|
}
|
|
@@ -135,7 +193,7 @@ export function extractSkippedSegments(response: Response): string[] | null {
|
|
|
135
193
|
* Extract route params from the X-Timber-Params response header.
|
|
136
194
|
* Returns null if the header is missing or malformed.
|
|
137
195
|
*
|
|
138
|
-
* Used to populate
|
|
196
|
+
* Used to populate useSegmentParams() after client-side navigation.
|
|
139
197
|
*/
|
|
140
198
|
export function extractParams(response: Response): Record<string, string | string[]> | null {
|
|
141
199
|
const header = response.headers.get('X-Timber-Params');
|
|
@@ -143,6 +201,7 @@ export function extractParams(response: Response): Record<string, string | strin
|
|
|
143
201
|
try {
|
|
144
202
|
return JSON.parse(header);
|
|
145
203
|
} catch {
|
|
204
|
+
warnMalformedHeader('X-Timber-Params', header);
|
|
146
205
|
return null;
|
|
147
206
|
}
|
|
148
207
|
}
|
|
@@ -161,6 +220,36 @@ export class RedirectError extends Error {
|
|
|
161
220
|
}
|
|
162
221
|
}
|
|
163
222
|
|
|
223
|
+
/**
|
|
224
|
+
* Thrown when the server signals a version skew (X-Timber-Reload header).
|
|
225
|
+
* Caught in navigate() to trigger a full page reload via triggerStaleReload().
|
|
226
|
+
* See TIM-446.
|
|
227
|
+
*/
|
|
228
|
+
export class VersionSkewError extends Error {
|
|
229
|
+
constructor() {
|
|
230
|
+
super('Version skew detected — server has been redeployed');
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Thrown when the server returns an error for an RSC payload request.
|
|
236
|
+
* The server sends X-Timber-Error header and a JSON body instead of a
|
|
237
|
+
* broken RSC stream for any RenderError (4xx or 5xx). Caught in
|
|
238
|
+
* navigate() to trigger a hard navigation so the server can render
|
|
239
|
+
* the error page as HTML.
|
|
240
|
+
*
|
|
241
|
+
* See design/10-error-handling.md §"Error Page Rendering for Client Navigation"
|
|
242
|
+
*/
|
|
243
|
+
export class ServerErrorResponse extends Error {
|
|
244
|
+
readonly status: number;
|
|
245
|
+
readonly url: string;
|
|
246
|
+
constructor(status: number, url: string) {
|
|
247
|
+
super(`Server error ${status} during navigation to ${url}`);
|
|
248
|
+
this.status = status;
|
|
249
|
+
this.url = url;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
164
253
|
// ─── Fetch ───────────────────────────────────────────────────────
|
|
165
254
|
|
|
166
255
|
/**
|
|
@@ -175,7 +264,8 @@ export async function fetchRscPayload(
|
|
|
175
264
|
url: string,
|
|
176
265
|
deps: RouterDeps,
|
|
177
266
|
stateTree?: { segments: string[] },
|
|
178
|
-
currentUrl?: string
|
|
267
|
+
currentUrl?: string,
|
|
268
|
+
signal?: AbortSignal
|
|
179
269
|
): Promise<FetchResult> {
|
|
180
270
|
const rscUrl = appendRscParam(url);
|
|
181
271
|
const headers = buildRscHeaders(stateTree, currentUrl);
|
|
@@ -186,12 +276,18 @@ export async function fetchRscPayload(
|
|
|
186
276
|
//
|
|
187
277
|
// Intercept the response to read X-Timber-Head before createFromFetch
|
|
188
278
|
// consumes the body. Reading headers does NOT consume the body stream.
|
|
189
|
-
const fetchPromise = deps.fetch(rscUrl, { headers, redirect: 'manual' });
|
|
279
|
+
const fetchPromise = deps.fetch(rscUrl, { headers, redirect: 'manual', signal });
|
|
190
280
|
let headElements: HeadElement[] | null = null;
|
|
191
281
|
let segmentInfo: SegmentInfo[] | null = null;
|
|
192
282
|
let params: Record<string, string | string[]> | null = null;
|
|
193
283
|
let skippedSegments: string[] | null = null;
|
|
194
284
|
const wrappedPromise = fetchPromise.then((response) => {
|
|
285
|
+
// Version skew detection (TIM-446): if the server signals a reload,
|
|
286
|
+
// throw VersionSkewError so the caller (router navigate) can trigger
|
|
287
|
+
// a full page reload via triggerStaleReload().
|
|
288
|
+
if (checkReloadSignal(response)) {
|
|
289
|
+
throw new VersionSkewError();
|
|
290
|
+
}
|
|
195
291
|
// Detect server-side redirects. The server returns 204 + X-Timber-Redirect
|
|
196
292
|
// for RSC payload requests instead of a raw 302, because fetch with
|
|
197
293
|
// redirect: "manual" turns 302s into opaque redirects (status 0, null body)
|
|
@@ -202,21 +298,29 @@ export async function fetchRscPayload(
|
|
|
202
298
|
if (redirectLocation) {
|
|
203
299
|
throw new RedirectError(redirectLocation);
|
|
204
300
|
}
|
|
301
|
+
// Detect server error responses. The server returns X-Timber-Error header
|
|
302
|
+
// with a JSON body instead of a broken RSC stream for any RenderError
|
|
303
|
+
// (4xx or 5xx). Hard-navigate so the server renders the error page as HTML.
|
|
304
|
+
// See design/10-error-handling.md §"Error Page Rendering for Client Navigation"
|
|
305
|
+
if (response.headers.get('X-Timber-Error') === '1') {
|
|
306
|
+
throw new ServerErrorResponse(response.status, url);
|
|
307
|
+
}
|
|
205
308
|
headElements = extractHeadElements(response);
|
|
206
309
|
segmentInfo = extractSegmentInfo(response);
|
|
207
310
|
params = extractParams(response);
|
|
208
311
|
skippedSegments = extractSkippedSegments(response);
|
|
209
312
|
return response;
|
|
210
313
|
});
|
|
211
|
-
// Await so headElements/segmentInfo/params are populated
|
|
212
|
-
// Also await the decoded payload — createFromFetch returns a thenable
|
|
213
|
-
// that resolves to the React element tree.
|
|
314
|
+
// Await headers so headElements/segmentInfo/params are populated.
|
|
214
315
|
await wrappedPromise;
|
|
316
|
+
// Await the decoded payload — createFromFetch returns a thenable
|
|
317
|
+
// that resolves to the React element tree once the Flight stream
|
|
318
|
+
// has enough data to produce the shell.
|
|
215
319
|
const payload = await deps.decodeRsc(wrappedPromise);
|
|
216
320
|
return { payload, headElements, segmentInfo, params, skippedSegments };
|
|
217
321
|
}
|
|
218
322
|
// Test/fallback path: return raw text
|
|
219
|
-
const response = await deps.fetch(rscUrl, { headers, redirect: 'manual' });
|
|
323
|
+
const response = await deps.fetch(rscUrl, { headers, redirect: 'manual', signal });
|
|
220
324
|
// Check for redirect in test path too
|
|
221
325
|
if (response.status >= 300 && response.status < 400) {
|
|
222
326
|
const location = response.headers.get('Location');
|
|
@@ -11,7 +11,7 @@ export interface PrefetchResult {
|
|
|
11
11
|
headElements: HeadElement[] | null;
|
|
12
12
|
/** Segment metadata from X-Timber-Segments header for populating the segment cache. */
|
|
13
13
|
segmentInfo?: SegmentInfo[] | null;
|
|
14
|
-
/** Route params from X-Timber-Params header for populating
|
|
14
|
+
/** Route params from X-Timber-Params header for populating useSegmentParams(). */
|
|
15
15
|
params?: Record<string, string | string[]> | null;
|
|
16
16
|
/** Segment paths skipped by the server (for client-side merging). */
|
|
17
17
|
skippedSegments?: string[] | null;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SegmentOutlet — client component boundary at each layout segment.
|
|
3
|
+
*
|
|
4
|
+
* Replaces the post-hoc tree walking in segment-merger.ts with an explicit
|
|
5
|
+
* client component at each segment boundary. Each outlet:
|
|
6
|
+
*
|
|
7
|
+
* 1. Knows its own segment path (prop from the server)
|
|
8
|
+
* 2. Caches its children in a ref across navigations
|
|
9
|
+
* 3. When `keepCurrent` is true (partial navigation, this segment skipped),
|
|
10
|
+
* returns the previously cached children — layout state is preserved
|
|
11
|
+
* 4. When `keepCurrent` is false (full navigation or this segment changed),
|
|
12
|
+
* stores and renders the new children
|
|
13
|
+
*
|
|
14
|
+
* This eliminates the need for client-side element tree walking, which
|
|
15
|
+
* breaks on real RSC trees due to opaque client component lazy refs,
|
|
16
|
+
* Suspense thenables, and AccessGate wrappers.
|
|
17
|
+
*
|
|
18
|
+
* Architecture is similar to Next.js's `<LayoutRouter>` client component —
|
|
19
|
+
* each layout boundary is an explicit client component that manages its
|
|
20
|
+
* own subtree. See design/19-client-navigation.md.
|
|
21
|
+
*
|
|
22
|
+
* Security: This is a performance optimization only. The server always
|
|
23
|
+
* runs all access.ts files regardless of segment skipping. A fabricated
|
|
24
|
+
* keepCurrent prop can only cause stale layouts — never auth bypass.
|
|
25
|
+
* See design/13-security.md §"State tree manipulation".
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
'use client';
|
|
29
|
+
|
|
30
|
+
import { useRef, type ReactNode } from 'react';
|
|
31
|
+
|
|
32
|
+
export interface SegmentOutletProps {
|
|
33
|
+
/**
|
|
34
|
+
* Unique identifier for this segment. For normal segments this is the
|
|
35
|
+
* urlPath (e.g., "/", "/dashboard"). For route groups this includes the
|
|
36
|
+
* group name (e.g., "/(marketing)") to distinguish siblings that share
|
|
37
|
+
* the same urlPath. Must match the segmentId used in state-tree-diff.ts.
|
|
38
|
+
*/
|
|
39
|
+
segmentPath: string;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* When true, the outlet returns its previously cached children instead
|
|
43
|
+
* of rendering the new children prop. Set by the server when this
|
|
44
|
+
* segment was skipped (the client already has the layout mounted).
|
|
45
|
+
*
|
|
46
|
+
* On the first render (SSR/hydration), this is always false — there's
|
|
47
|
+
* no cached content yet. On subsequent partial navigations, the server
|
|
48
|
+
* sets this to true for segments it skipped rendering.
|
|
49
|
+
*/
|
|
50
|
+
keepCurrent?: boolean;
|
|
51
|
+
|
|
52
|
+
/** The segment's React subtree (layout + inner content). */
|
|
53
|
+
children: ReactNode;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Client component boundary at each layout segment in the element tree.
|
|
58
|
+
*
|
|
59
|
+
* On full navigation: receives new children, stores them, renders them.
|
|
60
|
+
* On partial navigation (keepCurrent=true): ignores children prop,
|
|
61
|
+
* returns previously stored content — React reconciles the same elements,
|
|
62
|
+
* preserving all client component state in the layout subtree.
|
|
63
|
+
*
|
|
64
|
+
* React preserves the ref across `reactRoot.render()` calls because:
|
|
65
|
+
* - SegmentOutlet has a stable type (client component module reference)
|
|
66
|
+
* - It appears at the same tree position on every navigation
|
|
67
|
+
* - React reconciles same-type, same-position → instance preserved
|
|
68
|
+
*/
|
|
69
|
+
export function SegmentOutlet({
|
|
70
|
+
segmentPath: _segmentPath,
|
|
71
|
+
keepCurrent = false,
|
|
72
|
+
children,
|
|
73
|
+
}: SegmentOutletProps) {
|
|
74
|
+
// Store content in a ref to avoid triggering re-renders on cache updates.
|
|
75
|
+
// The ref persists across reactRoot.render() calls because React reconciles
|
|
76
|
+
// the same component type at the same tree position.
|
|
77
|
+
const contentRef = useRef<ReactNode>(null);
|
|
78
|
+
|
|
79
|
+
if (!keepCurrent) {
|
|
80
|
+
// Full render or this segment was re-rendered — store and render new content
|
|
81
|
+
contentRef.current = children;
|
|
82
|
+
}
|
|
83
|
+
// else: keepCurrent=true — return previously cached content
|
|
84
|
+
|
|
85
|
+
return contentRef.current;
|
|
86
|
+
}
|
package/src/client/ssr-data.ts
CHANGED
|
@@ -41,12 +41,20 @@ export interface SsrData {
|
|
|
41
41
|
/** The request's route params (e.g. { id: '123' }) */
|
|
42
42
|
params: Record<string, string | string[]>;
|
|
43
43
|
/**
|
|
44
|
-
* Mutable reference to NavContext for error boundary →
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
44
|
+
* Mutable reference to NavContext for error boundary → pipeline communication.
|
|
45
|
+
*
|
|
46
|
+
* When TimberErrorBoundary catches a DenySignal during SSR, it:
|
|
47
|
+
* 1. Sets `statusCode` to the deny status (e.g., 403) — so the HTTP
|
|
48
|
+
* Response has the correct status code without a re-render.
|
|
49
|
+
* 2. Sets `_denyHandledByBoundary = true` — so the pipeline skips
|
|
50
|
+
* the redundant renderDenyPage() re-render.
|
|
51
|
+
*
|
|
52
|
+
* This runs synchronously during Fizz rendering, BEFORE onShellReady,
|
|
53
|
+
* so the status code is committed before any bytes are sent.
|
|
54
|
+
*
|
|
55
|
+
* See TIM-664, design/04-authorization.md §"React.cache Scope in Deny/Error Re-renders"
|
|
48
56
|
*/
|
|
49
|
-
_navContext?: { _denyHandledByBoundary?: boolean };
|
|
57
|
+
_navContext?: { statusCode?: number; _denyHandledByBoundary?: boolean };
|
|
50
58
|
}
|
|
51
59
|
|
|
52
60
|
// ─── ALS-Backed Provider ─────────────────────────────────────────
|
|
@@ -16,6 +16,16 @@
|
|
|
16
16
|
|
|
17
17
|
const RELOAD_FLAG_KEY = '__timber_stale_reload';
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* In-memory fallback counter for environments where sessionStorage is
|
|
21
|
+
* unavailable (private browsing, storage full, extension interference).
|
|
22
|
+
* Incremented each time triggerStaleReload() falls into the catch path.
|
|
23
|
+
* If the counter exceeds 0 on a subsequent call, the reload is suppressed
|
|
24
|
+
* to prevent an infinite loop. Resets naturally on page load (module
|
|
25
|
+
* re-evaluates) and can be manually reset via clearStaleReloadFlag().
|
|
26
|
+
*/
|
|
27
|
+
let memoryReloadCount = 0;
|
|
28
|
+
|
|
19
29
|
/**
|
|
20
30
|
* Check if an error is a stale client reference error from React's
|
|
21
31
|
* Flight client. These errors have the message pattern:
|
|
@@ -32,6 +42,34 @@ export function isStaleClientReference(error: unknown): boolean {
|
|
|
32
42
|
return msg.includes('Could not find the module') || msg.includes('client reference not found');
|
|
33
43
|
}
|
|
34
44
|
|
|
45
|
+
/**
|
|
46
|
+
* Check if an error is a chunk load failure from a dynamic import.
|
|
47
|
+
*
|
|
48
|
+
* After a deployment, old chunk filenames no longer exist. When the client
|
|
49
|
+
* tries to dynamically import a chunk that's been replaced, the browser
|
|
50
|
+
* throws one of these errors:
|
|
51
|
+
*
|
|
52
|
+
* - Chromium: "Failed to fetch dynamically imported module: <url>"
|
|
53
|
+
* - Firefox: "error loading dynamically imported module: <url>"
|
|
54
|
+
* - Safari: "Importing a module script failed."
|
|
55
|
+
* - Vite/Rollup: "Unable to preload CSS for <url>"
|
|
56
|
+
*
|
|
57
|
+
* See TIM-446
|
|
58
|
+
*/
|
|
59
|
+
export function isChunkLoadError(error: unknown): boolean {
|
|
60
|
+
if (!(error instanceof Error)) return false;
|
|
61
|
+
const msg = error.message.toLowerCase();
|
|
62
|
+
return (
|
|
63
|
+
msg.includes('failed to fetch dynamically imported module') ||
|
|
64
|
+
msg.includes('error loading dynamically imported module') ||
|
|
65
|
+
msg.includes('importing a module script failed') ||
|
|
66
|
+
msg.includes('unable to preload css') ||
|
|
67
|
+
// Webpack-style chunk load errors (unlikely in Vite but defensive)
|
|
68
|
+
msg.includes('loading chunk') ||
|
|
69
|
+
msg.includes('loading css chunk')
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
35
73
|
/**
|
|
36
74
|
* Trigger a full page reload to pick up new bundles.
|
|
37
75
|
*
|
|
@@ -65,9 +103,33 @@ export function triggerStaleReload(): boolean {
|
|
|
65
103
|
window.location.reload();
|
|
66
104
|
return true;
|
|
67
105
|
} catch {
|
|
68
|
-
// sessionStorage
|
|
69
|
-
//
|
|
70
|
-
|
|
106
|
+
// sessionStorage unavailable (private browsing, storage full, etc.)
|
|
107
|
+
// Use document.cookie as a reload-persistent fallback loop guard.
|
|
108
|
+
// Module-level memoryReloadCount resets on every reload, so it can't
|
|
109
|
+
// detect cross-reload loops. Cookies persist across reloads and are
|
|
110
|
+
// available even when sessionStorage is blocked (TIM-576).
|
|
111
|
+
const cookieFlag = document.cookie.includes(RELOAD_FLAG_KEY + '=1');
|
|
112
|
+
if (cookieFlag || memoryReloadCount > 0) {
|
|
113
|
+
console.warn(
|
|
114
|
+
'[timber] Stale client reference detected again after reload. ' +
|
|
115
|
+
'Not reloading to prevent infinite loop. ' +
|
|
116
|
+
'This may indicate a deployment issue — try a hard refresh.'
|
|
117
|
+
);
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
memoryReloadCount++;
|
|
122
|
+
// Set a short-lived cookie (60s) as the persistent loop guard.
|
|
123
|
+
// It auto-expires so it won't block future legitimate reloads.
|
|
124
|
+
try {
|
|
125
|
+
document.cookie = `${RELOAD_FLAG_KEY}=1; max-age=60; path=/; SameSite=Lax`;
|
|
126
|
+
} catch {
|
|
127
|
+
// Cookie API unavailable — proceed anyway, memoryReloadCount guards same-page loops
|
|
128
|
+
}
|
|
129
|
+
console.warn(
|
|
130
|
+
'[timber] Stale client reference detected — the server has been ' +
|
|
131
|
+
'redeployed with new bundles. Reloading to pick up the new version.'
|
|
132
|
+
);
|
|
71
133
|
window.location.reload();
|
|
72
134
|
return true;
|
|
73
135
|
}
|
|
@@ -79,9 +141,16 @@ export function triggerStaleReload(): boolean {
|
|
|
79
141
|
* reference error should trigger a fresh reload attempt.
|
|
80
142
|
*/
|
|
81
143
|
export function clearStaleReloadFlag(): void {
|
|
144
|
+
memoryReloadCount = 0;
|
|
82
145
|
try {
|
|
83
146
|
sessionStorage.removeItem(RELOAD_FLAG_KEY);
|
|
84
147
|
} catch {
|
|
85
148
|
// sessionStorage unavailable — nothing to clear
|
|
86
149
|
}
|
|
150
|
+
// Also clear the cookie fallback
|
|
151
|
+
try {
|
|
152
|
+
document.cookie = `${RELOAD_FLAG_KEY}=; max-age=0; path=/; SameSite=Lax`;
|
|
153
|
+
} catch {
|
|
154
|
+
// Cookie API unavailable
|
|
155
|
+
}
|
|
87
156
|
}
|
package/src/client/state.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* ALL mutable module-level state that must have singleton semantics across
|
|
5
5
|
* the client bundle lives here. Individual modules (router-ref.ts, ssr-data.ts,
|
|
6
|
-
* use-params.ts, use-search-params.ts, unload-guard.ts) import from this file
|
|
6
|
+
* use-segment-params.ts, use-search-params.ts, unload-guard.ts) import from this file
|
|
7
7
|
* and re-export thin wrapper functions.
|
|
8
8
|
*
|
|
9
9
|
* Why: In Vite dev, a module is instantiated separately if reached via different
|
|
@@ -50,7 +50,7 @@ export function _setCurrentSsrData(data: SsrData | undefined): void {
|
|
|
50
50
|
currentSsrData = data;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
// ─── Route Params (from use-params.ts) ──────────────────────────────────────
|
|
53
|
+
// ─── Route Params (from use-segment-params.ts) ──────────────────────────────────────
|
|
54
54
|
|
|
55
55
|
/** Current route params snapshot — replaced (not mutated) on each navigation. */
|
|
56
56
|
export let currentParams: Record<string, string | string[]> = {};
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Shows an animated progress bar at the top of the viewport while an RSC
|
|
5
5
|
* navigation is in flight. Injected automatically by the framework into
|
|
6
|
-
*
|
|
6
|
+
* NavigationRoot — users never render this component directly.
|
|
7
7
|
*
|
|
8
8
|
* Configuration is via timber.config.ts `topLoader` key. Enabled by default.
|
|
9
9
|
* Users who want a fully custom progress indicator disable the built-in one
|
|
10
|
-
* (`topLoader: { enabled: false }`) and use `
|
|
10
|
+
* (`topLoader: { enabled: false }`) and use `usePendingNavigation()` directly.
|
|
11
11
|
*
|
|
12
12
|
* Animation approach: pure CSS @keyframes. The bar crawls from 0% to ~90%
|
|
13
13
|
* width over ~30s using ease-out timing. When navigation completes, the bar
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* stays invisible during the delay period. If navigation finishes before the
|
|
22
22
|
* delay, the bar was never visible so the finish transition is also invisible.
|
|
23
23
|
*
|
|
24
|
-
* See design/19-client-navigation.md §"
|
|
24
|
+
* See design/19-client-navigation.md §"usePendingNavigation()"
|
|
25
25
|
* See LOCAL-336 for design decisions.
|
|
26
26
|
*/
|
|
27
27
|
|
|
@@ -39,7 +39,7 @@ export interface TopLoaderConfig {
|
|
|
39
39
|
color?: string;
|
|
40
40
|
/** Bar height in pixels. Default: 3. */
|
|
41
41
|
height?: number;
|
|
42
|
-
/** Show subtle glow/shadow effect. Default:
|
|
42
|
+
/** Show subtle glow/shadow effect. Default: false. */
|
|
43
43
|
shadow?: boolean;
|
|
44
44
|
/** Delay in ms before showing the bar. Default: 0. */
|
|
45
45
|
delay?: number;
|
|
@@ -51,7 +51,7 @@ export interface TopLoaderConfig {
|
|
|
51
51
|
|
|
52
52
|
const DEFAULT_COLOR = '#2299DD';
|
|
53
53
|
const DEFAULT_HEIGHT = 3;
|
|
54
|
-
const DEFAULT_SHADOW =
|
|
54
|
+
const DEFAULT_SHADOW = false;
|
|
55
55
|
const DEFAULT_DELAY = 0;
|
|
56
56
|
const DEFAULT_Z_INDEX = 1600;
|
|
57
57
|
|
|
@@ -97,7 +97,7 @@ function ensureKeyframes(): void {
|
|
|
97
97
|
// ─── Component ───────────────────────────────────────────────────
|
|
98
98
|
|
|
99
99
|
/**
|
|
100
|
-
* Internal top-loader component. Injected by
|
|
100
|
+
* Internal top-loader component. Injected by NavigationRoot.
|
|
101
101
|
*
|
|
102
102
|
* Reads pending navigation state from PendingNavigationContext.
|
|
103
103
|
* Phase transitions are derived synchronously during render:
|
|
@@ -112,6 +112,18 @@ function ensureKeyframes(): void {
|
|
|
112
112
|
*/
|
|
113
113
|
export function TopLoader({ config }: { config?: TopLoaderConfig }): React.ReactElement | null {
|
|
114
114
|
const pendingUrl = usePendingNavigationUrl();
|
|
115
|
+
// Navigation is pending when the React-based pending URL is set.
|
|
116
|
+
// pendingUrl is set as an urgent update in navigateTransition() —
|
|
117
|
+
// React commits it before the next paint, so the TopLoader appears
|
|
118
|
+
// immediately when a real RSC navigation starts.
|
|
119
|
+
//
|
|
120
|
+
// We intentionally do NOT check hasNativeNavigationTransition() here.
|
|
121
|
+
// The Navigation API's transition is active for ALL intercepted
|
|
122
|
+
// navigations, including shallow URL updates (nuqs search param
|
|
123
|
+
// changes with shallow: true) and prevented navigations. Those
|
|
124
|
+
// briefly set navigation.transition via event.intercept() but do
|
|
125
|
+
// NOT trigger RSC fetches — showing the TopLoader would be incorrect.
|
|
126
|
+
// pendingUrl is the authoritative signal for "we're fetching RSC data."
|
|
115
127
|
const isPending = pendingUrl !== null;
|
|
116
128
|
|
|
117
129
|
const color = config?.color ?? DEFAULT_COLOR;
|
package/src/client/use-cookie.ts
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
import { useSyncExternalStore } from 'react';
|
|
12
12
|
import { getSsrData } from './ssr-data.js';
|
|
13
|
+
import { assertValidCookieName } from '../cookies/validation.js';
|
|
13
14
|
|
|
14
15
|
// ─── Types ────────────────────────────────────────────────────────────────
|
|
15
16
|
|
|
@@ -38,7 +39,7 @@ type Listener = () => void;
|
|
|
38
39
|
const listeners = new Map<string, Set<Listener>>();
|
|
39
40
|
|
|
40
41
|
/** Parse a cookie name from document.cookie. */
|
|
41
|
-
function getCookieValue(name: string): string | undefined {
|
|
42
|
+
export function getCookieValue(name: string): string | undefined {
|
|
42
43
|
if (typeof document === 'undefined') return undefined;
|
|
43
44
|
const match = document.cookie.match(
|
|
44
45
|
new RegExp('(?:^|;\\s*)' + name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '\\s*=\\s*([^;]*)')
|
|
@@ -47,7 +48,7 @@ function getCookieValue(name: string): string | undefined {
|
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
/** Serialize options into a cookie string suffix. */
|
|
50
|
-
function serializeOptions(options?: ClientCookieOptions): string {
|
|
51
|
+
export function serializeOptions(options?: ClientCookieOptions): string {
|
|
51
52
|
if (!options) return '; Path=/; SameSite=Lax';
|
|
52
53
|
const parts: string[] = [];
|
|
53
54
|
parts.push(`Path=${options.path ?? '/'}`);
|
|
@@ -68,6 +69,17 @@ function notify(name: string): void {
|
|
|
68
69
|
}
|
|
69
70
|
}
|
|
70
71
|
|
|
72
|
+
/**
|
|
73
|
+
* Notify useCookie subscribers that a cookie value changed.
|
|
74
|
+
* Called by defineCookie's imperative client .set()/.delete() methods
|
|
75
|
+
* so mounted useCookie() consumers re-render.
|
|
76
|
+
*
|
|
77
|
+
* @internal — framework use only
|
|
78
|
+
*/
|
|
79
|
+
export function notifyCookieChange(name: string): void {
|
|
80
|
+
notify(name);
|
|
81
|
+
}
|
|
82
|
+
|
|
71
83
|
// ─── Hook ─────────────────────────────────────────────────────────────────
|
|
72
84
|
|
|
73
85
|
/**
|
|
@@ -103,8 +115,25 @@ export function useCookie(
|
|
|
103
115
|
|
|
104
116
|
const value = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
|
|
105
117
|
|
|
118
|
+
// Validate the name once per hook instance — names are typically
|
|
119
|
+
// stable string literals, so this catches the bug at first render
|
|
120
|
+
// rather than on every write. Throws via `assertValidCookieName` with
|
|
121
|
+
// a precise error if the name violates RFC 7230 token rules.
|
|
122
|
+
assertValidCookieName(name);
|
|
123
|
+
|
|
106
124
|
const setCookie: CookieSetter = (newValue: string, options?: ClientCookieOptions) => {
|
|
125
|
+
if (typeof newValue !== 'string') {
|
|
126
|
+
throw new Error(
|
|
127
|
+
`[timber] useCookie(${JSON.stringify(name)}): value must be a string, got ${typeof newValue}.\n` +
|
|
128
|
+
` To store a JSON-serializable value, use defineCookie + jsonCookieCodec from\n` +
|
|
129
|
+
` '@timber-js/app/cookies' and call its useCookie() hook instead.`
|
|
130
|
+
);
|
|
131
|
+
}
|
|
107
132
|
const merged = { ...defaultOptions, ...options };
|
|
133
|
+
// Auto-encode mirrors the server's `cookies().set()` contract:
|
|
134
|
+
// values are URL-encoded on write, URL-decoded on read, so the
|
|
135
|
+
// logical bytes round-trip losslessly. See design/29-cookies.md
|
|
136
|
+
// §"Encoding Contract".
|
|
108
137
|
document.cookie = `${name}=${encodeURIComponent(newValue)}${serializeOptions(merged)}`;
|
|
109
138
|
notify(name);
|
|
110
139
|
};
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
// useLinkStatus — returns {
|
|
3
|
+
// useLinkStatus — returns { isPending: true } while the nearest parent <Link>'s
|
|
4
4
|
// navigation is in flight. No arguments — scoped via React context.
|
|
5
5
|
// See design/19-client-navigation.md §"useLinkStatus()"
|
|
6
6
|
|
|
7
7
|
import { useContext, createContext } from 'react';
|
|
8
8
|
|
|
9
9
|
export interface LinkStatus {
|
|
10
|
-
|
|
10
|
+
isPending: boolean;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* React context provided by <Link>. Holds the pending status
|
|
15
15
|
* for that specific link's navigation.
|
|
16
16
|
*/
|
|
17
|
-
export const LinkStatusContext = createContext<LinkStatus>({
|
|
17
|
+
export const LinkStatusContext = createContext<LinkStatus>({ isPending: false });
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
* Returns `{
|
|
20
|
+
* Returns `{ isPending: true }` while the nearest parent `<Link>` component's
|
|
21
21
|
* navigation is in flight. Must be used inside a `<Link>` component's children.
|
|
22
22
|
*
|
|
23
|
-
* Unlike `
|
|
23
|
+
* Unlike `usePendingNavigation()` which is global, this hook is scoped to
|
|
24
24
|
* the nearest parent `<Link>` — only the link the user clicked shows pending.
|
|
25
25
|
*
|
|
26
26
|
* ```tsx
|
|
@@ -28,8 +28,8 @@ export const LinkStatusContext = createContext<LinkStatus>({ pending: false });
|
|
|
28
28
|
* import { Link, useLinkStatus } from '@timber-js/app/client'
|
|
29
29
|
*
|
|
30
30
|
* function Hint() {
|
|
31
|
-
* const {
|
|
32
|
-
* return <span className={
|
|
31
|
+
* const { isPending } = useLinkStatus()
|
|
32
|
+
* return <span className={isPending ? 'opacity-50' : ''} />
|
|
33
33
|
* }
|
|
34
34
|
*
|
|
35
35
|
* export function NavLink({ href, children }) {
|