@timber-js/app 0.2.0-alpha.19 → 0.2.0-alpha.191
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/agent-skill.md +344 -0
- package/dist/_chunks/actions-BjbbNRFN.js +318 -0
- package/dist/_chunks/actions-BjbbNRFN.js.map +1 -0
- package/dist/_chunks/als-registry-C6kcfprT.js +41 -0
- package/dist/_chunks/als-registry-C6kcfprT.js.map +1 -0
- package/dist/_chunks/als-slots-BEEIPKYm.js +26 -0
- package/dist/_chunks/als-slots-BEEIPKYm.js.map +1 -0
- package/dist/_chunks/base-path-DaQrzbez.js +80 -0
- package/dist/_chunks/base-path-DaQrzbez.js.map +1 -0
- package/dist/_chunks/build-manifest-DWppEdLB.js +86 -0
- package/dist/_chunks/build-manifest-DWppEdLB.js.map +1 -0
- package/dist/_chunks/build-output-helper-C3DrfzZR.js +369 -0
- package/dist/_chunks/build-output-helper-C3DrfzZR.js.map +1 -0
- package/dist/_chunks/cache-api-DllJ-Lyw.js +1196 -0
- package/dist/_chunks/cache-api-DllJ-Lyw.js.map +1 -0
- package/dist/_chunks/cli-check-DJZDc22E.js +256 -0
- package/dist/_chunks/cli-check-DJZDc22E.js.map +1 -0
- package/dist/_chunks/cli-schema-sync-D4_AZVUb.js +298 -0
- package/dist/_chunks/cli-schema-sync-D4_AZVUb.js.map +1 -0
- package/dist/_chunks/cloudflare-CGP6BZKO.js +1284 -0
- package/dist/_chunks/cloudflare-CGP6BZKO.js.map +1 -0
- package/dist/_chunks/codec-registry-oOUxugz3.js +21 -0
- package/dist/_chunks/codec-registry-oOUxugz3.js.map +1 -0
- package/dist/_chunks/convention-lint-CpteIpTm.js +784 -0
- package/dist/_chunks/convention-lint-CpteIpTm.js.map +1 -0
- package/dist/_chunks/dist-BA3u1z3W.js +423 -0
- package/dist/_chunks/dist-BA3u1z3W.js.map +1 -0
- package/dist/_chunks/error-boundary-D-ODYX41.js +353 -0
- package/dist/_chunks/error-boundary-D-ODYX41.js.map +1 -0
- package/dist/_chunks/fast-hash-C-tVYrLb.js +41 -0
- package/dist/_chunks/fast-hash-C-tVYrLb.js.map +1 -0
- package/dist/_chunks/file-cache-DmX7OqZP.js +454 -0
- package/dist/_chunks/file-cache-DmX7OqZP.js.map +1 -0
- package/dist/_chunks/format-CfwjgPz9.js +14 -0
- package/dist/_chunks/format-CfwjgPz9.js.map +1 -0
- package/dist/_chunks/fs-identity-D7vb6GdI.js +208 -0
- package/dist/_chunks/fs-identity-D7vb6GdI.js.map +1 -0
- package/dist/_chunks/href-validation-CMc5JRls.js +141 -0
- package/dist/_chunks/href-validation-CMc5JRls.js.map +1 -0
- package/dist/_chunks/json-lossy-check-ClNvBM_3.js +63 -0
- package/dist/_chunks/json-lossy-check-ClNvBM_3.js.map +1 -0
- package/dist/_chunks/logger-CH7IcMmg.js +1436 -0
- package/dist/_chunks/logger-CH7IcMmg.js.map +1 -0
- package/dist/_chunks/mdx-file-C005ay-P.js +25 -0
- package/dist/_chunks/mdx-file-C005ay-P.js.map +1 -0
- package/dist/_chunks/plugin-context-rCinWLiE.js +321 -0
- package/dist/_chunks/plugin-context-rCinWLiE.js.map +1 -0
- package/dist/_chunks/purge-store-Byr8XOjU.js +14 -0
- package/dist/_chunks/purge-store-Byr8XOjU.js.map +1 -0
- package/dist/_chunks/resolve-schema-CBR6Lm4i.js +50 -0
- package/dist/_chunks/resolve-schema-CBR6Lm4i.js.map +1 -0
- package/dist/_chunks/router-ref-DuYuV_0Q.js +28 -0
- package/dist/_chunks/router-ref-DuYuV_0Q.js.map +1 -0
- package/dist/_chunks/rsc-cache-key-DD0fl_-s.js +243 -0
- package/dist/_chunks/rsc-cache-key-DD0fl_-s.js.map +1 -0
- package/dist/_chunks/rsc-error-envelope-tT5PJs4q.js +40 -0
- package/dist/_chunks/rsc-error-envelope-tT5PJs4q.js.map +1 -0
- package/dist/_chunks/rsc-media-type-DRqE_lD_.js +46 -0
- package/dist/_chunks/rsc-media-type-DRqE_lD_.js.map +1 -0
- package/dist/_chunks/rsc-payload-path-B_LBodc2.js +48 -0
- package/dist/_chunks/rsc-payload-path-B_LBodc2.js.map +1 -0
- package/dist/_chunks/scanner-CAietmj4.js +1564 -0
- package/dist/_chunks/scanner-CAietmj4.js.map +1 -0
- package/dist/_chunks/schema-bridge-C83xa9lT.js +199 -0
- package/dist/_chunks/schema-bridge-C83xa9lT.js.map +1 -0
- package/dist/_chunks/segment-classify-C539Pa2O.js +197 -0
- package/dist/_chunks/segment-classify-C539Pa2O.js.map +1 -0
- package/dist/_chunks/segment-context-CjOlyB8Y.js +97 -0
- package/dist/_chunks/segment-context-CjOlyB8Y.js.map +1 -0
- package/dist/_chunks/segment-keys-BawYuNFO.js +307 -0
- package/dist/_chunks/segment-keys-BawYuNFO.js.map +1 -0
- package/dist/_chunks/sizeof-lXffQ1Vr.js +35 -0
- package/dist/_chunks/sizeof-lXffQ1Vr.js.map +1 -0
- package/dist/_chunks/slot-params-BCTmZkQB.js +76 -0
- package/dist/_chunks/slot-params-BCTmZkQB.js.map +1 -0
- package/dist/_chunks/{ssr-data-MjmprTmO.js → ssr-data-14MXm7Pj.js} +17 -2
- package/dist/_chunks/ssr-data-14MXm7Pj.js.map +1 -0
- package/dist/_chunks/use-query-states-I3JMng6J.js +226 -0
- package/dist/_chunks/use-query-states-I3JMng6J.js.map +1 -0
- package/dist/_chunks/use-segment-params-C4r4BD9T.js +398 -0
- package/dist/_chunks/use-segment-params-C4r4BD9T.js.map +1 -0
- package/dist/_chunks/walkers-BsVLmD1S.js +141 -0
- package/dist/_chunks/walkers-BsVLmD1S.js.map +1 -0
- package/dist/adapters/build-output-helper.d.ts +72 -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 +65 -0
- package/dist/adapters/cloudflare-kv-cache.d.ts.map +1 -0
- package/dist/adapters/cloudflare-kv-cache.js +124 -0
- package/dist/adapters/cloudflare-kv-cache.js.map +1 -0
- package/dist/adapters/cloudflare.d.ts +199 -21
- package/dist/adapters/cloudflare.d.ts.map +1 -1
- package/dist/adapters/cloudflare.js +2 -188
- package/dist/adapters/compress-module.d.ts +17 -4
- package/dist/adapters/compress-module.d.ts.map +1 -1
- package/dist/adapters/fs-identity.d.ts +64 -0
- package/dist/adapters/fs-identity.d.ts.map +1 -0
- package/dist/adapters/nitro.d.ts +55 -3
- package/dist/adapters/nitro.d.ts.map +1 -1
- package/dist/adapters/nitro.js +287 -171
- package/dist/adapters/nitro.js.map +1 -1
- package/dist/adapters/shared.d.ts +62 -0
- package/dist/adapters/shared.d.ts.map +1 -0
- package/dist/adapters/types.d.ts +28 -6
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/cache/cache-api.d.ts +48 -0
- package/dist/cache/cache-api.d.ts.map +1 -0
- package/dist/cache/fast-hash.d.ts +5 -0
- package/dist/cache/fast-hash.d.ts.map +1 -1
- package/dist/cache/handler-store.d.ts +33 -0
- package/dist/cache/handler-store.d.ts.map +1 -0
- package/dist/cache/index.d.ts +31 -8
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +3 -326
- package/dist/cache/invalidation-epoch.d.ts +43 -0
- package/dist/cache/invalidation-epoch.d.ts.map +1 -0
- package/dist/cache/json-lossy-check.d.ts +11 -0
- package/dist/cache/json-lossy-check.d.ts.map +1 -0
- package/dist/cache/redis-handler.d.ts +140 -8
- package/dist/cache/redis-handler.d.ts.map +1 -1
- package/dist/cache/singleflight.d.ts +19 -2
- 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/store.d.ts +53 -0
- package/dist/cache/store.d.ts.map +1 -0
- package/dist/cache/stores/cloudflare-kv.d.ts +38 -0
- package/dist/cache/stores/cloudflare-kv.d.ts.map +1 -0
- package/dist/cache/stores/cloudflare-kv.js +29 -0
- package/dist/cache/stores/cloudflare-kv.js.map +1 -0
- package/dist/cache/stores/memory.d.ts +42 -0
- package/dist/cache/stores/memory.d.ts.map +1 -0
- package/dist/cache/stores/memory.js +90 -0
- package/dist/cache/stores/memory.js.map +1 -0
- package/dist/cache/stores/redis.d.ts +69 -0
- package/dist/cache/stores/redis.d.ts.map +1 -0
- package/dist/cache/stores/redis.js +35 -0
- package/dist/cache/stores/redis.js.map +1 -0
- package/dist/cache/stores/vercel.d.ts +36 -0
- package/dist/cache/stores/vercel.d.ts.map +1 -0
- package/dist/cache/stores/vercel.js +33 -0
- package/dist/cache/stores/vercel.js.map +1 -0
- package/dist/cache/tag-aware-handler.d.ts +52 -0
- package/dist/cache/tag-aware-handler.d.ts.map +1 -0
- package/dist/cache/timber-cache.d.ts +20 -10
- package/dist/cache/timber-cache.d.ts.map +1 -1
- package/dist/cdn/cloudflare-purge.d.ts +23 -0
- package/dist/cdn/cloudflare-purge.d.ts.map +1 -0
- package/dist/cdn/cloudflare-purge.js +30 -0
- package/dist/cdn/cloudflare-purge.js.map +1 -0
- package/dist/cdn/fastly-purge.d.ts +25 -0
- package/dist/cdn/fastly-purge.d.ts.map +1 -0
- package/dist/cdn/fastly-purge.js +33 -0
- package/dist/cdn/fastly-purge.js.map +1 -0
- package/dist/cdn/headers.d.ts +97 -0
- package/dist/cdn/headers.d.ts.map +1 -0
- package/dist/cdn/index.d.ts +5 -0
- package/dist/cdn/index.d.ts.map +1 -0
- package/dist/cdn/index.js +94 -0
- package/dist/cdn/index.js.map +1 -0
- package/dist/cdn/purge-store.d.ts +23 -0
- package/dist/cdn/purge-store.d.ts.map +1 -0
- package/dist/cdn/workers-cache-purge.d.ts +16 -0
- package/dist/cdn/workers-cache-purge.d.ts.map +1 -0
- package/dist/cdn/workers-cache-purge.js +35 -0
- package/dist/cdn/workers-cache-purge.js.map +1 -0
- package/dist/cli-check.d.ts +153 -0
- package/dist/cli-check.d.ts.map +1 -0
- package/dist/cli-schema-sync.d.ts +59 -0
- package/dist/cli-schema-sync.d.ts.map +1 -0
- package/dist/cli.d.ts +66 -7
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +151 -47
- package/dist/cli.js.map +1 -1
- package/dist/client/browser-dev.d.ts +37 -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 +57 -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 +29 -0
- package/dist/client/browser-entry/post-hydration.d.ts.map +1 -0
- package/dist/client/browser-entry/router-init.d.ts +30 -0
- package/dist/client/browser-entry/router-init.d.ts.map +1 -0
- package/dist/client/browser-entry/rsc-stream.d.ts +32 -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 +19 -5
- package/dist/client/error-boundary.d.ts.map +1 -1
- package/dist/client/error-boundary.js +1 -125
- 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 +29 -7
- package/dist/client/history.d.ts.map +1 -1
- package/dist/client/index.d.ts +11 -24
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +186 -1134
- package/dist/client/index.js.map +1 -1
- package/dist/client/internal.d.ts +20 -0
- package/dist/client/internal.d.ts.map +1 -0
- package/dist/client/internal.js +1624 -0
- package/dist/client/internal.js.map +1 -0
- package/dist/client/link.d.ts +63 -60
- package/dist/client/link.d.ts.map +1 -1
- package/dist/client/navigation-api.d.ts +121 -0
- package/dist/client/navigation-api.d.ts.map +1 -0
- package/dist/client/navigation-commit.d.ts +87 -0
- package/dist/client/navigation-commit.d.ts.map +1 -0
- package/dist/client/navigation-context.d.ts +38 -20
- package/dist/client/navigation-context.d.ts.map +1 -1
- package/dist/client/navigation-root.d.ts +159 -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/params-context.d.ts +82 -0
- package/dist/client/params-context.d.ts.map +1 -0
- package/dist/client/router-effects.d.ts +129 -0
- package/dist/client/router-effects.d.ts.map +1 -0
- package/dist/client/router-lifecycle.d.ts +55 -0
- package/dist/client/router-lifecycle.d.ts.map +1 -0
- package/dist/client/router-pipeline.d.ts +84 -0
- package/dist/client/router-pipeline.d.ts.map +1 -0
- package/dist/client/router-ref.d.ts +2 -2
- package/dist/client/router-ref.d.ts.map +1 -1
- package/dist/client/router-skew.d.ts +21 -0
- package/dist/client/router-skew.d.ts.map +1 -0
- package/dist/client/router-types.d.ts +207 -0
- package/dist/client/router-types.d.ts.map +1 -0
- package/dist/client/router.d.ts +1 -97
- package/dist/client/router.d.ts.map +1 -1
- package/dist/client/rsc-fetch.d.ts +113 -26
- package/dist/client/rsc-fetch.d.ts.map +1 -1
- package/dist/client/segment-cache.d.ts +107 -25
- package/dist/client/segment-cache.d.ts.map +1 -1
- package/dist/client/segment-outlet.d.ts +57 -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/slot-context.d.ts +31 -0
- package/dist/client/slot-context.d.ts.map +1 -0
- package/dist/client/slot-outlet.d.ts +16 -0
- package/dist/client/slot-outlet.d.ts.map +1 -0
- package/dist/client/slot-provider.d.ts +25 -0
- package/dist/client/slot-provider.d.ts.map +1 -0
- package/dist/client/ssr-data.d.ts +21 -5
- package/dist/client/ssr-data.d.ts.map +1 -1
- package/dist/client/stale-client.d.ts +69 -0
- package/dist/client/stale-client.d.ts.map +1 -0
- package/dist/client/state.d.ts +14 -4
- package/dist/client/state.d.ts.map +1 -1
- package/dist/client/top-loader.d.ts +7 -6
- package/dist/client/top-loader.d.ts.map +1 -1
- package/dist/client/unload-guard.d.ts +5 -0
- package/dist/client/unload-guard.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 +10 -4
- package/dist/client/use-query-states.d.ts.map +1 -1
- package/dist/client/use-router.d.ts +2 -2
- 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} +29 -16
- 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 +76 -0
- package/dist/codec.js.map +1 -0
- package/dist/config-types.d.ts +284 -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 +257 -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 +40 -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} +17 -3
- 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 +177 -0
- package/dist/fonts/pipeline.d.ts.map +1 -0
- package/dist/fonts/transform.d.ts +82 -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 +50 -181
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9805 -14134
- 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 +276 -0
- package/dist/plugin-context.d.ts.map +1 -0
- package/dist/plugins/adapter-build.d.ts +21 -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 +47 -10
- package/dist/plugins/build-report.d.ts.map +1 -1
- package/dist/plugins/cache.d.ts +64 -0
- package/dist/plugins/cache.d.ts.map +1 -0
- package/dist/plugins/callsite-ast.d.ts +117 -0
- package/dist/plugins/callsite-ast.d.ts.map +1 -0
- package/dist/plugins/callsite-jsx.d.ts +35 -0
- package/dist/plugins/callsite-jsx.d.ts.map +1 -0
- package/dist/plugins/chunks.d.ts +11 -4
- package/dist/plugins/chunks.d.ts.map +1 -1
- package/dist/plugins/client-chunks.d.ts +40 -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 +28 -4
- 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/prebuilt-capture.d.ts +60 -0
- package/dist/plugins/prebuilt-capture.d.ts.map +1 -0
- package/dist/plugins/prebuilt-options-analysis.d.ts +40 -0
- package/dist/plugins/prebuilt-options-analysis.d.ts.map +1 -0
- package/dist/plugins/prebuilt.d.ts +82 -0
- package/dist/plugins/prebuilt.d.ts.map +1 -0
- package/dist/plugins/prerender-sugar.d.ts +42 -0
- package/dist/plugins/prerender-sugar.d.ts.map +1 -0
- package/dist/plugins/request-dep/analysis.d.ts +106 -0
- package/dist/plugins/request-dep/analysis.d.ts.map +1 -0
- package/dist/plugins/request-dep/index.d.ts +75 -0
- package/dist/plugins/request-dep/index.d.ts.map +1 -0
- package/dist/plugins/request-dep/origin.d.ts +61 -0
- package/dist/plugins/request-dep/origin.d.ts.map +1 -0
- 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 +218 -21
- package/dist/plugins/static-build.d.ts.map +1 -1
- package/dist/routing/codegen-shared.d.ts +26 -0
- package/dist/routing/codegen-shared.d.ts.map +1 -0
- package/dist/routing/codegen-types.d.ts +61 -0
- package/dist/routing/codegen-types.d.ts.map +1 -0
- package/dist/routing/codegen-write.d.ts +51 -0
- package/dist/routing/codegen-write.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/collision-probe.d.ts +104 -0
- package/dist/routing/collision-probe.d.ts.map +1 -0
- package/dist/routing/collision-spaces.d.ts +26 -0
- package/dist/routing/collision-spaces.d.ts.map +1 -0
- package/dist/routing/convention-lint.d.ts +55 -0
- package/dist/routing/convention-lint.d.ts.map +1 -0
- package/dist/routing/export-detect.d.ts +72 -0
- package/dist/routing/export-detect.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 +5 -2
- package/dist/routing/interception.d.ts +234 -10
- package/dist/routing/interception.d.ts.map +1 -1
- package/dist/routing/link-codegen.d.ts +105 -0
- package/dist/routing/link-codegen.d.ts.map +1 -0
- package/dist/routing/manifest-codegen.d.ts +26 -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 +114 -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/segment-keys.d.ts +118 -0
- package/dist/routing/segment-keys.d.ts.map +1 -0
- package/dist/routing/slot-placement.d.ts +48 -0
- package/dist/routing/slot-placement.d.ts.map +1 -0
- package/dist/routing/types.d.ts +74 -26
- package/dist/routing/types.d.ts.map +1 -1
- package/dist/routing/walkers.d.ts +57 -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 +145 -0
- package/dist/schema-bridge.d.ts.map +1 -0
- package/dist/search-params/define.d.ts +262 -0
- package/dist/search-params/define.d.ts.map +1 -0
- package/dist/search-params/index.d.ts +3 -7
- package/dist/search-params/index.d.ts.map +1 -1
- package/dist/search-params/index.js +179 -360
- package/dist/search-params/index.js.map +1 -1
- package/dist/search-params/parse-total.d.ts +81 -0
- package/dist/search-params/parse-total.d.ts.map +1 -0
- package/dist/search-params/serialize-equal.d.ts +9 -0
- package/dist/search-params/serialize-equal.d.ts.map +1 -0
- package/dist/search-params/wrappers.d.ts +76 -0
- package/dist/search-params/wrappers.d.ts.map +1 -0
- package/dist/server/access-gate.d.ts +26 -10
- package/dist/server/access-gate.d.ts.map +1 -1
- package/dist/server/action-client.d.ts +42 -7
- 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 +12 -33
- package/dist/server/actions.d.ts.map +1 -1
- package/dist/server/als-registry.d.ts +115 -11
- package/dist/server/als-registry.d.ts.map +1 -1
- package/dist/server/asset-headers.d.ts +8 -18
- 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 +25 -30
- 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/chain-url-parts.d.ts +82 -0
- package/dist/server/chain-url-parts.d.ts.map +1 -0
- package/dist/server/children-interception.d.ts +49 -0
- package/dist/server/children-interception.d.ts.map +1 -0
- package/dist/server/coalesce-tick.d.ts +40 -0
- package/dist/server/coalesce-tick.d.ts.map +1 -0
- package/dist/server/compress.d.ts.map +1 -1
- 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 +65 -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/default-status-page.d.ts +45 -0
- package/dist/server/default-status-page.d.ts.map +1 -0
- package/dist/server/deny-boundary.d.ts +247 -0
- package/dist/server/deny-boundary.d.ts.map +1 -0
- package/dist/server/deny-renderer.d.ts +16 -5
- 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 +86 -10
- 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 +41 -0
- package/dist/server/form-data.d.ts.map +1 -1
- package/dist/server/head-response.d.ts +35 -0
- package/dist/server/head-response.d.ts.map +1 -0
- package/dist/server/html-injector-core.d.ts +242 -0
- package/dist/server/html-injector-core.d.ts.map +1 -0
- package/dist/server/html-injectors.d.ts +82 -41
- package/dist/server/html-injectors.d.ts.map +1 -1
- package/dist/server/index.d.ts +11 -47
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +183 -2906
- package/dist/server/index.js.map +1 -1
- package/dist/server/internal.d.ts +51 -0
- package/dist/server/internal.d.ts.map +1 -0
- package/dist/server/internal.js +4154 -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-collector.d.ts +74 -0
- package/dist/server/metadata-collector.d.ts.map +1 -0
- package/dist/server/metadata-routes.d.ts +60 -11
- package/dist/server/metadata-routes.d.ts.map +1 -1
- package/dist/server/metadata.d.ts +8 -0
- package/dist/server/metadata.d.ts.map +1 -1
- package/dist/server/middleware-runner.d.ts +19 -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 +71 -0
- package/dist/server/param-coercion.d.ts.map +1 -0
- package/dist/server/pipeline-helpers.d.ts +77 -0
- package/dist/server/pipeline-helpers.d.ts.map +1 -0
- package/dist/server/pipeline-interception.d.ts +59 -9
- 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 +59 -0
- package/dist/server/pipeline-phases.d.ts.map +1 -0
- package/dist/server/pipeline.d.ts +152 -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/prebuilt/cache-key.d.ts +63 -0
- package/dist/server/prebuilt/cache-key.d.ts.map +1 -0
- package/dist/server/prebuilt/capture-state.d.ts +57 -0
- package/dist/server/prebuilt/capture-state.d.ts.map +1 -0
- package/dist/server/prebuilt/key-discipline.d.ts +23 -0
- package/dist/server/prebuilt/key-discipline.d.ts.map +1 -0
- package/dist/server/prebuilt/manifest-tag-index.d.ts +27 -0
- package/dist/server/prebuilt/manifest-tag-index.d.ts.map +1 -0
- package/dist/server/prebuilt/overlay.d.ts +100 -0
- package/dist/server/prebuilt/overlay.d.ts.map +1 -0
- package/dist/server/prebuilt/payload-source.d.ts +79 -0
- package/dist/server/prebuilt/payload-source.d.ts.map +1 -0
- package/dist/server/prebuilt/slots.d.ts +99 -0
- package/dist/server/prebuilt/slots.d.ts.map +1 -0
- package/dist/server/prebuilt/synthetic-store.d.ts +67 -0
- package/dist/server/prebuilt/synthetic-store.d.ts.map +1 -0
- package/dist/server/prebuilt-builder.d.ts +121 -0
- package/dist/server/prebuilt-builder.d.ts.map +1 -0
- package/dist/server/prebuilt-runtime.d.ts +111 -0
- package/dist/server/prebuilt-runtime.d.ts.map +1 -0
- package/dist/server/primitives.d.ts +100 -44
- package/dist/server/primitives.d.ts.map +1 -1
- package/dist/server/publish-params.d.ts +33 -0
- package/dist/server/publish-params.d.ts.map +1 -0
- 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 +110 -106
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/request-dep.d.ts +15 -0
- package/dist/server/request-dep.d.ts.map +1 -0
- package/dist/server/route-element-builder.d.ts +74 -27
- 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 +38 -36
- package/dist/server/route-matcher.d.ts.map +1 -1
- package/dist/server/rsc-cache-key-guard.d.ts +78 -0
- package/dist/server/rsc-cache-key-guard.d.ts.map +1 -0
- 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/deny-fallback.d.ts +29 -0
- package/dist/server/rsc-entry/deny-fallback.d.ts.map +1 -0
- package/dist/server/rsc-entry/error-renderer.d.ts +38 -13
- package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/helpers.d.ts +59 -42
- package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
- package/dist/server/rsc-entry/index.d.ts +39 -6
- package/dist/server/rsc-entry/index.d.ts.map +1 -1
- package/dist/server/rsc-entry/render-route.d.ts +51 -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 +5 -6
- package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
- package/dist/server/rsc-entry/rsc-stream.d.ts +40 -3
- 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 +36 -4
- package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/wrap-action-dispatch.d.ts +89 -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 +130 -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/skippable-prefix.d.ts +26 -0
- package/dist/server/skippable-prefix.d.ts.map +1 -0
- package/dist/server/slot-interception.d.ts +80 -0
- package/dist/server/slot-interception.d.ts.map +1 -0
- package/dist/server/slot-resolver.d.ts +139 -5
- package/dist/server/slot-resolver.d.ts.map +1 -1
- package/dist/server/ssr-bridge-types.d.ts +140 -0
- package/dist/server/ssr-bridge-types.d.ts.map +1 -0
- package/dist/server/ssr-entry.d.ts +1 -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 +61 -0
- package/dist/server/ssr-wrappers.d.ts.map +1 -0
- package/dist/server/state-tree-diff.d.ts +44 -9
- package/dist/server/state-tree-diff.d.ts.map +1 -1
- package/dist/server/static-generator.d.ts +112 -0
- package/dist/server/static-generator.d.ts.map +1 -0
- package/dist/server/static-not-found.d.ts +52 -0
- package/dist/server/static-not-found.d.ts.map +1 -0
- package/dist/server/status-code-resolver.d.ts +26 -15
- package/dist/server/status-code-resolver.d.ts.map +1 -1
- package/dist/server/stream-utils.d.ts +47 -0
- package/dist/server/stream-utils.d.ts.map +1 -0
- package/dist/server/tracing.d.ts +44 -9
- package/dist/server/tracing.d.ts.map +1 -1
- package/dist/server/tree-builder.d.ts +66 -42
- 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 +77 -6
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/utils/element-type.d.ts +40 -0
- package/dist/server/utils/element-type.d.ts.map +1 -0
- 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/server/workers-cache-bridge.d.ts +26 -0
- package/dist/server/workers-cache-bridge.d.ts.map +1 -0
- package/dist/shared/als-slots.d.ts +42 -0
- package/dist/shared/als-slots.d.ts.map +1 -0
- package/dist/shared/base-path.d.ts +56 -0
- package/dist/shared/base-path.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/param-value.d.ts +104 -0
- package/dist/shared/param-value.d.ts.map +1 -0
- package/dist/shared/payload-root.d.ts +109 -0
- package/dist/shared/payload-root.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/shared/rsc-cache-key.d.ts +163 -0
- package/dist/shared/rsc-cache-key.d.ts.map +1 -0
- package/dist/shared/rsc-error-envelope.d.ts +25 -0
- package/dist/shared/rsc-error-envelope.d.ts.map +1 -0
- package/dist/shared/rsc-manifest.d.ts +28 -0
- package/dist/shared/rsc-manifest.d.ts.map +1 -0
- package/dist/shared/rsc-media-type.d.ts +40 -0
- package/dist/shared/rsc-media-type.d.ts.map +1 -0
- package/dist/shared/rsc-payload-path.d.ts +42 -0
- package/dist/shared/rsc-payload-path.d.ts.map +1 -0
- package/dist/shared/segment-info.d.ts +66 -0
- package/dist/shared/segment-info.d.ts.map +1 -0
- package/dist/shared/slot-params.d.ts +52 -0
- package/dist/shared/slot-params.d.ts.map +1 -0
- package/dist/shared/static-platform-files.d.ts +71 -0
- package/dist/shared/static-platform-files.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 +120 -120
- package/dist/shims/image.d.ts.map +1 -1
- package/dist/shims/navigation-client.d.ts +25 -12
- package/dist/shims/navigation-client.d.ts.map +1 -1
- package/dist/shims/navigation.d.ts +10 -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/docs/api/30-api-server.mdx +233 -0
- package/docs/api/31-api-client.mdx +163 -0
- package/docs/api/32-api-cache.mdx +311 -0
- package/docs/api/33-api-search-params.mdx +176 -0
- package/docs/api/34-api-config.mdx +325 -0
- package/docs/api/35-api-typescript.mdx +170 -0
- package/docs/api/36-cli.mdx +170 -0
- package/docs/learn/00-introduction.mdx +109 -0
- package/docs/learn/01-quick-start.mdx +94 -0
- package/docs/learn/02-pages-and-layouts.mdx +147 -0
- package/docs/learn/03-fetching-data.mdx +211 -0
- package/docs/learn/03b-access-control.mdx +130 -0
- package/docs/learn/04-loading-states.mdx +67 -0
- package/docs/learn/04b-the-flush-point.mdx +115 -0
- package/docs/learn/05-typed-params.mdx +275 -0
- package/docs/learn/06-forms-and-actions.mdx +146 -0
- package/docs/learn/07-typed-routes.mdx +132 -0
- package/docs/learn/08-streaming.mdx +146 -0
- package/docs/learn/09-caching.mdx +252 -0
- package/docs/learn/10-middleware.mdx +157 -0
- package/docs/learn/11-error-handling.mdx +173 -0
- package/docs/learn/12-client-navigation.mdx +176 -0
- package/docs/learn/13-configuration.mdx +166 -0
- package/docs/learn/14-deploying.mdx +287 -0
- package/docs/more/01-advanced-routing.mdx +343 -0
- package/docs/more/02-advanced-forms.mdx +137 -0
- package/docs/more/03-coming-from-nextjs.mdx +186 -0
- package/docs/more/04-metadata-and-fonts.mdx +193 -0
- package/docs/more/04b-mdx.mdx +209 -0
- package/docs/more/05-content-collections.mdx +90 -0
- package/docs/more/06-instrumentation.mdx +214 -0
- package/docs/more/07-security.mdx +129 -0
- package/docs/more/08-developer-experience.mdx +134 -0
- package/docs/more/40-why-timber.mdx +50 -0
- package/docs/more/41-timber-vs-nextjs.mdx +81 -0
- package/docs/more/42-timber-vs-others.mdx +68 -0
- package/docs/more/50-ai-agent-instructions.mdx +171 -0
- package/llms.txt +55 -0
- package/package.json +108 -26
- package/src/adapters/build-output-helper.ts +351 -0
- package/src/adapters/cloudflare-dev.ts +177 -0
- package/src/adapters/cloudflare-kv-cache.ts +204 -0
- package/src/adapters/cloudflare.ts +740 -129
- package/src/adapters/compress-module.ts +101 -88
- package/src/adapters/fs-identity.ts +156 -0
- package/src/adapters/nitro.ts +320 -120
- package/src/adapters/raw-imports.d.ts +5 -0
- package/src/adapters/shared.ts +274 -0
- package/src/adapters/types.ts +28 -7
- package/src/adapters/wrangler.d.ts +7 -0
- package/src/cache/cache-api.ts +107 -0
- package/src/cache/fast-hash.ts +5 -0
- package/src/cache/handler-store.ts +76 -0
- package/src/cache/index.ts +114 -21
- package/src/cache/invalidation-epoch.ts +93 -0
- package/src/cache/json-lossy-check.ts +75 -0
- package/src/cache/redis-handler.ts +197 -19
- package/src/cache/singleflight.ts +64 -6
- package/src/cache/sizeof.ts +33 -0
- package/src/cache/stable-stringify.ts +65 -2
- package/src/cache/store.ts +71 -0
- package/src/cache/stores/cloudflare-kv.ts +52 -0
- package/src/cache/stores/memory.ts +125 -0
- package/src/cache/stores/redis.ts +97 -0
- package/src/cache/stores/vercel.ts +59 -0
- package/src/cache/tag-aware-handler.ts +237 -0
- package/src/cache/timber-cache.ts +161 -36
- package/src/cdn/cloudflare-purge.ts +50 -0
- package/src/cdn/fastly-purge.ts +63 -0
- package/src/cdn/headers.ts +153 -0
- package/src/cdn/index.ts +17 -0
- package/src/cdn/purge-store.ts +34 -0
- package/src/cdn/workers-cache-purge.ts +30 -0
- package/src/cli-check.ts +458 -0
- package/src/cli-schema-sync.ts +401 -0
- package/src/cli.ts +221 -53
- package/src/client/browser-dev.ts +156 -1
- package/src/client/browser-entry/action-dispatch.ts +130 -0
- package/src/client/browser-entry/hmr.ts +70 -0
- package/src/client/browser-entry/hydrate.ts +198 -0
- package/src/client/browser-entry/index.ts +121 -0
- package/src/client/browser-entry/post-hydration.ts +122 -0
- package/src/client/browser-entry/router-init.ts +342 -0
- package/src/client/browser-entry/rsc-stream.ts +166 -0
- package/src/client/browser-entry/scroll.ts +50 -0
- package/src/client/error-boundary.tsx +210 -36
- package/src/client/error-reconstituter.tsx +79 -0
- package/src/client/form.tsx +31 -32
- package/src/client/history.ts +29 -7
- package/src/client/index.ts +78 -45
- package/src/client/internal.ts +59 -0
- package/src/client/link.tsx +397 -150
- package/src/client/navigation-api.ts +345 -0
- package/src/client/navigation-commit.ts +197 -0
- package/src/client/navigation-context.ts +43 -62
- package/src/client/navigation-root.tsx +580 -0
- package/src/client/nuqs-adapter.tsx +16 -3
- package/src/client/params-context.ts +192 -0
- package/src/client/router-effects.ts +231 -0
- package/src/client/router-lifecycle.ts +288 -0
- package/src/client/router-pipeline.ts +393 -0
- package/src/client/router-ref.ts +2 -2
- package/src/client/router-skew.ts +30 -0
- package/src/client/router-types.ts +230 -0
- package/src/client/router.ts +339 -410
- package/src/client/rsc-fetch.ts +530 -73
- package/src/client/segment-cache.ts +224 -38
- package/src/client/segment-outlet.tsx +141 -0
- package/src/client/segment-update-context.ts +42 -0
- package/src/client/shallow-url.ts +22 -0
- package/src/client/slot-context.ts +50 -0
- package/src/client/slot-outlet.tsx +22 -0
- package/src/client/slot-provider.tsx +32 -0
- package/src/client/ssr-data.ts +21 -6
- package/src/client/stale-client.ts +191 -0
- package/src/client/state.ts +19 -5
- package/src/client/top-loader.tsx +13 -10
- package/src/client/unload-guard.ts +34 -2
- package/src/client/use-cookie.ts +69 -17
- 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 +206 -36
- package/src/client/use-router.ts +5 -2
- package/src/client/use-search-params.ts +31 -44
- package/src/client/{use-params.ts → use-segment-params.ts} +52 -25
- package/src/codec.ts +149 -0
- package/src/config-types.ts +282 -0
- package/src/config-validation.ts +330 -0
- package/src/content/index.ts +5 -13
- package/src/cookies/define-cookie.ts +222 -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 +55 -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/{server/dev-logger.ts → dev-tools/logger.ts} +33 -51
- package/src/{plugins/dev-logs.ts → dev-tools/logs.ts} +122 -26
- package/src/dev-tools/overlay.ts +469 -0
- package/src/dev-tools/stack-classifier.ts +75 -0
- package/src/dev-tools/terminal.ts +182 -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 +100 -18
- package/src/fonts/local.ts +9 -8
- package/src/fonts/paths.ts +58 -0
- package/src/fonts/pipeline.ts +348 -0
- package/src/fonts/transform.ts +311 -0
- package/src/fonts/types.ts +52 -1
- package/src/fonts/virtual-modules.ts +179 -0
- package/src/index.ts +468 -353
- 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 +503 -0
- package/src/plugins/adapter-build.ts +229 -7
- package/src/plugins/build-manifest.ts +201 -26
- package/src/plugins/build-report.ts +259 -47
- package/src/plugins/cache.ts +243 -0
- package/src/plugins/callsite-ast.ts +472 -0
- package/src/plugins/callsite-jsx.ts +243 -0
- package/src/plugins/chunks.ts +74 -5
- package/src/plugins/client-chunks.ts +185 -0
- package/src/plugins/cloudflare-wasm.ts +141 -0
- package/src/plugins/content.ts +1 -1
- package/src/plugins/dev-server.ts +284 -94
- package/src/plugins/entries.ts +138 -16
- package/src/plugins/fonts.ts +228 -660
- package/src/plugins/mdx.ts +47 -10
- package/src/plugins/prebuilt-capture.ts +217 -0
- package/src/plugins/prebuilt-options-analysis.ts +175 -0
- package/src/plugins/prebuilt.ts +655 -0
- package/src/plugins/prerender-sugar.ts +328 -0
- package/src/plugins/request-dep/analysis.ts +447 -0
- package/src/plugins/request-dep/index.ts +376 -0
- package/src/plugins/request-dep/origin.ts +310 -0
- package/src/plugins/routing.ts +268 -277
- package/src/plugins/server-bundle.ts +89 -12
- package/src/plugins/shims.ts +240 -64
- package/src/plugins/static-build.ts +704 -66
- package/src/routing/codegen-shared.ts +39 -0
- package/src/routing/codegen-types.ts +62 -0
- package/src/routing/codegen-write.ts +139 -0
- package/src/routing/codegen.ts +339 -231
- package/src/routing/collision-probe.ts +438 -0
- package/src/routing/collision-spaces.ts +281 -0
- package/src/routing/convention-lint.ts +493 -0
- package/src/routing/export-detect.ts +448 -0
- package/src/routing/file-cache.ts +23 -0
- package/src/routing/index.ts +10 -1
- package/src/routing/interception.ts +894 -67
- package/src/routing/link-codegen.ts +280 -0
- package/src/routing/manifest-codegen.ts +226 -0
- package/src/routing/scanner.ts +368 -218
- package/src/routing/schema-validation.ts +155 -0
- package/src/routing/segment-classify.ts +280 -0
- package/src/routing/segment-codegen.ts +98 -0
- package/src/routing/segment-keys.ts +186 -0
- package/src/routing/slot-placement.ts +97 -0
- package/src/routing/types.ts +75 -26
- package/src/routing/walkers.ts +98 -0
- package/src/rsc-runtime/rsc.ts +9 -0
- package/src/rsc-runtime/ssr.ts +50 -0
- package/src/rsc-runtime/vendor-types.d.ts +7 -0
- package/src/schema-bridge.ts +380 -0
- package/src/search-params/define.ts +677 -0
- package/src/search-params/index.ts +14 -20
- package/src/search-params/parse-total.ts +91 -0
- package/src/search-params/serialize-equal.ts +14 -0
- package/src/search-params/wrappers.ts +150 -0
- package/src/server/access-gate.tsx +121 -51
- package/src/server/action-client.ts +120 -29
- package/src/server/action-encryption.ts +144 -0
- package/src/server/action-handler.ts +230 -43
- package/src/server/actions.ts +54 -57
- package/src/server/als-registry.ts +159 -20
- package/src/server/asset-headers.ts +15 -37
- package/src/server/body-limits.ts +10 -2
- package/src/server/build-manifest.ts +33 -57
- package/src/server/canonicalize.ts +6 -3
- package/src/server/chain-url-parts.ts +163 -0
- package/src/server/children-interception.ts +115 -0
- package/src/server/coalesce-tick.ts +75 -0
- package/src/server/compress.ts +43 -8
- package/src/server/cookie-context.ts +484 -0
- package/src/server/cookie-parsing.ts +163 -0
- package/src/server/csrf.ts +39 -6
- package/src/server/default-logger.ts +99 -0
- package/src/server/default-status-page.ts +127 -0
- package/src/server/deny-boundary.ts +516 -0
- package/src/server/deny-renderer.ts +181 -101
- 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 +170 -44
- 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 +124 -12
- package/src/server/head-response.ts +54 -0
- package/src/server/html-injector-core.ts +495 -0
- package/src/server/html-injectors.ts +271 -254
- package/src/server/index.ts +32 -184
- package/src/server/internal.ts +181 -0
- package/src/server/logger.ts +72 -36
- package/src/server/metadata-collector.ts +189 -0
- package/src/server/metadata-routes.ts +205 -24
- package/src/server/metadata.ts +21 -0
- package/src/server/middleware-runner.ts +31 -4
- package/src/server/node-stream-transforms.ts +336 -0
- package/src/server/param-coercion.ts +189 -0
- package/src/server/pipeline-helpers.ts +159 -0
- package/src/server/pipeline-interception.ts +109 -33
- package/src/server/pipeline-metadata.ts +14 -0
- package/src/server/pipeline-outcome.ts +196 -0
- package/src/server/pipeline-phases.ts +599 -0
- package/src/server/pipeline.ts +322 -382
- package/src/server/port-resolution.ts +215 -0
- package/src/server/prebuilt/cache-key.ts +299 -0
- package/src/server/prebuilt/capture-state.ts +89 -0
- package/src/server/prebuilt/key-discipline.ts +53 -0
- package/src/server/prebuilt/manifest-tag-index.ts +46 -0
- package/src/server/prebuilt/overlay.ts +256 -0
- package/src/server/prebuilt/payload-source.ts +202 -0
- package/src/server/prebuilt/slots.ts +190 -0
- package/src/server/prebuilt/synthetic-store.ts +122 -0
- package/src/server/prebuilt-builder.ts +804 -0
- package/src/server/prebuilt-runtime.ts +817 -0
- package/src/server/primitives.ts +174 -90
- package/src/server/publish-params.ts +42 -0
- package/src/server/render-timeout.ts +108 -0
- package/src/server/render-utils.ts +31 -0
- package/src/server/request-context.ts +243 -333
- package/src/server/request-dep.ts +37 -0
- package/src/server/route-element-builder.ts +666 -308
- package/src/server/route-handler.ts +39 -12
- package/src/server/route-matcher.ts +162 -269
- package/src/server/rsc-cache-key-guard.ts +164 -0
- package/src/server/rsc-entry/action-middleware-runner.ts +167 -0
- package/src/server/rsc-entry/api-handler.ts +67 -32
- package/src/server/rsc-entry/deny-fallback.ts +93 -0
- package/src/server/rsc-entry/error-renderer.ts +370 -94
- package/src/server/rsc-entry/helpers.ts +226 -95
- package/src/server/rsc-entry/index.ts +357 -330
- package/src/server/rsc-entry/render-route.ts +308 -0
- package/src/server/rsc-entry/revalidate-renderer.ts +350 -0
- package/src/server/rsc-entry/rsc-payload.ts +188 -55
- package/src/server/rsc-entry/rsc-stream.ts +122 -18
- package/src/server/rsc-entry/ssr-bridge.ts +18 -5
- package/src/server/rsc-entry/ssr-renderer.ts +299 -80
- package/src/server/rsc-entry/wrap-action-dispatch.ts +186 -0
- package/src/server/safe-load.ts +60 -0
- package/src/server/sensitive-fields.ts +230 -0
- package/src/server/server-only-guard-noop.js +3 -0
- package/src/server/sitemap-generator.ts +337 -0
- package/src/server/sitemap-handler.ts +157 -0
- package/src/server/skippable-prefix.ts +74 -0
- package/src/server/slot-interception.ts +168 -0
- package/src/server/slot-resolver.ts +678 -294
- package/src/server/ssr-bridge-types.ts +145 -0
- package/src/server/ssr-entry.ts +216 -78
- package/src/server/ssr-render.ts +345 -82
- package/src/server/ssr-wrappers.tsx +142 -0
- package/src/server/state-tree-diff.ts +85 -30
- package/src/server/static-generator.ts +715 -0
- package/src/server/static-not-found.ts +134 -0
- package/src/server/status-code-resolver.ts +107 -148
- package/src/server/stream-utils.ts +288 -0
- package/src/server/tracing.ts +126 -14
- package/src/server/tree-builder.ts +99 -168
- package/src/server/tree-match.ts +262 -0
- package/src/server/types.ts +84 -9
- package/src/server/utils/element-type.ts +72 -0
- 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/server/workers-cache-bridge.ts +33 -0
- package/src/shared/als-slots.ts +74 -0
- package/src/shared/base-path.ts +80 -0
- package/src/shared/href-validation.ts +159 -0
- package/src/shared/merge-search-params.ts +55 -0
- package/src/shared/param-value.ts +281 -0
- package/src/shared/payload-root.ts +152 -0
- package/src/shared/redirect-type.ts +17 -0
- package/src/shared/rsc-cache-key.ts +269 -0
- package/src/shared/rsc-error-envelope.ts +31 -0
- package/src/shared/rsc-manifest.ts +29 -0
- package/src/shared/rsc-media-type.ts +43 -0
- package/src/shared/rsc-payload-path.ts +45 -0
- package/src/shared/segment-info.ts +67 -0
- package/src/shared/slot-params.ts +110 -0
- package/src/shared/static-platform-files.ts +75 -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 +36 -32
- package/src/shims/navigation.ts +10 -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 +0 -153
- 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 +0 -109
- package/dist/_chunks/use-query-states-D5KaffOK.js.map +0 -1
- package/dist/adapters/cloudflare.js.map +0 -1
- package/dist/cache/index.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/error-boundary.js.map +0 -1
- package/dist/client/head.d.ts +0 -16
- package/dist/client/head.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/search-params/registry.d.ts +0 -20
- package/dist/search-params/registry.d.ts.map +0 -1
- package/dist/server/client-module-map.d.ts +0 -47
- package/dist/server/client-module-map.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/head.ts +0 -61
- 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/search-params/registry.ts +0 -31
- package/src/server/client-module-map.ts +0 -58
- 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/dist/client/index.js
CHANGED
|
@@ -1,21 +1,25 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
2
|
+
import { n as classifyUrlSegment } from "../_chunks/segment-classify-C539Pa2O.js";
|
|
3
|
+
import { a as mergePreservedSearchParams, i as validateNavigationHref, n as isInternalHref } from "../_chunks/href-validation-CMc5JRls.js";
|
|
4
|
+
import { n as getSsrData } from "../_chunks/ssr-data-14MXm7Pj.js";
|
|
5
|
+
import { n as getRouterOrNull } from "../_chunks/router-ref-DuYuV_0Q.js";
|
|
6
|
+
import { n as useSegmentContext } from "../_chunks/segment-context-CjOlyB8Y.js";
|
|
7
|
+
import { t as getLinkCodec } from "../_chunks/codec-registry-oOUxugz3.js";
|
|
8
|
+
import { l as useNavigationContext, r as useSegmentParams, u as usePendingNavigation } from "../_chunks/use-segment-params-C4r4BD9T.js";
|
|
9
|
+
import { n as useQueryStates } from "../_chunks/use-query-states-I3JMng6J.js";
|
|
10
|
+
import { createContext, useActionState as useActionState$1, useContext, useRef, useState, useTransition } from "react";
|
|
7
11
|
import { jsx } from "react/jsx-runtime";
|
|
8
12
|
//#region src/client/use-link-status.ts
|
|
9
13
|
/**
|
|
10
14
|
* React context provided by <Link>. Holds the pending status
|
|
11
15
|
* for that specific link's navigation.
|
|
12
16
|
*/
|
|
13
|
-
var LinkStatusContext = createContext({
|
|
17
|
+
var LinkStatusContext = createContext({ isPending: false });
|
|
14
18
|
/**
|
|
15
|
-
* Returns `{
|
|
19
|
+
* Returns `{ isPending: true }` while the nearest parent `<Link>` component's
|
|
16
20
|
* navigation is in flight. Must be used inside a `<Link>` component's children.
|
|
17
21
|
*
|
|
18
|
-
* Unlike `
|
|
22
|
+
* Unlike `usePendingNavigation()` which is global, this hook is scoped to
|
|
19
23
|
* the nearest parent `<Link>` — only the link the user clicked shows pending.
|
|
20
24
|
*
|
|
21
25
|
* ```tsx
|
|
@@ -23,8 +27,8 @@ var LinkStatusContext = createContext({ pending: false });
|
|
|
23
27
|
* import { Link, useLinkStatus } from '@timber-js/app/client'
|
|
24
28
|
*
|
|
25
29
|
* function Hint() {
|
|
26
|
-
* const {
|
|
27
|
-
* return <span className={
|
|
30
|
+
* const { isPending } = useLinkStatus()
|
|
31
|
+
* return <span className={isPending ? 'opacity-50' : ''} />
|
|
28
32
|
* }
|
|
29
33
|
*
|
|
30
34
|
* export function NavLink({ href, children }) {
|
|
@@ -40,247 +44,135 @@ function useLinkStatus() {
|
|
|
40
44
|
return useContext(LinkStatusContext);
|
|
41
45
|
}
|
|
42
46
|
//#endregion
|
|
43
|
-
//#region src/client/
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
*
|
|
47
|
-
* Holds the current route params and pathname, updated atomically
|
|
48
|
-
* with the RSC tree on each navigation. This replaces the previous
|
|
49
|
-
* useSyncExternalStore approach for useParams() and usePathname(),
|
|
50
|
-
* which suffered from a timing gap: the new tree could commit before
|
|
51
|
-
* the external store re-renders fired, causing a frame where both
|
|
52
|
-
* old and new active states were visible simultaneously.
|
|
53
|
-
*
|
|
54
|
-
* By wrapping the RSC payload element in NavigationProvider inside
|
|
55
|
-
* renderRoot(), the context value and the element tree are passed to
|
|
56
|
-
* reactRoot.render() in the same call — atomic by construction.
|
|
57
|
-
* All consumers (useParams, usePathname) see the new values in the
|
|
58
|
-
* same render pass as the new tree.
|
|
59
|
-
*
|
|
60
|
-
* During SSR, no NavigationProvider is mounted. Hooks fall back to
|
|
61
|
-
* the ALS-backed getSsrData() for per-request isolation.
|
|
62
|
-
*
|
|
63
|
-
* IMPORTANT: createContext and useContext are NOT available in the RSC
|
|
64
|
-
* environment (React Server Components use a stripped-down React).
|
|
65
|
-
* The context is lazily initialized on first access, and all functions
|
|
66
|
-
* that depend on these APIs are safe to call from any environment —
|
|
67
|
-
* they return null or no-op when the APIs aren't available.
|
|
68
|
-
*
|
|
69
|
-
* SINGLETON GUARANTEE: All shared mutable state uses globalThis via
|
|
70
|
-
* Symbol.for keys. The RSC client bundler can duplicate this module
|
|
71
|
-
* across chunks (browser-entry graph + client-reference graph). With
|
|
72
|
-
* ESM output, each chunk gets its own module scope — module-level
|
|
73
|
-
* variables would create separate singleton instances per chunk.
|
|
74
|
-
* globalThis guarantees a single instance regardless of duplication.
|
|
75
|
-
*
|
|
76
|
-
* This workaround will be removed when Rolldown ships `format: 'app'`
|
|
77
|
-
* (module registry format that deduplicates like webpack/Turbopack).
|
|
78
|
-
* See design/27-chunking-strategy.md.
|
|
79
|
-
*
|
|
80
|
-
* See design/19-client-navigation.md §"NavigationContext"
|
|
81
|
-
*/
|
|
82
|
-
/**
|
|
83
|
-
* The context is created lazily to avoid calling createContext at module
|
|
84
|
-
* level. In the RSC environment, React.createContext doesn't exist —
|
|
85
|
-
* calling it at import time would crash the server.
|
|
86
|
-
*
|
|
87
|
-
* Context instances are stored on globalThis (NOT in module-level
|
|
88
|
-
* variables) because the ESM bundler can duplicate this module across
|
|
89
|
-
* chunks. Module-level variables would create separate instances per
|
|
90
|
-
* chunk — the provider in TransitionRoot (index chunk) would use
|
|
91
|
-
* context A while the consumer in LinkStatusProvider (shared chunk)
|
|
92
|
-
* reads from context B. globalThis guarantees a single instance.
|
|
93
|
-
*
|
|
94
|
-
* See design/27-chunking-strategy.md §"Singleton Safety"
|
|
95
|
-
*/
|
|
96
|
-
var NAV_CTX_KEY = Symbol.for("__timber_nav_ctx");
|
|
97
|
-
var PENDING_CTX_KEY = Symbol.for("__timber_pending_nav_ctx");
|
|
98
|
-
function getOrCreateContext() {
|
|
99
|
-
const existing = globalThis[NAV_CTX_KEY];
|
|
100
|
-
if (existing !== void 0) return existing;
|
|
101
|
-
if (typeof React.createContext === "function") {
|
|
102
|
-
const ctx = React.createContext(null);
|
|
103
|
-
globalThis[NAV_CTX_KEY] = ctx;
|
|
104
|
-
return ctx;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
47
|
+
//#region src/client/link.tsx
|
|
48
|
+
var LINK_PENDING = { isPending: true };
|
|
49
|
+
var LINK_IDLE = { isPending: false };
|
|
107
50
|
/**
|
|
108
|
-
* Read the
|
|
109
|
-
*
|
|
110
|
-
*
|
|
51
|
+
* Read the current URL's search string without requiring a React hook.
|
|
52
|
+
* On the client, reads window.location.search. During SSR, reads from
|
|
53
|
+
* the request context (getSsrData). Returns empty string if unavailable.
|
|
111
54
|
*/
|
|
112
|
-
function
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
if (
|
|
116
|
-
|
|
55
|
+
function getCurrentSearch() {
|
|
56
|
+
if (typeof window !== "undefined") return window.location.search;
|
|
57
|
+
const data = getSsrData();
|
|
58
|
+
if (!data) return "";
|
|
59
|
+
const str = new URLSearchParams(data.searchParams).toString();
|
|
60
|
+
return str ? `?${str}` : "";
|
|
117
61
|
}
|
|
118
62
|
/**
|
|
119
|
-
*
|
|
63
|
+
* Interpolate dynamic segments in a route pattern with actual values.
|
|
64
|
+
* e.g. interpolateParams("/products/[id]", { id: "123" }) → "/products/123"
|
|
120
65
|
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
66
|
+
* Supports:
|
|
67
|
+
* - [param] → single segment
|
|
68
|
+
* - [...param] → catch-all (joined with /)
|
|
69
|
+
* - [[...param]] → optional catch-all (omitted if undefined/empty)
|
|
123
70
|
*/
|
|
124
|
-
function NavigationProvider({ value, children }) {
|
|
125
|
-
const ctx = getOrCreateContext();
|
|
126
|
-
if (!ctx) return children;
|
|
127
|
-
return createElement(ctx.Provider, { value }, children);
|
|
128
|
-
}
|
|
129
71
|
/**
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
* The router calls setNavigationState() before renderRoot(). The
|
|
133
|
-
* renderRoot callback reads via getNavigationState() to create the
|
|
134
|
-
* NavigationProvider with the correct params/pathname.
|
|
135
|
-
*
|
|
136
|
-
* This is NOT used by hooks directly — hooks read from React context.
|
|
137
|
-
*
|
|
138
|
-
* Stored on globalThis (like the context instances above) because the
|
|
139
|
-
* router lives in one chunk while renderRoot lives in another. Module-
|
|
140
|
-
* level variables would be separate per chunk.
|
|
72
|
+
* Parse a route pattern's path portion into classified segments.
|
|
73
|
+
* Exported for testing. Uses the shared character-based classifier.
|
|
141
74
|
*/
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
const g = globalThis;
|
|
145
|
-
if (!g[NAV_STATE_KEY]) g[NAV_STATE_KEY] = { current: {
|
|
146
|
-
params: {},
|
|
147
|
-
pathname: "/"
|
|
148
|
-
} };
|
|
149
|
-
return g[NAV_STATE_KEY];
|
|
150
|
-
}
|
|
151
|
-
function setNavigationState(state) {
|
|
152
|
-
_getNavStateStore().current = state;
|
|
153
|
-
}
|
|
154
|
-
function getNavigationState() {
|
|
155
|
-
return _getNavStateStore().current;
|
|
75
|
+
function parseSegments(pattern) {
|
|
76
|
+
return pattern.split("/").filter(Boolean).map(classifyUrlSegment);
|
|
156
77
|
}
|
|
157
78
|
/**
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
* and useNavigationPending.
|
|
79
|
+
* Resolve a single classified segment into its string representation.
|
|
80
|
+
* Returns null for optional catch-all with no value (filtered out before join).
|
|
161
81
|
*
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
* level variables would create separate context instances.
|
|
82
|
+
* When schema codecs are registered (via virtual:timber-schema), uses
|
|
83
|
+
* codec.serialize() for URL construction instead of plain String().
|
|
165
84
|
*/
|
|
166
|
-
function
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
85
|
+
function resolveSegment(seg, params, pattern) {
|
|
86
|
+
switch (seg.kind) {
|
|
87
|
+
case "static": return seg.value;
|
|
88
|
+
case "optional-catch-all": {
|
|
89
|
+
const value = params[seg.name];
|
|
90
|
+
if (value === void 0 || Array.isArray(value) && value.length === 0) return null;
|
|
91
|
+
const codec = getLinkCodec(`[[...${seg.name}]]`);
|
|
92
|
+
if (codec) {
|
|
93
|
+
const serialized = codec.serialize(value);
|
|
94
|
+
if (!serialized) return null;
|
|
95
|
+
return serialized.split("/").map(encodeURIComponent).join("/");
|
|
96
|
+
}
|
|
97
|
+
return (Array.isArray(value) ? value : [value]).map(encodeURIComponent).join("/");
|
|
98
|
+
}
|
|
99
|
+
case "catch-all": {
|
|
100
|
+
const value = params[seg.name];
|
|
101
|
+
if (value === void 0) throw new Error(`<Link> missing required catch-all param "${seg.name}" for pattern "${pattern}".`);
|
|
102
|
+
const codec = getLinkCodec(`[...${seg.name}]`);
|
|
103
|
+
if (codec) {
|
|
104
|
+
const serialized = codec.serialize(value);
|
|
105
|
+
if (!serialized) throw new Error(`<Link> catch-all param "${seg.name}" codec returned null for pattern "${pattern}".`);
|
|
106
|
+
return serialized.split("/").map(encodeURIComponent).join("/");
|
|
107
|
+
}
|
|
108
|
+
const segments = Array.isArray(value) ? value : [value];
|
|
109
|
+
if (segments.length === 0) throw new Error(`<Link> catch-all param "${seg.name}" must have at least one segment for pattern "${pattern}".`);
|
|
110
|
+
return segments.map(encodeURIComponent).join("/");
|
|
111
|
+
}
|
|
112
|
+
case "dynamic": {
|
|
113
|
+
const value = params[seg.name];
|
|
114
|
+
if (value === void 0) throw new Error(`<Link> missing required param "${seg.name}" for pattern "${pattern}".`);
|
|
115
|
+
if (Array.isArray(value)) throw new Error(`<Link> param "${seg.name}" expected a string but received an array for pattern "${pattern}".`);
|
|
116
|
+
const codec = getLinkCodec(`[${seg.name}]`);
|
|
117
|
+
const str = codec ? codec.serialize(value) ?? String(value) : String(value);
|
|
118
|
+
const encoded = encodeURIComponent(str);
|
|
119
|
+
const prefix = seg.prefix ?? "";
|
|
120
|
+
const suffix = seg.suffix ?? "";
|
|
121
|
+
return prefix + encoded + suffix;
|
|
122
|
+
}
|
|
173
123
|
}
|
|
174
124
|
}
|
|
175
125
|
/**
|
|
176
|
-
*
|
|
177
|
-
*
|
|
178
|
-
*/
|
|
179
|
-
function usePendingNavigationUrl() {
|
|
180
|
-
const ctx = getOrCreatePendingContext();
|
|
181
|
-
if (!ctx) return null;
|
|
182
|
-
if (typeof React.useContext !== "function") return null;
|
|
183
|
-
return React.useContext(ctx);
|
|
184
|
-
}
|
|
185
|
-
//#endregion
|
|
186
|
-
//#region src/client/link-status-provider.tsx
|
|
187
|
-
var NOT_PENDING = { pending: false };
|
|
188
|
-
var IS_PENDING = { pending: true };
|
|
189
|
-
/**
|
|
190
|
-
* Client component that reads the pending URL from PendingNavigationContext
|
|
191
|
-
* and provides a scoped LinkStatusContext to children. Renders no extra DOM —
|
|
192
|
-
* just a context provider around children.
|
|
193
|
-
*/
|
|
194
|
-
function LinkStatusProvider({ href, children }) {
|
|
195
|
-
const status = usePendingNavigationUrl() === href ? IS_PENDING : NOT_PENDING;
|
|
196
|
-
return /* @__PURE__ */ jsx(LinkStatusContext.Provider, {
|
|
197
|
-
value: status,
|
|
198
|
-
children
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
//#endregion
|
|
202
|
-
//#region src/client/router-ref.ts
|
|
203
|
-
/**
|
|
204
|
-
* Set the global router instance. Called once during bootstrap.
|
|
126
|
+
* Split a URL pattern into the path portion and any trailing ?query/#hash suffix.
|
|
127
|
+
* Uses URL parsing for correctness rather than manual index arithmetic.
|
|
205
128
|
*/
|
|
206
|
-
function
|
|
207
|
-
|
|
129
|
+
function splitPatternSuffix(pattern) {
|
|
130
|
+
if (!pattern.includes("?") && !pattern.includes("#")) return [pattern, ""];
|
|
131
|
+
const url = new URL(pattern, "http://x");
|
|
132
|
+
const suffix = url.search + url.hash;
|
|
133
|
+
return [pattern.slice(0, pattern.length - suffix.length), suffix];
|
|
208
134
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
*/
|
|
213
|
-
function getRouter() {
|
|
214
|
-
if (!globalRouter) throw new Error("[timber] Router not initialized. getRouter() was called before bootstrap().");
|
|
215
|
-
return globalRouter;
|
|
135
|
+
function interpolateParams(pattern, params) {
|
|
136
|
+
const [pathPart, suffix] = splitPatternSuffix(pattern);
|
|
137
|
+
return ("/" + parseSegments(pathPart).map((seg) => resolveSegment(seg, params, pattern)).filter((s) => s !== null).join("/") || "/") + suffix;
|
|
216
138
|
}
|
|
217
139
|
/**
|
|
218
|
-
*
|
|
219
|
-
*
|
|
220
|
-
*
|
|
140
|
+
* Resolve the final href string from Link props.
|
|
141
|
+
*
|
|
142
|
+
* Handles:
|
|
143
|
+
* - params interpolation into route patterns
|
|
144
|
+
* - searchParams serialization (see the two shapes documented above)
|
|
145
|
+
* - Validation that searchParams and inline query strings are exclusive
|
|
221
146
|
*/
|
|
222
|
-
function getRouterOrNull() {
|
|
223
|
-
return globalRouter;
|
|
224
|
-
}
|
|
225
|
-
//#endregion
|
|
226
|
-
//#region src/client/link.tsx
|
|
227
147
|
/**
|
|
228
|
-
*
|
|
229
|
-
*
|
|
148
|
+
* Tolerate a leading '?'. `buildSearchParams()` never emits one, but callers
|
|
149
|
+
* hand-rolling a query string reasonably might, and silently producing
|
|
150
|
+
* `?%3Fa=b` for it would be a worse failure than accepting both.
|
|
230
151
|
*/
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
if (DANGEROUS_SCHEMES.test(href)) throw new Error(`<Link> received a dangerous href: "${href}". javascript:, data:, and vbscript: URLs are not allowed.`);
|
|
234
|
-
}
|
|
235
|
-
/** Returns true if the href is an internal path (not an external URL) */
|
|
236
|
-
function isInternalHref(href) {
|
|
237
|
-
if (href.startsWith("/") || href.startsWith("#") || href.startsWith("?")) return true;
|
|
238
|
-
if (/^[a-z][a-z0-9+.-]*:/i.test(href)) return false;
|
|
239
|
-
return true;
|
|
152
|
+
function stripLeadingQuestionMark(qs) {
|
|
153
|
+
return qs.startsWith("?") ? qs.slice(1) : qs;
|
|
240
154
|
}
|
|
241
155
|
/**
|
|
242
|
-
*
|
|
243
|
-
*
|
|
156
|
+
* Escape-hatch serialization for a plain object: String()-coerce every
|
|
157
|
+
* value, append arrays as repeated keys, skip null/undefined.
|
|
244
158
|
*
|
|
245
|
-
*
|
|
246
|
-
* - [param] → single segment
|
|
247
|
-
* - [...param] → catch-all (joined with /)
|
|
248
|
-
* - [[...param]] → optional catch-all (omitted if undefined/empty)
|
|
159
|
+
* Deliberately codec-free and alias-free — see the shape docs above.
|
|
249
160
|
*/
|
|
250
|
-
function
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
const value = params[catchAll];
|
|
259
|
-
if (value === void 0) throw new Error(`<Link> missing required catch-all param "${catchAll}" for pattern "${pattern}".`);
|
|
260
|
-
const segments = Array.isArray(value) ? value : [value];
|
|
261
|
-
if (segments.length === 0) throw new Error(`<Link> catch-all param "${catchAll}" must have at least one segment for pattern "${pattern}".`);
|
|
262
|
-
return segments.map(encodeURIComponent).join("/");
|
|
263
|
-
}
|
|
264
|
-
const value = params[single];
|
|
265
|
-
if (value === void 0) throw new Error(`<Link> missing required param "${single}" for pattern "${pattern}".`);
|
|
266
|
-
if (Array.isArray(value)) throw new Error(`<Link> param "${single}" expected a string but received an array for pattern "${pattern}".`);
|
|
267
|
-
return encodeURIComponent(String(value));
|
|
268
|
-
}).replace(/\/+$/, "") || "/";
|
|
161
|
+
function coerceToQueryString(values) {
|
|
162
|
+
const usp = new URLSearchParams();
|
|
163
|
+
for (const [key, val] of Object.entries(values)) {
|
|
164
|
+
if (val === void 0 || val === null) continue;
|
|
165
|
+
if (Array.isArray(val)) for (const item of val) usp.append(key, String(item));
|
|
166
|
+
else usp.set(key, String(val));
|
|
167
|
+
}
|
|
168
|
+
return usp.toString();
|
|
269
169
|
}
|
|
270
|
-
/**
|
|
271
|
-
* Resolve the final href string from Link props.
|
|
272
|
-
*
|
|
273
|
-
* Handles:
|
|
274
|
-
* - params interpolation into route patterns
|
|
275
|
-
* - searchParams serialization via SearchParamsDefinition
|
|
276
|
-
* - Validation that searchParams and inline query strings are exclusive
|
|
277
|
-
*/
|
|
278
170
|
function resolveHref(href, params, searchParams) {
|
|
279
171
|
let resolvedPath = href;
|
|
280
172
|
if (params) resolvedPath = interpolateParams(href, params);
|
|
281
173
|
if (searchParams) {
|
|
282
174
|
if (resolvedPath.includes("?")) throw new Error("<Link> received both a searchParams prop and a query string in href. These are mutually exclusive — use one or the other.");
|
|
283
|
-
const qs = searchParams
|
|
175
|
+
const qs = typeof searchParams === "string" ? stripLeadingQuestionMark(searchParams) : coerceToQueryString(searchParams);
|
|
284
176
|
if (qs) resolvedPath = `${resolvedPath}?${qs}`;
|
|
285
177
|
}
|
|
286
178
|
return resolvedPath;
|
|
@@ -291,7 +183,7 @@ function resolveHref(href, params, searchParams) {
|
|
|
291
183
|
*/
|
|
292
184
|
function buildLinkProps(props) {
|
|
293
185
|
const resolvedHref = resolveHref(props.href, props.params, props.searchParams);
|
|
294
|
-
|
|
186
|
+
validateNavigationHref(resolvedHref);
|
|
295
187
|
return { href: resolvedHref };
|
|
296
188
|
}
|
|
297
189
|
/**
|
|
@@ -323,17 +215,27 @@ function shouldInterceptClick(event, resolvedHref) {
|
|
|
323
215
|
* navigation via the router. No global event delegation — each Link owns
|
|
324
216
|
* its own click handling.
|
|
325
217
|
*
|
|
326
|
-
* Supports typed routes via
|
|
327
|
-
*
|
|
218
|
+
* Supports typed routes via the Routes interface (populated by codegen).
|
|
219
|
+
* At runtime:
|
|
220
|
+
* - `segmentParams` prop interpolates dynamic segments in the href pattern
|
|
328
221
|
* - `searchParams` prop serializes query parameters via a SearchParamsDefinition
|
|
222
|
+
*
|
|
223
|
+
* Typed via the LinkFunction callable interface. The base call signature
|
|
224
|
+
* forbids segmentParams; per-route signatures are added by codegen via
|
|
225
|
+
* interface merging. See TIM-624.
|
|
329
226
|
*/
|
|
330
|
-
|
|
331
|
-
const { href:
|
|
227
|
+
var Link = function LinkImpl(props) {
|
|
228
|
+
const { href, prefetch, scroll, segmentParams, searchParams, preserveSearchParams, onNavigate, onClick: userOnClick, onMouseEnter: userOnMouseEnter, children, ...rest } = props;
|
|
229
|
+
const { href: baseHref } = buildLinkProps({
|
|
332
230
|
href,
|
|
333
|
-
params,
|
|
231
|
+
params: segmentParams,
|
|
334
232
|
searchParams
|
|
335
233
|
});
|
|
336
|
-
const
|
|
234
|
+
const [isPending, setIsPending] = useState(false);
|
|
235
|
+
const clickSeq = useRef(0);
|
|
236
|
+
const linkStatus = isPending ? LINK_PENDING : LINK_IDLE;
|
|
237
|
+
const internal = isInternalHref(baseHref);
|
|
238
|
+
const resolvedHref = preserveSearchParams && internal ? mergePreservedSearchParams(baseHref, getCurrentSearch(), preserveSearchParams) : baseHref;
|
|
337
239
|
const handleClick = internal ? (event) => {
|
|
338
240
|
userOnClick?.(event);
|
|
339
241
|
if (!shouldInterceptClick(event, resolvedHref)) return;
|
|
@@ -349,827 +251,42 @@ function Link({ href, prefetch, scroll, params, searchParams, onNavigate, onClic
|
|
|
349
251
|
}
|
|
350
252
|
const router = getRouterOrNull();
|
|
351
253
|
if (!router) return;
|
|
254
|
+
const navHref = preserveSearchParams ? mergePreservedSearchParams(baseHref, getCurrentSearch(), preserveSearchParams) : resolvedHref;
|
|
255
|
+
const resolved = new URL(navHref, window.location.href);
|
|
256
|
+
if (resolved.pathname === window.location.pathname && resolved.search === window.location.search && resolved.hash) return;
|
|
352
257
|
event.preventDefault();
|
|
353
258
|
const shouldScroll = scroll !== false;
|
|
354
|
-
|
|
259
|
+
const absoluteHref = resolved.pathname + resolved.search + resolved.hash;
|
|
260
|
+
const seq = ++clickSeq.current;
|
|
261
|
+
const settle = () => {
|
|
262
|
+
if (clickSeq.current === seq) setIsPending(false);
|
|
263
|
+
};
|
|
264
|
+
setIsPending(true);
|
|
265
|
+
router.navigate(absoluteHref, { scroll: shouldScroll }).then(settle, (error) => {
|
|
266
|
+
settle();
|
|
267
|
+
throw error;
|
|
268
|
+
});
|
|
355
269
|
} : userOnClick;
|
|
356
270
|
const handleMouseEnter = internal && prefetch ? (event) => {
|
|
357
271
|
userOnMouseEnter?.(event);
|
|
358
272
|
const router = getRouterOrNull();
|
|
359
|
-
if (router)
|
|
273
|
+
if (router) {
|
|
274
|
+
const prefetchHref = preserveSearchParams ? mergePreservedSearchParams(baseHref, getCurrentSearch(), preserveSearchParams) : resolvedHref;
|
|
275
|
+
const resolved = new URL(prefetchHref, window.location.href);
|
|
276
|
+
router.prefetch(resolved.pathname + resolved.search);
|
|
277
|
+
}
|
|
360
278
|
} : userOnMouseEnter;
|
|
361
279
|
return /* @__PURE__ */ jsx("a", {
|
|
362
280
|
...rest,
|
|
363
281
|
href: resolvedHref,
|
|
364
282
|
onClick: handleClick,
|
|
365
283
|
onMouseEnter: handleMouseEnter,
|
|
366
|
-
children: /* @__PURE__ */ jsx(
|
|
367
|
-
|
|
284
|
+
children: /* @__PURE__ */ jsx(LinkStatusContext.Provider, {
|
|
285
|
+
value: linkStatus,
|
|
368
286
|
children
|
|
369
287
|
})
|
|
370
288
|
});
|
|
371
|
-
}
|
|
372
|
-
//#endregion
|
|
373
|
-
//#region src/client/segment-cache.ts
|
|
374
|
-
/**
|
|
375
|
-
* Maintains the client-side segment tree representing currently mounted
|
|
376
|
-
* layouts and pages. Used for navigation reconciliation — the router diffs
|
|
377
|
-
* new routes against this tree to determine which segments to re-fetch.
|
|
378
|
-
*/
|
|
379
|
-
var SegmentCache = class {
|
|
380
|
-
root;
|
|
381
|
-
get(segment) {
|
|
382
|
-
if (segment === "/" || segment === this.root?.segment) return this.root;
|
|
383
|
-
}
|
|
384
|
-
set(segment, node) {
|
|
385
|
-
if (segment === "/" || !this.root) this.root = node;
|
|
386
|
-
}
|
|
387
|
-
clear() {
|
|
388
|
-
this.root = void 0;
|
|
389
|
-
}
|
|
390
|
-
/**
|
|
391
|
-
* Serialize the mounted segment tree for the X-Timber-State-Tree header.
|
|
392
|
-
* Only includes sync segments — async segments are excluded because the
|
|
393
|
-
* server must always re-render them (they may depend on request context).
|
|
394
|
-
*
|
|
395
|
-
* When mergeableFilter is provided, only segments whose paths are in the
|
|
396
|
-
* set are included. This ensures the server only skips segments that the
|
|
397
|
-
* client can actually merge (i.e., segments whose cached element tree
|
|
398
|
-
* contains an inner SegmentProvider the merger can splice into).
|
|
399
|
-
*
|
|
400
|
-
* This is a performance optimization only, NOT a security boundary.
|
|
401
|
-
* The server always runs all access.ts files regardless of the state tree.
|
|
402
|
-
*/
|
|
403
|
-
serializeStateTree(mergeableFilter) {
|
|
404
|
-
const segments = [];
|
|
405
|
-
if (this.root) collectSyncSegments(this.root, segments, mergeableFilter);
|
|
406
|
-
return { segments };
|
|
407
|
-
}
|
|
408
|
-
};
|
|
409
|
-
/** Recursively collect sync segment paths from the tree */
|
|
410
|
-
function collectSyncSegments(node, out, mergeableFilter) {
|
|
411
|
-
if (!node.isAsync && (!mergeableFilter || mergeableFilter.has(node.segment))) out.push(node.segment);
|
|
412
|
-
for (const child of node.children.values()) collectSyncSegments(child, out, mergeableFilter);
|
|
413
|
-
}
|
|
414
|
-
/**
|
|
415
|
-
* Build a SegmentNode tree from flat segment metadata.
|
|
416
|
-
*
|
|
417
|
-
* Takes an ordered list of segment descriptors (root → leaf) from the
|
|
418
|
-
* server's X-Timber-Segments header and constructs the hierarchical
|
|
419
|
-
* tree structure that SegmentCache expects.
|
|
420
|
-
*
|
|
421
|
-
* Each segment is nested as a child of the previous one, forming a
|
|
422
|
-
* linear chain from root to leaf. The leaf segment (page) is excluded
|
|
423
|
-
* from the tree — pages are never cached across navigations.
|
|
424
|
-
*/
|
|
425
|
-
function buildSegmentTree(segments) {
|
|
426
|
-
if (segments.length === 0) return void 0;
|
|
427
|
-
const layouts = segments.length > 1 ? segments.slice(0, -1) : segments;
|
|
428
|
-
let root;
|
|
429
|
-
let parent;
|
|
430
|
-
for (const info of layouts) {
|
|
431
|
-
const node = {
|
|
432
|
-
segment: info.path,
|
|
433
|
-
payload: null,
|
|
434
|
-
isAsync: info.isAsync,
|
|
435
|
-
children: /* @__PURE__ */ new Map()
|
|
436
|
-
};
|
|
437
|
-
if (!root) root = node;
|
|
438
|
-
if (parent) parent.children.set(info.path, node);
|
|
439
|
-
parent = node;
|
|
440
|
-
}
|
|
441
|
-
return root;
|
|
442
|
-
}
|
|
443
|
-
/**
|
|
444
|
-
* Short-lived cache for hover-triggered prefetches. Entries expire after
|
|
445
|
-
* 30 seconds. When a link is clicked, the prefetched payload is consumed
|
|
446
|
-
* (moved to the history stack) and removed from this cache.
|
|
447
|
-
*
|
|
448
|
-
* timber.js does NOT prefetch on viewport intersection — only explicit
|
|
449
|
-
* hover on <Link prefetch> triggers a prefetch.
|
|
450
|
-
*/
|
|
451
|
-
var PrefetchCache = class PrefetchCache {
|
|
452
|
-
static TTL_MS = 3e4;
|
|
453
|
-
entries = /* @__PURE__ */ new Map();
|
|
454
|
-
set(url, result) {
|
|
455
|
-
this.entries.set(url, {
|
|
456
|
-
result,
|
|
457
|
-
expiresAt: Date.now() + PrefetchCache.TTL_MS
|
|
458
|
-
});
|
|
459
|
-
}
|
|
460
|
-
get(url) {
|
|
461
|
-
const entry = this.entries.get(url);
|
|
462
|
-
if (!entry) return void 0;
|
|
463
|
-
if (Date.now() >= entry.expiresAt) {
|
|
464
|
-
this.entries.delete(url);
|
|
465
|
-
return;
|
|
466
|
-
}
|
|
467
|
-
return entry.result;
|
|
468
|
-
}
|
|
469
|
-
/** Get and remove the entry (used when navigation consumes a prefetch) */
|
|
470
|
-
consume(url) {
|
|
471
|
-
const result = this.get(url);
|
|
472
|
-
if (result !== void 0) this.entries.delete(url);
|
|
473
|
-
return result;
|
|
474
|
-
}
|
|
475
|
-
};
|
|
476
|
-
//#endregion
|
|
477
|
-
//#region src/client/history.ts
|
|
478
|
-
/**
|
|
479
|
-
* Session-lived history stack keyed by URL. Enables instant back/forward
|
|
480
|
-
* navigation without a server roundtrip.
|
|
481
|
-
*
|
|
482
|
-
* On forward navigation, the new page's payload is pushed onto the stack.
|
|
483
|
-
* On popstate, the cached payload is replayed instantly.
|
|
484
|
-
*
|
|
485
|
-
* Scroll positions are stored in history.state (browser History API),
|
|
486
|
-
* not in this stack — see design/19-client-navigation.md §Scroll Restoration.
|
|
487
|
-
*
|
|
488
|
-
* Entries persist for the session duration (no expiry) and are cleared
|
|
489
|
-
* when the tab is closed — matching browser back-button behavior.
|
|
490
|
-
*/
|
|
491
|
-
var HistoryStack = class {
|
|
492
|
-
entries = /* @__PURE__ */ new Map();
|
|
493
|
-
push(url, entry) {
|
|
494
|
-
this.entries.set(url, entry);
|
|
495
|
-
}
|
|
496
|
-
get(url) {
|
|
497
|
-
return this.entries.get(url);
|
|
498
|
-
}
|
|
499
|
-
has(url) {
|
|
500
|
-
return this.entries.has(url);
|
|
501
|
-
}
|
|
502
|
-
};
|
|
503
|
-
//#endregion
|
|
504
|
-
//#region src/client/use-params.ts
|
|
505
|
-
/**
|
|
506
|
-
* Set the current route params in the module-level store.
|
|
507
|
-
*
|
|
508
|
-
* Called by the router on each navigation. This updates the fallback
|
|
509
|
-
* snapshot used by tests and by the hook when called outside a React
|
|
510
|
-
* component (no NavigationContext available).
|
|
511
|
-
*
|
|
512
|
-
* On the client, the primary reactivity path is NavigationContext —
|
|
513
|
-
* the router calls setNavigationState() then renderRoot() which wraps
|
|
514
|
-
* the element in NavigationProvider. setCurrentParams is still called
|
|
515
|
-
* for the module-level fallback.
|
|
516
|
-
*
|
|
517
|
-
* During SSR, params are also available via getSsrData().params
|
|
518
|
-
* (ALS-backed).
|
|
519
|
-
*/
|
|
520
|
-
function setCurrentParams(params) {
|
|
521
|
-
_setCurrentParams(params);
|
|
522
|
-
}
|
|
523
|
-
function useParams(_route) {
|
|
524
|
-
try {
|
|
525
|
-
const navContext = useNavigationContext();
|
|
526
|
-
if (navContext !== null) return navContext.params;
|
|
527
|
-
} catch {}
|
|
528
|
-
return getSsrData()?.params ?? currentParams;
|
|
529
|
-
}
|
|
530
|
-
//#endregion
|
|
531
|
-
//#region src/client/segment-merger.ts
|
|
532
|
-
/**
|
|
533
|
-
* Segment Merger — client-side tree merging for partial RSC payloads.
|
|
534
|
-
*
|
|
535
|
-
* When the server skips rendering sync layouts (because the client already
|
|
536
|
-
* has them cached), the RSC payload is missing outer segment wrappers.
|
|
537
|
-
* This module reconstructs the full element tree by splicing the partial
|
|
538
|
-
* payload into cached segment subtrees.
|
|
539
|
-
*
|
|
540
|
-
* The approach:
|
|
541
|
-
* 1. After each full RSC payload render, walk the decoded element tree
|
|
542
|
-
* and cache each segment's subtree (identified by SegmentProvider boundaries)
|
|
543
|
-
* 2. When a partial payload arrives, wrap it with cached segment elements
|
|
544
|
-
* using React.cloneElement to preserve component identity
|
|
545
|
-
*
|
|
546
|
-
* React.cloneElement preserves the element's `type` — React sees the same
|
|
547
|
-
* component at the same tree position and reconciles (preserving state)
|
|
548
|
-
* rather than remounting. This is how layout state survives navigations.
|
|
549
|
-
*
|
|
550
|
-
* Design docs: 19-client-navigation.md §"Navigation Reconciliation"
|
|
551
|
-
* Security: access.ts runs on the server regardless of skipping — this
|
|
552
|
-
* is a performance optimization only. See 13-security.md.
|
|
553
|
-
*/
|
|
554
|
-
/**
|
|
555
|
-
* Cache of React element subtrees per segment path.
|
|
556
|
-
* Updated after each navigation with the full decoded RSC element tree.
|
|
557
|
-
*/
|
|
558
|
-
var SegmentElementCache = class {
|
|
559
|
-
entries = /* @__PURE__ */ new Map();
|
|
560
|
-
get(segmentPath) {
|
|
561
|
-
return this.entries.get(segmentPath);
|
|
562
|
-
}
|
|
563
|
-
set(segmentPath, entry) {
|
|
564
|
-
this.entries.set(segmentPath, entry);
|
|
565
|
-
}
|
|
566
|
-
has(segmentPath) {
|
|
567
|
-
return this.entries.has(segmentPath);
|
|
568
|
-
}
|
|
569
|
-
clear() {
|
|
570
|
-
this.entries.clear();
|
|
571
|
-
}
|
|
572
|
-
get size() {
|
|
573
|
-
return this.entries.size;
|
|
574
|
-
}
|
|
575
|
-
/**
|
|
576
|
-
* Get the set of segment paths that are safe for the server to skip.
|
|
577
|
-
* Only segments with an inner SegmentProvider (hasMergeableChild) are
|
|
578
|
-
* included — the merger can only replace inner SegmentProviders, not
|
|
579
|
-
* pages embedded in layout output. Used to filter the state tree.
|
|
580
|
-
*
|
|
581
|
-
* Returns an empty set if the element cache is empty (no elements
|
|
582
|
-
* cached yet). This is the safe default — an empty set means no
|
|
583
|
-
* segments pass the filter, so the state tree is empty and the server
|
|
584
|
-
* does a full render. The element cache is populated lazily after the
|
|
585
|
-
* first SPA navigation (RSC-decoded elements from hydration are
|
|
586
|
-
* thenables that can't be walked until React resolves them).
|
|
587
|
-
*/
|
|
588
|
-
getMergeablePaths() {
|
|
589
|
-
const paths = /* @__PURE__ */ new Set();
|
|
590
|
-
for (const [, entry] of this.entries) if (entry.hasMergeableChild) paths.add(entry.segmentPath);
|
|
591
|
-
return paths;
|
|
592
|
-
}
|
|
593
|
-
};
|
|
594
|
-
/**
|
|
595
|
-
* Check if a React element is a SegmentProvider by looking for the
|
|
596
|
-
* `segments` prop (an array of path segments). This is the only
|
|
597
|
-
* component that receives this prop shape.
|
|
598
|
-
*/
|
|
599
|
-
function isSegmentProvider(element) {
|
|
600
|
-
if (!isValidElement(element)) return false;
|
|
601
|
-
const props = element.props;
|
|
602
|
-
return Array.isArray(props.segments);
|
|
603
|
-
}
|
|
604
|
-
/**
|
|
605
|
-
* Extract the segment path from a SegmentProvider element.
|
|
606
|
-
*
|
|
607
|
-
* Uses the `segmentId` prop if available (set by the server for route groups
|
|
608
|
-
* to distinguish siblings that share the same urlPath). Falls back to
|
|
609
|
-
* reconstructing from the `segments` array prop.
|
|
610
|
-
*/
|
|
611
|
-
function getSegmentPath(element) {
|
|
612
|
-
const props = element.props;
|
|
613
|
-
if (props.segmentId) return props.segmentId;
|
|
614
|
-
const filtered = props.segments.filter(Boolean);
|
|
615
|
-
return filtered.length === 0 ? "/" : "/" + filtered.join("/");
|
|
616
|
-
}
|
|
617
|
-
/**
|
|
618
|
-
* Walk a React element tree and extract all SegmentProvider boundaries.
|
|
619
|
-
* Returns an ordered list of segment entries from outermost to innermost.
|
|
620
|
-
*
|
|
621
|
-
* This only finds SegmentProviders along the main children path — it does
|
|
622
|
-
* not descend into parallel routes/slots (those are separate subtrees).
|
|
623
|
-
*/
|
|
624
|
-
function extractSegments(element) {
|
|
625
|
-
const segments = [];
|
|
626
|
-
walkForSegments(element, segments);
|
|
627
|
-
for (let i = 0; i < segments.length; i++) segments[i].hasMergeableChild = i < segments.length - 1;
|
|
628
|
-
return segments;
|
|
629
|
-
}
|
|
630
|
-
function walkForSegments(node, out) {
|
|
631
|
-
if (!isValidElement(node)) return;
|
|
632
|
-
const el = node;
|
|
633
|
-
const props = el.props;
|
|
634
|
-
if (isSegmentProvider(node)) {
|
|
635
|
-
out.push({
|
|
636
|
-
segmentPath: getSegmentPath(el),
|
|
637
|
-
element: el,
|
|
638
|
-
hasMergeableChild: false
|
|
639
|
-
});
|
|
640
|
-
walkChildren(props.children, out);
|
|
641
|
-
return;
|
|
642
|
-
}
|
|
643
|
-
walkChildren(props.children, out);
|
|
644
|
-
}
|
|
645
|
-
function walkChildren(children, out) {
|
|
646
|
-
if (children == null) return;
|
|
647
|
-
if (Array.isArray(children)) for (const child of children) walkForSegments(child, out);
|
|
648
|
-
else walkForSegments(children, out);
|
|
649
|
-
}
|
|
650
|
-
/**
|
|
651
|
-
* Cache all segment subtrees from a fully-rendered RSC element tree.
|
|
652
|
-
* Call this after every full RSC payload render (navigate, refresh, hydration).
|
|
653
|
-
*/
|
|
654
|
-
function cacheSegmentElements(element, cache) {
|
|
655
|
-
const segments = extractSegments(element);
|
|
656
|
-
for (const entry of segments) cache.set(entry.segmentPath, entry);
|
|
657
|
-
}
|
|
658
|
-
function findSegmentProviderPath(node, targetPath) {
|
|
659
|
-
const children = node.props.children;
|
|
660
|
-
if (children == null) return null;
|
|
661
|
-
if (Array.isArray(children)) for (let i = 0; i < children.length; i++) {
|
|
662
|
-
const child = children[i];
|
|
663
|
-
if (!isValidElement(child)) continue;
|
|
664
|
-
if (isSegmentProvider(child)) {
|
|
665
|
-
if (!targetPath || getSegmentPath(child) === targetPath) return [{
|
|
666
|
-
element: node,
|
|
667
|
-
childIndex: i
|
|
668
|
-
}];
|
|
669
|
-
}
|
|
670
|
-
const deeper = findSegmentProviderPath(child, targetPath);
|
|
671
|
-
if (deeper) return [{
|
|
672
|
-
element: node,
|
|
673
|
-
childIndex: i
|
|
674
|
-
}, ...deeper];
|
|
675
|
-
}
|
|
676
|
-
else if (isValidElement(children)) {
|
|
677
|
-
if (isSegmentProvider(children)) {
|
|
678
|
-
if (!targetPath || getSegmentPath(children) === targetPath) return [{
|
|
679
|
-
element: node,
|
|
680
|
-
childIndex: -1
|
|
681
|
-
}];
|
|
682
|
-
}
|
|
683
|
-
const deeper = findSegmentProviderPath(children, targetPath);
|
|
684
|
-
if (deeper) return [{
|
|
685
|
-
element: node,
|
|
686
|
-
childIndex: -1
|
|
687
|
-
}, ...deeper];
|
|
688
|
-
}
|
|
689
|
-
return null;
|
|
690
|
-
}
|
|
691
|
-
/**
|
|
692
|
-
* Replace a nested SegmentProvider within a cached element tree with
|
|
693
|
-
* new content. Uses cloneElement along the path to produce a new tree
|
|
694
|
-
* with preserved component identity at every level except the replaced node.
|
|
695
|
-
*
|
|
696
|
-
* @param cachedElement The cached SegmentProvider element for this segment
|
|
697
|
-
* @param newInnerContent The new React element to splice in at the inner segment position
|
|
698
|
-
* @param innerSegmentPath The path of the inner segment to replace (optional — replaces first found)
|
|
699
|
-
* @returns New element tree with the inner segment replaced
|
|
700
|
-
*/
|
|
701
|
-
function replaceInnerSegment(cachedElement, newInnerContent, innerSegmentPath) {
|
|
702
|
-
const path = findSegmentProviderPath(cachedElement, innerSegmentPath);
|
|
703
|
-
if (!path || path.length === 0) return cachedElement;
|
|
704
|
-
let replacement = newInnerContent;
|
|
705
|
-
for (let i = path.length - 1; i >= 0; i--) {
|
|
706
|
-
const { element, childIndex } = path[i];
|
|
707
|
-
if (childIndex === -1) replacement = cloneElement(element, {}, replacement);
|
|
708
|
-
else {
|
|
709
|
-
const newChildren = [...element.props.children];
|
|
710
|
-
newChildren[childIndex] = replacement;
|
|
711
|
-
replacement = cloneElement(element, {}, ...newChildren);
|
|
712
|
-
}
|
|
713
|
-
}
|
|
714
|
-
return replacement;
|
|
715
|
-
}
|
|
716
|
-
/**
|
|
717
|
-
* Merge a partial RSC payload with cached segment elements.
|
|
718
|
-
*
|
|
719
|
-
* When the server skips segments, the partial payload starts from the
|
|
720
|
-
* first non-skipped segment. This function wraps it with cached elements
|
|
721
|
-
* for the skipped segments, producing a full tree that React can
|
|
722
|
-
* reconcile with the mounted tree (preserving layout state).
|
|
723
|
-
*
|
|
724
|
-
* @param partialPayload The RSC payload element (may be partial)
|
|
725
|
-
* @param skippedSegments Ordered list of segment paths that were skipped (outermost first)
|
|
726
|
-
* @param cache The segment element cache
|
|
727
|
-
* @returns The merged full element tree, or the partial payload if merging isn't possible
|
|
728
|
-
*/
|
|
729
|
-
function mergeSegmentTree(partialPayload, skippedSegments, cache) {
|
|
730
|
-
if (!isValidElement(partialPayload)) return partialPayload;
|
|
731
|
-
if (skippedSegments.length === 0) return partialPayload;
|
|
732
|
-
let result = partialPayload;
|
|
733
|
-
for (let i = skippedSegments.length - 1; i >= 0; i--) {
|
|
734
|
-
const segmentPath = skippedSegments[i];
|
|
735
|
-
const cached = cache.get(segmentPath);
|
|
736
|
-
if (!cached) return partialPayload;
|
|
737
|
-
result = replaceInnerSegment(cached.element, result);
|
|
738
|
-
}
|
|
739
|
-
return result;
|
|
740
|
-
}
|
|
741
|
-
//#endregion
|
|
742
|
-
//#region src/client/rsc-fetch.ts
|
|
743
|
-
var RSC_CONTENT_TYPE = "text/x-component";
|
|
744
|
-
/**
|
|
745
|
-
* Generate a short random cache-busting ID (5 chars, a-z0-9).
|
|
746
|
-
* Matches the format Next.js uses for _rsc params.
|
|
747
|
-
*/
|
|
748
|
-
function generateCacheBustId() {
|
|
749
|
-
const chars = "abcdefghijklmnopqrstuvwxyz0123456789";
|
|
750
|
-
let id = "";
|
|
751
|
-
for (let i = 0; i < 5; i++) id += chars[Math.random() * 36 | 0];
|
|
752
|
-
return id;
|
|
753
|
-
}
|
|
754
|
-
/**
|
|
755
|
-
* Append a `_rsc=<id>` query parameter to the URL.
|
|
756
|
-
* Follows Next.js's pattern — prevents CDN/browser from serving cached HTML
|
|
757
|
-
* for RSC navigation requests and signals that this is an RSC fetch.
|
|
758
|
-
*/
|
|
759
|
-
function appendRscParam(url) {
|
|
760
|
-
return `${url}${url.includes("?") ? "&" : "?"}_rsc=${generateCacheBustId()}`;
|
|
761
|
-
}
|
|
762
|
-
function buildRscHeaders(stateTree, currentUrl) {
|
|
763
|
-
const headers = { Accept: RSC_CONTENT_TYPE };
|
|
764
|
-
if (stateTree) headers["X-Timber-State-Tree"] = JSON.stringify(stateTree);
|
|
765
|
-
if (currentUrl) headers["X-Timber-URL"] = currentUrl;
|
|
766
|
-
return headers;
|
|
767
|
-
}
|
|
768
|
-
/**
|
|
769
|
-
* Extract head elements from the X-Timber-Head response header.
|
|
770
|
-
* Returns null if the header is missing or malformed.
|
|
771
|
-
*/
|
|
772
|
-
function extractHeadElements(response) {
|
|
773
|
-
const header = response.headers.get("X-Timber-Head");
|
|
774
|
-
if (!header) return null;
|
|
775
|
-
try {
|
|
776
|
-
return JSON.parse(decodeURIComponent(header));
|
|
777
|
-
} catch {
|
|
778
|
-
return null;
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
/**
|
|
782
|
-
* Extract segment metadata from the X-Timber-Segments response header.
|
|
783
|
-
* Returns null if the header is missing or malformed.
|
|
784
|
-
*
|
|
785
|
-
* Format: JSON array of {path, isAsync} objects describing the rendered
|
|
786
|
-
* segment chain from root to leaf. Used to populate the client-side
|
|
787
|
-
* segment cache for state tree diffing on subsequent navigations.
|
|
788
|
-
*/
|
|
789
|
-
function extractSegmentInfo(response) {
|
|
790
|
-
const header = response.headers.get("X-Timber-Segments");
|
|
791
|
-
if (!header) return null;
|
|
792
|
-
try {
|
|
793
|
-
return JSON.parse(header);
|
|
794
|
-
} catch {
|
|
795
|
-
return null;
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
|
-
/**
|
|
799
|
-
* Extract skipped segment paths from the X-Timber-Skipped-Segments header.
|
|
800
|
-
* Returns null if the header is missing or malformed.
|
|
801
|
-
*
|
|
802
|
-
* When the server skips sync layouts the client already has cached,
|
|
803
|
-
* it sends this header listing the skipped segment paths (outermost first).
|
|
804
|
-
* The client uses this to merge the partial payload with cached segments.
|
|
805
|
-
*/
|
|
806
|
-
function extractSkippedSegments(response) {
|
|
807
|
-
const header = response.headers.get("X-Timber-Skipped-Segments");
|
|
808
|
-
if (!header) return null;
|
|
809
|
-
try {
|
|
810
|
-
const parsed = JSON.parse(header);
|
|
811
|
-
return Array.isArray(parsed) ? parsed : null;
|
|
812
|
-
} catch {
|
|
813
|
-
return null;
|
|
814
|
-
}
|
|
815
|
-
}
|
|
816
|
-
/**
|
|
817
|
-
* Extract route params from the X-Timber-Params response header.
|
|
818
|
-
* Returns null if the header is missing or malformed.
|
|
819
|
-
*
|
|
820
|
-
* Used to populate useParams() after client-side navigation.
|
|
821
|
-
*/
|
|
822
|
-
function extractParams(response) {
|
|
823
|
-
const header = response.headers.get("X-Timber-Params");
|
|
824
|
-
if (!header) return null;
|
|
825
|
-
try {
|
|
826
|
-
return JSON.parse(header);
|
|
827
|
-
} catch {
|
|
828
|
-
return null;
|
|
829
|
-
}
|
|
830
|
-
}
|
|
831
|
-
/**
|
|
832
|
-
* Thrown when an RSC payload response contains X-Timber-Redirect header.
|
|
833
|
-
* Caught in navigate() to trigger a soft router navigation to the redirect target.
|
|
834
|
-
*/
|
|
835
|
-
var RedirectError = class extends Error {
|
|
836
|
-
redirectUrl;
|
|
837
|
-
constructor(url) {
|
|
838
|
-
super(`Server redirect to ${url}`);
|
|
839
|
-
this.redirectUrl = url;
|
|
840
|
-
}
|
|
841
289
|
};
|
|
842
|
-
/**
|
|
843
|
-
* Fetch an RSC payload from the server. If a decodeRsc function is provided,
|
|
844
|
-
* the response is decoded into a React element tree via createFromFetch.
|
|
845
|
-
* Otherwise, the raw response text is returned (test mode).
|
|
846
|
-
*
|
|
847
|
-
* Also extracts head elements from the X-Timber-Head response header
|
|
848
|
-
* so the client can update document.title and <meta> tags after navigation.
|
|
849
|
-
*/
|
|
850
|
-
async function fetchRscPayload(url, deps, stateTree, currentUrl) {
|
|
851
|
-
const rscUrl = appendRscParam(url);
|
|
852
|
-
const headers = buildRscHeaders(stateTree, currentUrl);
|
|
853
|
-
if (deps.decodeRsc) {
|
|
854
|
-
const fetchPromise = deps.fetch(rscUrl, {
|
|
855
|
-
headers,
|
|
856
|
-
redirect: "manual"
|
|
857
|
-
});
|
|
858
|
-
let headElements = null;
|
|
859
|
-
let segmentInfo = null;
|
|
860
|
-
let params = null;
|
|
861
|
-
let skippedSegments = null;
|
|
862
|
-
const wrappedPromise = fetchPromise.then((response) => {
|
|
863
|
-
const redirectLocation = response.headers.get("X-Timber-Redirect") || (response.status >= 300 && response.status < 400 ? response.headers.get("Location") : null);
|
|
864
|
-
if (redirectLocation) throw new RedirectError(redirectLocation);
|
|
865
|
-
headElements = extractHeadElements(response);
|
|
866
|
-
segmentInfo = extractSegmentInfo(response);
|
|
867
|
-
params = extractParams(response);
|
|
868
|
-
skippedSegments = extractSkippedSegments(response);
|
|
869
|
-
return response;
|
|
870
|
-
});
|
|
871
|
-
await wrappedPromise;
|
|
872
|
-
return {
|
|
873
|
-
payload: await deps.decodeRsc(wrappedPromise),
|
|
874
|
-
headElements,
|
|
875
|
-
segmentInfo,
|
|
876
|
-
params,
|
|
877
|
-
skippedSegments
|
|
878
|
-
};
|
|
879
|
-
}
|
|
880
|
-
const response = await deps.fetch(rscUrl, {
|
|
881
|
-
headers,
|
|
882
|
-
redirect: "manual"
|
|
883
|
-
});
|
|
884
|
-
if (response.status >= 300 && response.status < 400) {
|
|
885
|
-
const location = response.headers.get("Location");
|
|
886
|
-
if (location) throw new RedirectError(location);
|
|
887
|
-
}
|
|
888
|
-
return {
|
|
889
|
-
payload: await response.text(),
|
|
890
|
-
headElements: extractHeadElements(response),
|
|
891
|
-
segmentInfo: extractSegmentInfo(response),
|
|
892
|
-
params: extractParams(response),
|
|
893
|
-
skippedSegments: extractSkippedSegments(response)
|
|
894
|
-
};
|
|
895
|
-
}
|
|
896
|
-
//#endregion
|
|
897
|
-
//#region src/client/router.ts
|
|
898
|
-
/**
|
|
899
|
-
* Check if an error is an abort error (connection closed / fetch aborted).
|
|
900
|
-
* Browsers throw DOMException with name 'AbortError' when a fetch is aborted.
|
|
901
|
-
*/
|
|
902
|
-
function isAbortError(error) {
|
|
903
|
-
if (error instanceof DOMException && error.name === "AbortError") return true;
|
|
904
|
-
if (error instanceof Error && error.name === "AbortError") return true;
|
|
905
|
-
return false;
|
|
906
|
-
}
|
|
907
|
-
/**
|
|
908
|
-
* Create a router instance. In production, called once at app hydration
|
|
909
|
-
* with real browser APIs. In tests, called with mock dependencies.
|
|
910
|
-
*/
|
|
911
|
-
function createRouter(deps) {
|
|
912
|
-
const segmentCache = new SegmentCache();
|
|
913
|
-
const prefetchCache = new PrefetchCache();
|
|
914
|
-
const historyStack = new HistoryStack();
|
|
915
|
-
const segmentElementCache = new SegmentElementCache();
|
|
916
|
-
let pending = false;
|
|
917
|
-
let pendingUrl = null;
|
|
918
|
-
const pendingListeners = /* @__PURE__ */ new Set();
|
|
919
|
-
function setPending(value, url) {
|
|
920
|
-
const newPendingUrl = value && url ? url : null;
|
|
921
|
-
if (pending === value && pendingUrl === newPendingUrl) return;
|
|
922
|
-
pending = value;
|
|
923
|
-
pendingUrl = newPendingUrl;
|
|
924
|
-
for (const listener of pendingListeners) listener(value);
|
|
925
|
-
}
|
|
926
|
-
/** Update the segment cache from server-provided segment metadata. */
|
|
927
|
-
function updateSegmentCache(segmentInfo) {
|
|
928
|
-
if (!segmentInfo || segmentInfo.length === 0) return;
|
|
929
|
-
const tree = buildSegmentTree(segmentInfo);
|
|
930
|
-
if (tree) segmentCache.set("/", tree);
|
|
931
|
-
}
|
|
932
|
-
/** Render a decoded RSC payload into the DOM if a renderer is available. */
|
|
933
|
-
function renderPayload(payload) {
|
|
934
|
-
if (deps.renderRoot) deps.renderRoot(payload);
|
|
935
|
-
}
|
|
936
|
-
/**
|
|
937
|
-
* Merge a partial RSC payload with cached segment elements if segments
|
|
938
|
-
* were skipped, then cache segments from the (merged) payload.
|
|
939
|
-
* Returns the merged payload ready for rendering.
|
|
940
|
-
*/
|
|
941
|
-
function mergeAndCachePayload(payload, skippedSegments) {
|
|
942
|
-
let merged = payload;
|
|
943
|
-
if (skippedSegments && skippedSegments.length > 0) merged = mergeSegmentTree(payload, skippedSegments, segmentElementCache);
|
|
944
|
-
cacheSegmentElements(merged, segmentElementCache);
|
|
945
|
-
return merged;
|
|
946
|
-
}
|
|
947
|
-
/**
|
|
948
|
-
* Update navigation state (params + pathname) for the next render.
|
|
949
|
-
*
|
|
950
|
-
* Sets both the module-level fallback (for tests and SSR) and the
|
|
951
|
-
* navigation context state (read by renderRoot to wrap the element
|
|
952
|
-
* in NavigationProvider). The context update is atomic with the tree
|
|
953
|
-
* render — both are passed to reactRoot.render() in the same call.
|
|
954
|
-
*/
|
|
955
|
-
function updateNavigationState(params, url) {
|
|
956
|
-
const resolvedParams = params ?? {};
|
|
957
|
-
setCurrentParams(resolvedParams);
|
|
958
|
-
setNavigationState({
|
|
959
|
-
params: resolvedParams,
|
|
960
|
-
pathname: url.startsWith("http") ? new URL(url).pathname : url.split("?")[0] || "/"
|
|
961
|
-
});
|
|
962
|
-
}
|
|
963
|
-
/**
|
|
964
|
-
* Render a payload via navigateTransition (production) or renderRoot (tests).
|
|
965
|
-
* The perform callback should fetch data, update state, and return the payload.
|
|
966
|
-
* In production, the entire callback runs inside a React transition with
|
|
967
|
-
* useOptimistic for the pending URL. In tests, the payload is rendered directly.
|
|
968
|
-
*/
|
|
969
|
-
async function renderViaTransition(url, perform) {
|
|
970
|
-
if (deps.navigateTransition) {
|
|
971
|
-
let headElements = null;
|
|
972
|
-
await deps.navigateTransition(url, async (wrapPayload) => {
|
|
973
|
-
const result = await perform();
|
|
974
|
-
headElements = result.headElements;
|
|
975
|
-
const merged = mergeAndCachePayload(result.payload, result.skippedSegments);
|
|
976
|
-
historyStack.push(url, {
|
|
977
|
-
payload: merged,
|
|
978
|
-
headElements: result.headElements,
|
|
979
|
-
params: result.params
|
|
980
|
-
});
|
|
981
|
-
return wrapPayload(merged);
|
|
982
|
-
});
|
|
983
|
-
return headElements;
|
|
984
|
-
}
|
|
985
|
-
const result = await perform();
|
|
986
|
-
const merged = mergeAndCachePayload(result.payload, result.skippedSegments);
|
|
987
|
-
historyStack.push(url, {
|
|
988
|
-
payload: merged,
|
|
989
|
-
headElements: result.headElements,
|
|
990
|
-
params: result.params
|
|
991
|
-
});
|
|
992
|
-
renderPayload(merged);
|
|
993
|
-
return result.headElements;
|
|
994
|
-
}
|
|
995
|
-
/** Apply head elements (title, meta tags) to the DOM if available. */
|
|
996
|
-
function applyHead(elements) {
|
|
997
|
-
if (elements && deps.applyHead) deps.applyHead(elements);
|
|
998
|
-
}
|
|
999
|
-
/** Run a callback after the next paint (after React commit). */
|
|
1000
|
-
function afterPaint(callback) {
|
|
1001
|
-
if (deps.afterPaint) deps.afterPaint(callback);
|
|
1002
|
-
else callback();
|
|
1003
|
-
}
|
|
1004
|
-
/**
|
|
1005
|
-
* Core navigation logic shared between the transition and fallback paths.
|
|
1006
|
-
* Fetches the RSC payload, updates all state, and returns the result.
|
|
1007
|
-
*/
|
|
1008
|
-
async function performNavigationFetch(url, options) {
|
|
1009
|
-
const prefetched = prefetchCache.consume(url);
|
|
1010
|
-
let result = prefetched ? {
|
|
1011
|
-
payload: prefetched.payload,
|
|
1012
|
-
headElements: prefetched.headElements,
|
|
1013
|
-
segmentInfo: prefetched.segmentInfo ?? null,
|
|
1014
|
-
params: prefetched.params ?? null,
|
|
1015
|
-
skippedSegments: prefetched.skippedSegments ?? null
|
|
1016
|
-
} : void 0;
|
|
1017
|
-
if (result === void 0) {
|
|
1018
|
-
const stateTree = segmentCache.serializeStateTree(segmentElementCache.getMergeablePaths());
|
|
1019
|
-
const rawCurrentUrl = deps.getCurrentUrl();
|
|
1020
|
-
result = await fetchRscPayload(url, deps, stateTree, rawCurrentUrl.startsWith("http") ? new URL(rawCurrentUrl).pathname : new URL(rawCurrentUrl, "http://localhost").pathname);
|
|
1021
|
-
}
|
|
1022
|
-
if (options.replace) deps.replaceState({
|
|
1023
|
-
timber: true,
|
|
1024
|
-
scrollY: 0
|
|
1025
|
-
}, "", url);
|
|
1026
|
-
else deps.pushState({
|
|
1027
|
-
timber: true,
|
|
1028
|
-
scrollY: 0
|
|
1029
|
-
}, "", url);
|
|
1030
|
-
updateSegmentCache(result.segmentInfo);
|
|
1031
|
-
updateNavigationState(result.params, url);
|
|
1032
|
-
return result;
|
|
1033
|
-
}
|
|
1034
|
-
async function navigate(url, options = {}) {
|
|
1035
|
-
const scroll = options.scroll !== false;
|
|
1036
|
-
const replace = options.replace === true;
|
|
1037
|
-
const currentScrollY = deps.getScrollY();
|
|
1038
|
-
deps.replaceState({
|
|
1039
|
-
timber: true,
|
|
1040
|
-
scrollY: currentScrollY
|
|
1041
|
-
}, "", deps.getCurrentUrl());
|
|
1042
|
-
setPending(true, url);
|
|
1043
|
-
try {
|
|
1044
|
-
applyHead(await renderViaTransition(url, () => performNavigationFetch(url, { replace })));
|
|
1045
|
-
window.dispatchEvent(new Event("timber:navigation-end"));
|
|
1046
|
-
afterPaint(() => {
|
|
1047
|
-
if (scroll) deps.scrollTo(0, 0);
|
|
1048
|
-
else deps.scrollTo(0, currentScrollY);
|
|
1049
|
-
window.dispatchEvent(new Event("timber:scroll-restored"));
|
|
1050
|
-
});
|
|
1051
|
-
} catch (error) {
|
|
1052
|
-
if (error instanceof RedirectError) {
|
|
1053
|
-
setPending(false);
|
|
1054
|
-
await navigate(error.redirectUrl, { replace: true });
|
|
1055
|
-
return;
|
|
1056
|
-
}
|
|
1057
|
-
if (isAbortError(error)) return;
|
|
1058
|
-
throw error;
|
|
1059
|
-
} finally {
|
|
1060
|
-
setPending(false);
|
|
1061
|
-
}
|
|
1062
|
-
}
|
|
1063
|
-
async function refresh() {
|
|
1064
|
-
const currentUrl = deps.getCurrentUrl();
|
|
1065
|
-
setPending(true, currentUrl);
|
|
1066
|
-
try {
|
|
1067
|
-
applyHead(await renderViaTransition(currentUrl, async () => {
|
|
1068
|
-
const result = await fetchRscPayload(currentUrl, deps);
|
|
1069
|
-
updateSegmentCache(result.segmentInfo);
|
|
1070
|
-
updateNavigationState(result.params, currentUrl);
|
|
1071
|
-
return result;
|
|
1072
|
-
}));
|
|
1073
|
-
} finally {
|
|
1074
|
-
setPending(false);
|
|
1075
|
-
}
|
|
1076
|
-
}
|
|
1077
|
-
async function handlePopState(url, scrollY = 0) {
|
|
1078
|
-
const entry = historyStack.get(url);
|
|
1079
|
-
if (entry && entry.payload !== null) {
|
|
1080
|
-
updateNavigationState(entry.params, url);
|
|
1081
|
-
renderPayload(entry.payload);
|
|
1082
|
-
applyHead(entry.headElements);
|
|
1083
|
-
afterPaint(() => {
|
|
1084
|
-
deps.scrollTo(0, scrollY);
|
|
1085
|
-
window.dispatchEvent(new Event("timber:scroll-restored"));
|
|
1086
|
-
});
|
|
1087
|
-
} else {
|
|
1088
|
-
setPending(true, url);
|
|
1089
|
-
try {
|
|
1090
|
-
applyHead(await renderViaTransition(url, async () => {
|
|
1091
|
-
const result = await fetchRscPayload(url, deps, segmentCache.serializeStateTree(segmentElementCache.getMergeablePaths()));
|
|
1092
|
-
updateSegmentCache(result.segmentInfo);
|
|
1093
|
-
updateNavigationState(result.params, url);
|
|
1094
|
-
return result;
|
|
1095
|
-
}));
|
|
1096
|
-
afterPaint(() => {
|
|
1097
|
-
deps.scrollTo(0, scrollY);
|
|
1098
|
-
window.dispatchEvent(new Event("timber:scroll-restored"));
|
|
1099
|
-
});
|
|
1100
|
-
} finally {
|
|
1101
|
-
setPending(false);
|
|
1102
|
-
}
|
|
1103
|
-
}
|
|
1104
|
-
}
|
|
1105
|
-
/**
|
|
1106
|
-
* Prefetch an RSC payload for a URL and store it in the prefetch cache.
|
|
1107
|
-
* Called on hover of <Link prefetch> elements.
|
|
1108
|
-
*/
|
|
1109
|
-
function prefetch(url) {
|
|
1110
|
-
if (prefetchCache.get(url) !== void 0) return;
|
|
1111
|
-
if (historyStack.has(url)) return;
|
|
1112
|
-
fetchRscPayload(url, deps, segmentCache.serializeStateTree(segmentElementCache.getMergeablePaths())).then((result) => {
|
|
1113
|
-
prefetchCache.set(url, result);
|
|
1114
|
-
}, () => {});
|
|
1115
|
-
}
|
|
1116
|
-
return {
|
|
1117
|
-
navigate,
|
|
1118
|
-
refresh,
|
|
1119
|
-
handlePopState,
|
|
1120
|
-
isPending: () => pending,
|
|
1121
|
-
getPendingUrl: () => pendingUrl,
|
|
1122
|
-
onPendingChange(listener) {
|
|
1123
|
-
pendingListeners.add(listener);
|
|
1124
|
-
return () => pendingListeners.delete(listener);
|
|
1125
|
-
},
|
|
1126
|
-
prefetch,
|
|
1127
|
-
applyRevalidation(element, headElements) {
|
|
1128
|
-
const currentUrl = deps.getCurrentUrl();
|
|
1129
|
-
const merged = mergeAndCachePayload(element, null);
|
|
1130
|
-
historyStack.push(currentUrl, {
|
|
1131
|
-
payload: merged,
|
|
1132
|
-
headElements
|
|
1133
|
-
});
|
|
1134
|
-
renderPayload(merged);
|
|
1135
|
-
applyHead(headElements);
|
|
1136
|
-
},
|
|
1137
|
-
initSegmentCache: (segments) => updateSegmentCache(segments),
|
|
1138
|
-
cacheElementTree: (element) => cacheSegmentElements(element, segmentElementCache),
|
|
1139
|
-
segmentCache,
|
|
1140
|
-
prefetchCache,
|
|
1141
|
-
historyStack
|
|
1142
|
-
};
|
|
1143
|
-
}
|
|
1144
|
-
//#endregion
|
|
1145
|
-
//#region src/client/use-navigation-pending.ts
|
|
1146
|
-
/**
|
|
1147
|
-
* Returns true while an RSC navigation is in flight.
|
|
1148
|
-
*
|
|
1149
|
-
* The pending state is true from the moment the RSC fetch starts until
|
|
1150
|
-
* React reconciliation completes. This includes the fetch itself,
|
|
1151
|
-
* RSC stream parsing, and React tree reconciliation.
|
|
1152
|
-
*
|
|
1153
|
-
* It does NOT include Suspense streaming after the shell — only the
|
|
1154
|
-
* initial shell reconciliation.
|
|
1155
|
-
*
|
|
1156
|
-
* ```tsx
|
|
1157
|
-
* 'use client'
|
|
1158
|
-
* import { useNavigationPending } from '@timber-js/app/client'
|
|
1159
|
-
*
|
|
1160
|
-
* export function NavBar() {
|
|
1161
|
-
* const isPending = useNavigationPending()
|
|
1162
|
-
* return (
|
|
1163
|
-
* <nav className={isPending ? 'opacity-50' : ''}>
|
|
1164
|
-
* <Link href="/dashboard">Dashboard</Link>
|
|
1165
|
-
* </nav>
|
|
1166
|
-
* )
|
|
1167
|
-
* }
|
|
1168
|
-
* ```
|
|
1169
|
-
*/
|
|
1170
|
-
function useNavigationPending() {
|
|
1171
|
-
return usePendingNavigationUrl() !== null;
|
|
1172
|
-
}
|
|
1173
290
|
//#endregion
|
|
1174
291
|
//#region src/client/use-router.ts
|
|
1175
292
|
/**
|
|
@@ -1188,13 +305,13 @@ function useNavigationPending() {
|
|
|
1188
305
|
* In timber, navigation calls reactRoot.render() which is a root-level
|
|
1189
306
|
* render — startTransition has no effect on root renders.
|
|
1190
307
|
*
|
|
1191
|
-
* Navigation state (
|
|
308
|
+
* Navigation state (pathname, search) is delivered atomically via
|
|
1192
309
|
* NavigationContext embedded in the element tree passed to
|
|
1193
310
|
* reactRoot.render(). See design/19-client-navigation.md §"NavigationContext".
|
|
1194
311
|
*
|
|
1195
312
|
* For loading UI during navigation, use:
|
|
1196
313
|
* - useLinkStatus() — per-link pending indicator (inside <Link>)
|
|
1197
|
-
* -
|
|
314
|
+
* - usePendingNavigation() — global navigation pending state
|
|
1198
315
|
*/
|
|
1199
316
|
/**
|
|
1200
317
|
* Get a router instance for programmatic navigation.
|
|
@@ -1216,6 +333,7 @@ function useNavigationPending() {
|
|
|
1216
333
|
function useRouter() {
|
|
1217
334
|
return {
|
|
1218
335
|
push(href, options) {
|
|
336
|
+
validateNavigationHref(href);
|
|
1219
337
|
const router = getRouterOrNull();
|
|
1220
338
|
if (!router) {
|
|
1221
339
|
if (process.env.NODE_ENV === "development") console.error("[timber] useRouter().push() called but router is not initialized. This is a bug — please report it.");
|
|
@@ -1224,6 +342,7 @@ function useRouter() {
|
|
|
1224
342
|
router.navigate(href, { scroll: options?.scroll });
|
|
1225
343
|
},
|
|
1226
344
|
replace(href, options) {
|
|
345
|
+
validateNavigationHref(href);
|
|
1227
346
|
const router = getRouterOrNull();
|
|
1228
347
|
if (!router) {
|
|
1229
348
|
if (process.env.NODE_ENV === "development") console.error("[timber] useRouter().replace() called but router is not initialized.");
|
|
@@ -1293,95 +412,38 @@ function usePathname() {
|
|
|
1293
412
|
return "/";
|
|
1294
413
|
}
|
|
1295
414
|
//#endregion
|
|
1296
|
-
//#region src/client/
|
|
415
|
+
//#region src/client/navigation-api.ts
|
|
1297
416
|
/**
|
|
1298
|
-
*
|
|
1299
|
-
*
|
|
1300
|
-
* Returns a read-only URLSearchParams instance reflecting the current
|
|
1301
|
-
* URL's query string. Updates when client-side navigation changes the URL.
|
|
1302
|
-
*
|
|
1303
|
-
* This is a thin wrapper over window.location.search, provided for
|
|
1304
|
-
* Next.js API compatibility (libraries like nuqs import useSearchParams
|
|
1305
|
-
* from next/navigation).
|
|
1306
|
-
*
|
|
1307
|
-
* Unlike Next.js's ReadonlyURLSearchParams, this returns a standard
|
|
1308
|
-
* URLSearchParams. Mutation methods (set, delete, append) work on the
|
|
1309
|
-
* local copy but do NOT affect the URL — use the router or nuqs for that.
|
|
1310
|
-
*
|
|
1311
|
-
* During SSR, reads the request search params from the SSR ALS context
|
|
1312
|
-
* (populated by ssr-entry.ts) instead of window.location.
|
|
1313
|
-
*
|
|
1314
|
-
* All mutable state is delegated to client/state.ts for singleton guarantees.
|
|
1315
|
-
* See design/18-build-system.md §"Singleton State Registry"
|
|
417
|
+
* Returns true if the Navigation API is available in the current environment.
|
|
418
|
+
* Feature-detected at runtime — no polyfill.
|
|
1316
419
|
*/
|
|
1317
|
-
function
|
|
1318
|
-
|
|
1319
|
-
const data = getSsrData();
|
|
1320
|
-
if (!data) return "";
|
|
1321
|
-
const str = new URLSearchParams(data.searchParams).toString();
|
|
1322
|
-
return str ? `?${str}` : "";
|
|
1323
|
-
}
|
|
1324
|
-
function getServerSearch() {
|
|
1325
|
-
const data = getSsrData();
|
|
1326
|
-
if (!data) return "";
|
|
1327
|
-
const str = new URLSearchParams(data.searchParams).toString();
|
|
1328
|
-
return str ? `?${str}` : "";
|
|
1329
|
-
}
|
|
1330
|
-
function subscribe(callback) {
|
|
1331
|
-
window.addEventListener("popstate", callback);
|
|
1332
|
-
return () => window.removeEventListener("popstate", callback);
|
|
1333
|
-
}
|
|
1334
|
-
function getSearchParams() {
|
|
1335
|
-
const search = getSearch();
|
|
1336
|
-
if (search !== cachedSearch) {
|
|
1337
|
-
const params = new URLSearchParams(search);
|
|
1338
|
-
_setCachedSearch(search, params);
|
|
1339
|
-
return params;
|
|
1340
|
-
}
|
|
1341
|
-
return cachedSearchParams;
|
|
1342
|
-
}
|
|
1343
|
-
function getServerSearchParams() {
|
|
1344
|
-
const data = getSsrData();
|
|
1345
|
-
return data ? new URLSearchParams(data.searchParams) : new URLSearchParams();
|
|
420
|
+
function hasNavigationApi() {
|
|
421
|
+
return typeof window !== "undefined" && "navigation" in window && window.navigation != null;
|
|
1346
422
|
}
|
|
1347
423
|
/**
|
|
1348
|
-
*
|
|
1349
|
-
*
|
|
1350
|
-
* Compatible with Next.js's `useSearchParams()` from `next/navigation`.
|
|
424
|
+
* Get the Navigation API instance. Returns null if unavailable.
|
|
1351
425
|
*/
|
|
1352
|
-
function
|
|
1353
|
-
|
|
1354
|
-
return
|
|
426
|
+
function getNavigationApi() {
|
|
427
|
+
if (!hasNavigationApi()) return null;
|
|
428
|
+
return window.navigation;
|
|
1355
429
|
}
|
|
1356
430
|
//#endregion
|
|
1357
|
-
//#region src/client/
|
|
431
|
+
//#region src/client/shallow-url.ts
|
|
1358
432
|
/**
|
|
1359
|
-
*
|
|
1360
|
-
*
|
|
1361
|
-
* Each layout in the segment tree is wrapped with a SegmentProvider that stores
|
|
1362
|
-
* the URL segments from root to the current layout level. The hooks read this
|
|
1363
|
-
* context to determine which child segments are active below the calling layout.
|
|
433
|
+
* Shallow URL replacement — update the browser URL bar without triggering
|
|
434
|
+
* RSC navigation, TopLoader, or any server round-trip.
|
|
1364
435
|
*
|
|
1365
|
-
*
|
|
1366
|
-
*
|
|
1367
|
-
*
|
|
1368
|
-
* Design docs: design/19-client-navigation.md, design/14-ecosystem.md
|
|
436
|
+
* Uses the Navigation API's `info: { shallow: true }` when available (Chrome),
|
|
437
|
+
* which the navigate event handler intercepts with a no-op handler. Falls back
|
|
438
|
+
* to raw `history.replaceState` (Safari/Firefox — no navigate event fired).
|
|
1369
439
|
*/
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
}
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
* Injected by rsc-entry.ts during element tree construction.
|
|
1378
|
-
*/
|
|
1379
|
-
function SegmentProvider({ segments, segmentId: _segmentId, parallelRouteKeys, children }) {
|
|
1380
|
-
const value = useMemo(() => ({
|
|
1381
|
-
segments,
|
|
1382
|
-
parallelRouteKeys
|
|
1383
|
-
}), [segments.join("/"), parallelRouteKeys.join(",")]);
|
|
1384
|
-
return createElement(SegmentContext.Provider, { value }, children);
|
|
440
|
+
function replaceUrl(url) {
|
|
441
|
+
const nav = getNavigationApi();
|
|
442
|
+
if (nav) nav.navigate(url, {
|
|
443
|
+
history: "replace",
|
|
444
|
+
info: { shallow: true }
|
|
445
|
+
});
|
|
446
|
+
else history.replaceState(history.state, "", url);
|
|
1385
447
|
}
|
|
1386
448
|
//#endregion
|
|
1387
449
|
//#region src/client/use-selected-layout-segment.ts
|
|
@@ -1514,7 +576,13 @@ function useSelectedLayoutSegments(parallelRouteKey) {
|
|
|
1514
576
|
* ```
|
|
1515
577
|
*/
|
|
1516
578
|
function useActionState(action, initialState, permalink) {
|
|
1517
|
-
|
|
579
|
+
const [result, formAction, isPending] = useActionState$1(action, initialState, permalink);
|
|
580
|
+
return [
|
|
581
|
+
result,
|
|
582
|
+
formAction,
|
|
583
|
+
isPending,
|
|
584
|
+
deriveFormErrors(result)
|
|
585
|
+
];
|
|
1518
586
|
}
|
|
1519
587
|
/**
|
|
1520
588
|
* Hook for calling a server action imperatively (not via a form).
|
|
@@ -1540,27 +608,11 @@ function useFormAction(action) {
|
|
|
1540
608
|
return [execute, isPending];
|
|
1541
609
|
}
|
|
1542
610
|
/**
|
|
1543
|
-
*
|
|
1544
|
-
*
|
|
1545
|
-
*
|
|
1546
|
-
* since it's used in render. Accepts the result from `useActionState`
|
|
1547
|
-
* or flash data from `getFormFlash()`.
|
|
1548
|
-
*
|
|
1549
|
-
* @example
|
|
1550
|
-
* ```tsx
|
|
1551
|
-
* const [result, action, isPending] = useActionState(createTodo, null)
|
|
1552
|
-
* const errors = useFormErrors(result)
|
|
1553
|
-
*
|
|
1554
|
-
* return (
|
|
1555
|
-
* <form action={action}>
|
|
1556
|
-
* <input name="title" />
|
|
1557
|
-
* {errors.getFieldError('title') && <p>{errors.getFieldError('title')}</p>}
|
|
1558
|
-
* {errors.formErrors.map(e => <p key={e}>{e}</p>)}
|
|
1559
|
-
* </form>
|
|
1560
|
-
* )
|
|
1561
|
-
* ```
|
|
611
|
+
* Derive FormErrorsResult from an action result.
|
|
612
|
+
* Used internally by useActionState 4th tuple element.
|
|
613
|
+
* @internal — exported for test access only.
|
|
1562
614
|
*/
|
|
1563
|
-
function
|
|
615
|
+
function deriveFormErrors(result) {
|
|
1564
616
|
const empty = {
|
|
1565
617
|
fieldErrors: {},
|
|
1566
618
|
formErrors: [],
|
|
@@ -1589,6 +641,6 @@ function useFormErrors(result) {
|
|
|
1589
641
|
};
|
|
1590
642
|
}
|
|
1591
643
|
//#endregion
|
|
1592
|
-
export {
|
|
644
|
+
export { Link, LinkStatusContext, buildLinkProps, interpolateParams, mergePreservedSearchParams, replaceUrl, resolveHref, useActionState, useFormAction, useLinkStatus, usePathname, usePendingNavigation, useQueryStates, useRouter, useSegmentParams, useSelectedLayoutSegment, useSelectedLayoutSegments, validateNavigationHref as validateLinkHref };
|
|
1593
645
|
|
|
1594
646
|
//# sourceMappingURL=index.js.map
|