@timber-js/app 0.2.0-alpha.185 → 0.2.0-alpha.187
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks/{actions-O_LsyCE4.js → actions-35jnMdeJ.js} +4 -3
- package/dist/_chunks/{actions-O_LsyCE4.js.map → actions-35jnMdeJ.js.map} +1 -1
- 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-B-lhk9p4.js → cache-api-DjNrIWRR.js} +8 -14
- package/dist/_chunks/cache-api-DjNrIWRR.js.map +1 -0
- package/dist/_chunks/cli-check-CpmN7Nh-.js +256 -0
- package/dist/_chunks/cli-check-CpmN7Nh-.js.map +1 -0
- package/dist/_chunks/cli-schema-sync-CGMp_Psg.js +298 -0
- package/dist/_chunks/cli-schema-sync-CGMp_Psg.js.map +1 -0
- package/dist/_chunks/{cloudflare-CnT5Lr7U.js → cloudflare-CGP6BZKO.js} +92 -14
- package/dist/_chunks/{cloudflare-CnT5Lr7U.js.map → cloudflare-CGP6BZKO.js.map} +1 -1
- package/dist/_chunks/convention-lint-kXsgc_-7.js +784 -0
- package/dist/_chunks/convention-lint-kXsgc_-7.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-D6hIVt1Y.js → fast-hash-C-tVYrLb.js} +6 -1
- 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/fs-identity-D7vb6GdI.js +208 -0
- package/dist/_chunks/fs-identity-D7vb6GdI.js.map +1 -0
- package/dist/_chunks/{logger-AWfuX-KJ.js → logger-D8xJZXIN.js} +34 -51
- package/dist/_chunks/logger-D8xJZXIN.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---kTF5v8.js → plugin-context-rCinWLiE.js} +8 -2
- 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-Dz3fcFUo.js → resolve-schema-5ma5pp1b.js} +2 -2
- package/dist/_chunks/{resolve-schema-Dz3fcFUo.js.map → resolve-schema-5ma5pp1b.js.map} +1 -1
- package/dist/_chunks/{router-ref-CtmF-aPv.js → router-ref-DuYuV_0Q.js} +2 -2
- 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-C8b0Gcw3.js +1564 -0
- package/dist/_chunks/scanner-C8b0Gcw3.js.map +1 -0
- package/dist/_chunks/schema-bridge-Cc2Gngu1.js +199 -0
- package/dist/_chunks/schema-bridge-Cc2Gngu1.js.map +1 -0
- package/dist/_chunks/{segment-classify-Byy425ng.js → segment-classify-C539Pa2O.js} +23 -2
- 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/{canonicalize-DQHyFClh.js → segment-keys-BawYuNFO.js} +61 -2
- package/dist/_chunks/segment-keys-BawYuNFO.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-BOWsq18U.js → ssr-data-14MXm7Pj.js} +17 -2
- package/dist/_chunks/ssr-data-14MXm7Pj.js.map +1 -0
- package/dist/_chunks/{use-query-states-DFvWd-EA.js → use-query-states-BbU5Ge1V.js} +74 -26
- package/dist/_chunks/use-query-states-BbU5Ge1V.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-RzN6AFjr.js +141 -0
- package/dist/_chunks/walkers-RzN6AFjr.js.map +1 -0
- package/dist/adapters/build-output-helper.d.ts +37 -0
- package/dist/adapters/build-output-helper.d.ts.map +1 -1
- package/dist/adapters/cloudflare-dev.js +1 -1
- package/dist/adapters/cloudflare-kv-cache.js +1 -1
- package/dist/adapters/cloudflare.d.ts.map +1 -1
- package/dist/adapters/cloudflare.js +1 -1
- package/dist/adapters/compress-module.d.ts +12 -0
- 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.map +1 -1
- package/dist/adapters/nitro.js +56 -5
- package/dist/adapters/nitro.js.map +1 -1
- package/dist/adapters/shared.d.ts +57 -1
- package/dist/adapters/shared.d.ts.map +1 -1
- package/dist/adapters/types.d.ts +13 -1
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/cache/fast-hash.d.ts +5 -0
- package/dist/cache/fast-hash.d.ts.map +1 -1
- package/dist/cache/index.js +1 -1
- package/dist/cdn/cloudflare-purge.js +30 -0
- package/dist/cdn/cloudflare-purge.js.map +1 -0
- package/dist/cdn/fastly-purge.js +33 -0
- package/dist/cdn/fastly-purge.js.map +1 -0
- package/dist/cdn/index.js +94 -0
- package/dist/cdn/index.js.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.d.ts +34 -8
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +46 -21
- package/dist/cli.js.map +1 -1
- package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -1
- package/dist/client/browser-entry/hydrate.d.ts +20 -9
- package/dist/client/browser-entry/hydrate.d.ts.map +1 -1
- package/dist/client/browser-entry/index.d.ts +1 -1
- package/dist/client/browser-entry/index.d.ts.map +1 -1
- package/dist/client/browser-entry/post-hydration.d.ts +4 -1
- package/dist/client/browser-entry/post-hydration.d.ts.map +1 -1
- package/dist/client/browser-entry/router-init.d.ts +3 -0
- package/dist/client/browser-entry/router-init.d.ts.map +1 -1
- package/dist/client/browser-entry/rsc-stream.d.ts +8 -0
- package/dist/client/browser-entry/rsc-stream.d.ts.map +1 -1
- package/dist/client/error-boundary.d.ts +7 -0
- package/dist/client/error-boundary.d.ts.map +1 -1
- package/dist/client/error-boundary.js +1 -162
- package/dist/client/history.d.ts +13 -6
- package/dist/client/history.d.ts.map +1 -1
- package/dist/client/index.d.ts +1 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +42 -41
- package/dist/client/index.js.map +1 -1
- package/dist/client/internal.d.ts +4 -3
- package/dist/client/internal.d.ts.map +1 -1
- package/dist/client/internal.js +877 -311
- package/dist/client/internal.js.map +1 -1
- package/dist/client/link.d.ts +1 -7
- package/dist/client/link.d.ts.map +1 -1
- package/dist/client/navigation-api.d.ts +2 -2
- 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 +37 -20
- package/dist/client/navigation-context.d.ts.map +1 -1
- package/dist/client/navigation-root.d.ts +63 -23
- package/dist/client/navigation-root.d.ts.map +1 -1
- package/dist/client/params-context.d.ts +81 -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 +1 -1
- 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 -182
- package/dist/client/router.d.ts.map +1 -1
- package/dist/client/rsc-fetch.d.ts +47 -26
- package/dist/client/rsc-fetch.d.ts.map +1 -1
- package/dist/client/segment-cache.d.ts +87 -34
- package/dist/client/segment-cache.d.ts.map +1 -1
- package/dist/client/ssr-data.d.ts +6 -0
- 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 +10 -1
- package/dist/client/state.d.ts.map +1 -1
- package/dist/client/top-loader.d.ts +2 -1
- 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.map +1 -1
- package/dist/client/use-query-states.d.ts +9 -3
- package/dist/client/use-query-states.d.ts.map +1 -1
- package/dist/client/use-router.d.ts +1 -1
- package/dist/client/use-segment-params.d.ts +18 -8
- package/dist/client/use-segment-params.d.ts.map +1 -1
- package/dist/codec.js +1 -1
- package/dist/cookies/define-cookie.d.ts.map +1 -1
- package/dist/cookies/index.js +5 -5
- package/dist/cookies/index.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1009 -759
- package/dist/index.js.map +1 -1
- package/dist/params/index.js +1 -1
- package/dist/plugin-context.d.ts +46 -0
- package/dist/plugin-context.d.ts.map +1 -1
- package/dist/plugins/adapter-build.d.ts.map +1 -1
- package/dist/plugins/build-manifest.d.ts +1 -1
- package/dist/plugins/build-manifest.d.ts.map +1 -1
- package/dist/plugins/entries.d.ts.map +1 -1
- package/dist/plugins/fonts.d.ts.map +1 -1
- 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.map +1 -1
- package/dist/plugins/shims.d.ts.map +1 -1
- package/dist/plugins/static-build.d.ts +160 -8
- package/dist/plugins/static-build.d.ts.map +1 -1
- package/dist/routing/codegen-shared.d.ts +3 -44
- package/dist/routing/codegen-shared.d.ts.map +1 -1
- package/dist/routing/codegen-types.d.ts +28 -31
- package/dist/routing/codegen-types.d.ts.map +1 -1
- 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.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 +18 -4
- package/dist/routing/convention-lint.d.ts.map +1 -1
- package/dist/routing/export-detect.d.ts +16 -0
- package/dist/routing/export-detect.d.ts.map +1 -1
- package/dist/routing/index.js +4 -3
- package/dist/routing/interception.d.ts +235 -6
- package/dist/routing/interception.d.ts.map +1 -1
- package/dist/routing/link-codegen.d.ts +19 -4
- package/dist/routing/link-codegen.d.ts.map +1 -1
- package/dist/routing/manifest-codegen.d.ts +1 -7
- package/dist/routing/manifest-codegen.d.ts.map +1 -1
- package/dist/routing/scanner.d.ts.map +1 -1
- package/dist/routing/segment-classify.d.ts +33 -0
- package/dist/routing/segment-classify.d.ts.map +1 -1
- package/dist/routing/segment-keys.d.ts +95 -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 +0 -6
- package/dist/routing/types.d.ts.map +1 -1
- package/dist/routing/walkers.d.ts +6 -0
- package/dist/routing/walkers.d.ts.map +1 -1
- package/dist/schema-bridge.d.ts +60 -9
- package/dist/schema-bridge.d.ts.map +1 -1
- package/dist/search-params/define.d.ts +62 -14
- package/dist/search-params/define.d.ts.map +1 -1
- package/dist/search-params/index.d.ts +0 -1
- package/dist/search-params/index.d.ts.map +1 -1
- package/dist/search-params/index.js +221 -10
- package/dist/search-params/index.js.map +1 -1
- package/dist/search-params/parse-total.d.ts +70 -0
- package/dist/search-params/parse-total.d.ts.map +1 -0
- package/dist/search-params/wrappers.d.ts +26 -3
- package/dist/search-params/wrappers.d.ts.map +1 -1
- package/dist/server/access-gate.d.ts +19 -8
- package/dist/server/access-gate.d.ts.map +1 -1
- package/dist/server/action-handler.d.ts.map +1 -1
- package/dist/server/actions.d.ts +6 -3
- package/dist/server/actions.d.ts.map +1 -1
- package/dist/server/als-registry.d.ts +18 -1
- package/dist/server/als-registry.d.ts.map +1 -1
- package/dist/server/build-manifest.d.ts +13 -1
- package/dist/server/build-manifest.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/compress.d.ts.map +1 -1
- 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 +148 -15
- package/dist/server/deny-boundary.d.ts.map +1 -1
- package/dist/server/deny-renderer.d.ts +15 -4
- package/dist/server/deny-renderer.d.ts.map +1 -1
- package/dist/server/error-boundary-wrapper.d.ts +85 -15
- package/dist/server/error-boundary-wrapper.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/index.d.ts +0 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +3 -2
- package/dist/server/index.js.map +1 -1
- package/dist/server/internal.d.ts +3 -1
- package/dist/server/internal.d.ts.map +1 -1
- package/dist/server/internal.js +712 -418
- package/dist/server/internal.js.map +1 -1
- package/dist/server/metadata-collector.d.ts +52 -0
- package/dist/server/metadata-collector.d.ts.map +1 -0
- package/dist/server/param-coercion.d.ts +22 -6
- package/dist/server/param-coercion.d.ts.map +1 -1
- package/dist/server/pipeline-helpers.d.ts +0 -18
- package/dist/server/pipeline-helpers.d.ts.map +1 -1
- package/dist/server/pipeline-interception.d.ts +59 -9
- package/dist/server/pipeline-interception.d.ts.map +1 -1
- package/dist/server/pipeline-outcome.d.ts.map +1 -1
- package/dist/server/pipeline-phases.d.ts.map +1 -1
- package/dist/server/pipeline.d.ts +11 -0
- package/dist/server/pipeline.d.ts.map +1 -1
- package/dist/server/primitives.d.ts +23 -0
- 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/request-context.d.ts +48 -0
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/route-element-builder.d.ts +22 -3
- 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 +13 -0
- 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/api-handler.d.ts.map +1 -1
- package/dist/server/rsc-entry/deny-fallback.d.ts.map +1 -1
- package/dist/server/rsc-entry/error-renderer.d.ts +15 -3
- package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/helpers.d.ts +2 -17
- package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
- package/dist/server/rsc-entry/index.d.ts +0 -1
- package/dist/server/rsc-entry/index.d.ts.map +1 -1
- package/dist/server/rsc-entry/render-route.d.ts.map +1 -1
- package/dist/server/rsc-entry/revalidate-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/rsc-payload.d.ts +1 -2
- package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
- package/dist/server/rsc-entry/rsc-stream.d.ts +15 -2
- package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
- package/dist/server/skippable-prefix.d.ts +23 -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 +70 -8
- package/dist/server/slot-resolver.d.ts.map +1 -1
- package/dist/server/ssr-bridge-types.d.ts +17 -0
- package/dist/server/ssr-bridge-types.d.ts.map +1 -1
- package/dist/server/ssr-entry.d.ts +0 -1
- package/dist/server/ssr-entry.d.ts.map +1 -1
- package/dist/server/ssr-wrappers.d.ts +24 -13
- package/dist/server/ssr-wrappers.d.ts.map +1 -1
- package/dist/server/state-tree-diff.d.ts +6 -27
- package/dist/server/state-tree-diff.d.ts.map +1 -1
- package/dist/server/static-generator.d.ts +6 -0
- package/dist/server/static-generator.d.ts.map +1 -1
- 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 +8 -1
- package/dist/server/status-code-resolver.d.ts.map +1 -1
- package/dist/server/tree-builder.d.ts +28 -36
- package/dist/server/tree-builder.d.ts.map +1 -1
- package/dist/server/types.d.ts +12 -7
- 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/shared/als-slots.d.ts +41 -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/param-value.d.ts +80 -0
- package/dist/shared/param-value.d.ts.map +1 -0
- package/dist/shared/payload-root.d.ts +108 -0
- package/dist/shared/payload-root.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 +59 -0
- package/dist/shared/segment-info.d.ts.map +1 -0
- package/dist/shared/slot-params.d.ts +51 -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/docs/api/30-api-server.mdx +1 -1
- package/docs/api/31-api-client.mdx +4 -2
- package/docs/api/33-api-search-params.mdx +38 -16
- package/docs/api/35-api-typescript.mdx +3 -3
- package/docs/api/36-cli.mdx +34 -7
- package/docs/learn/00-introduction.mdx +1 -1
- package/docs/learn/02-pages-and-layouts.mdx +2 -2
- package/docs/learn/05-typed-params.mdx +8 -8
- package/docs/learn/07-typed-routes.mdx +12 -7
- package/docs/learn/11-error-handling.mdx +18 -0
- package/docs/learn/12-client-navigation.mdx +2 -2
- package/docs/learn/14-deploying.mdx +23 -0
- package/docs/more/01-advanced-routing.mdx +173 -3
- package/docs/more/03-coming-from-nextjs.mdx +2 -2
- package/docs/more/04-metadata-and-fonts.mdx +1 -1
- package/docs/more/50-ai-agent-instructions.mdx +6 -4
- package/package.json +9 -6
- package/src/adapters/build-output-helper.ts +116 -3
- package/src/adapters/cloudflare.ts +90 -12
- package/src/adapters/compress-module.ts +79 -1
- package/src/adapters/fs-identity.ts +156 -0
- package/src/adapters/nitro.ts +6 -6
- package/src/adapters/shared.ts +196 -21
- package/src/adapters/types.ts +13 -1
- package/src/cache/fast-hash.ts +5 -0
- package/src/cli-check.ts +458 -0
- package/src/cli.ts +59 -24
- package/src/client/browser-entry/action-dispatch.ts +11 -5
- package/src/client/browser-entry/hydrate.ts +40 -29
- package/src/client/browser-entry/index.ts +15 -6
- package/src/client/browser-entry/post-hydration.ts +10 -9
- package/src/client/browser-entry/router-init.ts +104 -48
- package/src/client/browser-entry/rsc-stream.ts +11 -2
- package/src/client/error-boundary.tsx +85 -16
- package/src/client/history.ts +13 -6
- package/src/client/index.ts +14 -3
- package/src/client/internal.ts +4 -3
- package/src/client/link.tsx +120 -72
- package/src/client/navigation-api.ts +3 -3
- package/src/client/navigation-commit.ts +197 -0
- package/src/client/navigation-context.ts +40 -67
- package/src/client/navigation-root.tsx +326 -101
- 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 +1 -1
- package/src/client/router-skew.ts +30 -0
- package/src/client/router-types.ts +230 -0
- package/src/client/router.ts +243 -707
- package/src/client/rsc-fetch.ts +183 -106
- package/src/client/segment-cache.ts +129 -44
- package/src/client/ssr-data.ts +6 -0
- package/src/client/stale-client.ts +191 -0
- package/src/client/state.ts +14 -1
- package/src/client/top-loader.tsx +2 -1
- package/src/client/unload-guard.ts +34 -2
- package/src/client/use-cookie.ts +9 -2
- package/src/client/use-query-states.ts +102 -39
- package/src/client/use-router.ts +1 -1
- package/src/client/use-segment-params.ts +41 -18
- package/src/cookies/define-cookie.ts +6 -1
- package/src/index.ts +25 -4
- package/src/plugin-context.ts +58 -0
- package/src/plugins/adapter-build.ts +4 -0
- package/src/plugins/build-manifest.ts +34 -13
- package/src/plugins/entries.ts +4 -0
- package/src/plugins/fonts.ts +11 -8
- 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 +97 -102
- package/src/plugins/shims.ts +0 -1
- package/src/plugins/static-build.ts +391 -95
- package/src/routing/codegen-shared.ts +3 -79
- package/src/routing/codegen-types.ts +28 -31
- package/src/routing/codegen-write.ts +139 -0
- package/src/routing/codegen.ts +86 -172
- package/src/routing/collision-probe.ts +438 -0
- package/src/routing/collision-spaces.ts +281 -0
- package/src/routing/convention-lint.ts +139 -40
- package/src/routing/export-detect.ts +151 -7
- package/src/routing/interception.ts +896 -50
- package/src/routing/link-codegen.ts +32 -65
- package/src/routing/manifest-codegen.ts +6 -62
- package/src/routing/scanner.ts +117 -92
- package/src/routing/segment-classify.ts +57 -0
- package/src/routing/segment-keys.ts +146 -0
- package/src/routing/slot-placement.ts +97 -0
- package/src/routing/types.ts +0 -6
- package/src/routing/walkers.ts +8 -0
- package/src/schema-bridge.ts +180 -58
- package/src/search-params/define.ts +108 -66
- package/src/search-params/index.ts +0 -1
- package/src/search-params/parse-total.ts +78 -0
- package/src/search-params/wrappers.ts +60 -11
- package/src/server/access-gate.tsx +60 -40
- package/src/server/action-handler.ts +4 -5
- package/src/server/actions.ts +6 -3
- package/src/server/als-registry.ts +18 -1
- package/src/server/build-manifest.ts +14 -1
- package/src/server/chain-url-parts.ts +163 -0
- package/src/server/children-interception.ts +115 -0
- package/src/server/compress.ts +9 -1
- package/src/server/default-status-page.ts +127 -0
- package/src/server/deny-boundary.ts +269 -41
- package/src/server/deny-renderer.ts +111 -39
- package/src/server/error-boundary-wrapper.ts +166 -79
- package/src/server/head-response.ts +54 -0
- package/src/server/index.ts +1 -3
- package/src/server/internal.ts +2 -2
- package/src/server/metadata-collector.ts +115 -0
- package/src/server/param-coercion.ts +51 -69
- package/src/server/pipeline-helpers.ts +2 -47
- package/src/server/pipeline-interception.ts +81 -32
- package/src/server/pipeline-outcome.ts +4 -5
- package/src/server/pipeline-phases.ts +77 -25
- package/src/server/pipeline.ts +57 -10
- package/src/server/prebuilt-runtime.ts +4 -4
- package/src/server/primitives.ts +25 -0
- package/src/server/publish-params.ts +42 -0
- package/src/server/request-context.ts +97 -18
- package/src/server/route-element-builder.ts +241 -253
- package/src/server/route-handler.ts +8 -8
- package/src/server/route-matcher.ts +21 -9
- package/src/server/rsc-cache-key-guard.ts +164 -0
- package/src/server/rsc-entry/api-handler.ts +6 -8
- package/src/server/rsc-entry/deny-fallback.ts +3 -2
- package/src/server/rsc-entry/error-renderer.ts +94 -35
- package/src/server/rsc-entry/helpers.ts +33 -28
- package/src/server/rsc-entry/index.ts +36 -33
- package/src/server/rsc-entry/render-route.ts +18 -10
- package/src/server/rsc-entry/revalidate-renderer.ts +3 -2
- package/src/server/rsc-entry/rsc-payload.ts +113 -40
- package/src/server/rsc-entry/rsc-stream.ts +29 -5
- package/src/server/rsc-entry/ssr-renderer.ts +38 -22
- package/src/server/skippable-prefix.ts +92 -0
- package/src/server/slot-interception.ts +168 -0
- package/src/server/slot-resolver.ts +263 -158
- package/src/server/ssr-bridge-types.ts +18 -0
- package/src/server/ssr-entry.ts +20 -10
- package/src/server/ssr-wrappers.tsx +33 -32
- package/src/server/state-tree-diff.ts +14 -55
- package/src/server/static-generator.ts +68 -29
- package/src/server/static-not-found.ts +134 -0
- package/src/server/status-code-resolver.ts +28 -11
- package/src/server/tree-builder.ts +35 -218
- package/src/server/types.ts +12 -7
- package/src/server/utils/element-type.ts +72 -0
- package/src/shared/als-slots.ts +72 -0
- package/src/shared/base-path.ts +80 -0
- package/src/shared/param-value.ts +244 -0
- package/src/shared/payload-root.ts +151 -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 +60 -0
- package/src/shared/slot-params.ts +111 -0
- package/src/shared/static-platform-files.ts +75 -0
- package/dist/_chunks/build-output-helper-DOGYFb_X.js +0 -196
- package/dist/_chunks/build-output-helper-DOGYFb_X.js.map +0 -1
- package/dist/_chunks/cache-api-B-lhk9p4.js.map +0 -1
- package/dist/_chunks/canonicalize-DQHyFClh.js.map +0 -1
- package/dist/_chunks/cli-schema-sync-BTWEKJXo.js +0 -668
- package/dist/_chunks/cli-schema-sync-BTWEKJXo.js.map +0 -1
- package/dist/_chunks/define-COtkxMRT.js +0 -191
- package/dist/_chunks/define-COtkxMRT.js.map +0 -1
- package/dist/_chunks/define-c4au4I9R.js +0 -82
- package/dist/_chunks/define-c4au4I9R.js.map +0 -1
- package/dist/_chunks/fast-hash-D6hIVt1Y.js.map +0 -1
- package/dist/_chunks/logger-AWfuX-KJ.js.map +0 -1
- package/dist/_chunks/navigation-root-bUDZLw74.js +0 -124
- package/dist/_chunks/navigation-root-bUDZLw74.js.map +0 -1
- package/dist/_chunks/plugin-context---kTF5v8.js.map +0 -1
- package/dist/_chunks/registry-DbJPKoBp.js +0 -20
- package/dist/_chunks/registry-DbJPKoBp.js.map +0 -1
- package/dist/_chunks/router-ref-CtmF-aPv.js.map +0 -1
- package/dist/_chunks/schema-bridge-DT_Tn0Xf.js +0 -119
- package/dist/_chunks/schema-bridge-DT_Tn0Xf.js.map +0 -1
- package/dist/_chunks/segment-classify-Byy425ng.js.map +0 -1
- package/dist/_chunks/segment-context-ZDnXDkbz.js +0 -34
- package/dist/_chunks/segment-context-ZDnXDkbz.js.map +0 -1
- package/dist/_chunks/ssr-data-BOWsq18U.js.map +0 -1
- package/dist/_chunks/use-query-states-DFvWd-EA.js.map +0 -1
- package/dist/_chunks/use-segment-params-D1CzlgBo.js +0 -151
- package/dist/_chunks/use-segment-params-D1CzlgBo.js.map +0 -1
- package/dist/_chunks/walkers-_6zKFlch.js +0 -1002
- package/dist/_chunks/walkers-_6zKFlch.js.map +0 -1
- package/dist/client/error-boundary.js.map +0 -1
- package/dist/plugins/request-dep.d.ts +0 -32
- package/dist/plugins/request-dep.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/segment-params/define.d.ts +0 -89
- package/dist/segment-params/define.d.ts.map +0 -1
- package/dist/segment-params/index.d.ts +0 -3
- package/dist/segment-params/index.d.ts.map +0 -1
- package/dist/segment-params/index.js +0 -2
- package/src/plugins/request-dep.ts +0 -499
- package/src/search-params/registry.ts +0 -31
- package/src/segment-params/define.ts +0 -249
- package/src/segment-params/index.ts +0 -9
|
@@ -11,14 +11,14 @@
|
|
|
11
11
|
'use client';
|
|
12
12
|
|
|
13
13
|
import { useQueryStates as nuqsUseQueryStates } from 'nuqs';
|
|
14
|
-
import type {
|
|
14
|
+
import type { MultiParser } from 'nuqs';
|
|
15
15
|
import type {
|
|
16
16
|
SearchParamCodec,
|
|
17
17
|
SearchParamsDefinition,
|
|
18
18
|
SetParams,
|
|
19
19
|
QueryStatesOptions,
|
|
20
20
|
} from '../search-params/define.js';
|
|
21
|
-
import {
|
|
21
|
+
import { parseTotal } from '../search-params/parse-total.js';
|
|
22
22
|
|
|
23
23
|
// ─── Codec Bridge ─────────────────────────────────────────────────
|
|
24
24
|
|
|
@@ -50,32 +50,80 @@ function unwrapNuqsValue(value: unknown): unknown {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
/**
|
|
53
|
-
* Bridge a timber SearchParamCodec to a nuqs-compatible
|
|
53
|
+
* Bridge a timber SearchParamCodec to a nuqs-compatible MultiParser.
|
|
54
54
|
*
|
|
55
55
|
* nuqs parsers: { parse(string) → T|null, serialize?(T) → string, eq?, defaultValue? }
|
|
56
56
|
* timber codecs: { parse(string|string[]|undefined) → T, serialize(T) → string|null }
|
|
57
57
|
*
|
|
58
|
-
* The defaultValue is computed eagerly
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
58
|
+
* The defaultValue is computed eagerly, through `parseTotal` — the same
|
|
59
|
+
* entry point server-side `parse()` uses, so the hook and the server agree
|
|
60
|
+
* on what an absent param means (a bare nuqs parser answers `null`, not
|
|
61
|
+
* `undefined`; TIM-1350). Codecs are documented to return a default rather
|
|
62
|
+
* than throw, but a throwing codec must not crash every component that
|
|
63
|
+
* mounts the hook — treat its default as undefined and let its error
|
|
64
|
+
* surface from server-side parse() instead.
|
|
65
|
+
*
|
|
66
|
+
* A `null` absent-value is NOT registered as the nuqs default. nuqs
|
|
67
|
+
* already represents an absent key as `null`, so the hook reads the same
|
|
68
|
+
* value either way — but registering it makes `clearOnDefault` fire on
|
|
69
|
+
* `setParams({ q: null })` and delete the key before the bridged
|
|
70
|
+
* `serialize` runs. For a codec that encodes `null` as a real query value
|
|
71
|
+
* (`serialize(null) === 'none'`), that silently disagrees with
|
|
72
|
+
* `buildSearchParams({ q: null })`, which writes it. Same reasoning as
|
|
73
|
+
* `getDefaultSerialized` on the server: a codec with no value for an
|
|
74
|
+
* absent param has no default to register.
|
|
62
75
|
*/
|
|
63
|
-
function bridgeCodec<T>(codec: SearchParamCodec<T>):
|
|
64
|
-
let
|
|
76
|
+
function bridgeCodec<T>(codec: SearchParamCodec<T>): MultiParser<T> & { defaultValue: T } {
|
|
77
|
+
let absent: unknown;
|
|
65
78
|
try {
|
|
66
|
-
|
|
79
|
+
absent = parseTotal(codec, undefined);
|
|
67
80
|
} catch {
|
|
68
|
-
|
|
81
|
+
absent = undefined;
|
|
69
82
|
}
|
|
70
|
-
|
|
71
|
-
|
|
83
|
+
|
|
84
|
+
const parser = {
|
|
85
|
+
// `multi`, so nuqs reads the key with `searchParams.getAll()` and hands
|
|
86
|
+
// us EVERY value. A single parser reads `.get()` — the first value only
|
|
87
|
+
// — which is not the domain a timber codec is defined over. The server
|
|
88
|
+
// parses `?tags=a&tags=b` as `['a','b']`; a single parser made the hook
|
|
89
|
+
// answer `['a']` for the same URL, under a declared `string[]` that
|
|
90
|
+
// admitted no such disagreement (TIM-1352). Scalar codecs are unaffected:
|
|
91
|
+
// they receive the array and take `value[0]`, exactly as they do on the
|
|
92
|
+
// server, so first-value-wins is preserved through the same code path
|
|
93
|
+
// rather than through nuqs's reader.
|
|
94
|
+
//
|
|
95
|
+
// nuqs never calls this with an empty array — `isAbsentFromUrl` treats
|
|
96
|
+
// `[]` as absent and answers `defaultValue` directly — which is what
|
|
97
|
+
// keeps the absent case agreeing with the server's `undefined`.
|
|
98
|
+
//
|
|
99
|
+
// Reading every value is only half of it: the values must arrive in the
|
|
100
|
+
// SAME SHAPE the server would have produced, or the divergence just
|
|
101
|
+
// moves. `normalizeRaw` (search-params/define.ts) collapses a
|
|
102
|
+
// single-valued key to a bare string and keeps an array only for a
|
|
103
|
+
// repeated one, so this mirrors that rule exactly. Handing a codec
|
|
104
|
+
// `['3']` where the server hands it `'3'` breaks every codec whose
|
|
105
|
+
// `parse` is written for the scalar case — which is most hand-written
|
|
106
|
+
// ones, contract or no contract.
|
|
107
|
+
type: 'multi' as const,
|
|
108
|
+
// Through parseTotal, not codec.parse. nuqs's own `.withDefault(d)`
|
|
109
|
+
// overrides ONLY `parseServerSide`, so `parseAsInteger.withDefault(1)`
|
|
110
|
+
// on `?page=abc` returned 1 from the server and null from the hook —
|
|
111
|
+
// a divergence the declared non-nullable `number` did not admit.
|
|
112
|
+
parse: (v: readonly string[]) =>
|
|
113
|
+
wrapNuqsValue(parseTotal(codec, v.length === 1 ? v[0] : [...v])),
|
|
72
114
|
serialize: (v: unknown) => {
|
|
73
115
|
const value = unwrapNuqsValue(v);
|
|
74
116
|
// Delegate null to the codec — some codecs encode null as a real
|
|
75
117
|
// query value. undefined has no encoding; nuqs requires a string.
|
|
76
|
-
|
|
118
|
+
//
|
|
119
|
+
// ONE element, always. A multi parser may return several — nuqs
|
|
120
|
+
// appends one key per entry — but `Codec.serialize` returns a single
|
|
121
|
+
// string by construction, so timber cannot emit repeated keys here
|
|
122
|
+
// any more than `buildSearchParams` can. Widening that protocol is
|
|
123
|
+
// TIM-1353. Wrapping the same string keeps the URL the hook writes
|
|
124
|
+
// byte-identical to the one `buildSearchParams` writes.
|
|
125
|
+
return [value === undefined ? '' : (codec.serialize(value as T) ?? '')];
|
|
77
126
|
},
|
|
78
|
-
defaultValue: wrapNuqsValue(defaultValue),
|
|
79
127
|
eq: (a: unknown, b: unknown) => {
|
|
80
128
|
if (a === b) return true;
|
|
81
129
|
try {
|
|
@@ -86,7 +134,26 @@ function bridgeCodec<T>(codec: SearchParamCodec<T>): SingleParser<T> & { default
|
|
|
86
134
|
return false;
|
|
87
135
|
}
|
|
88
136
|
},
|
|
89
|
-
} as
|
|
137
|
+
} as MultiParser<T> & { defaultValue: T };
|
|
138
|
+
|
|
139
|
+
if (absent !== null) parser.defaultValue = wrapNuqsValue(absent) as T;
|
|
140
|
+
return parser;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Collect `withUrlKey` aliases off a codec map.
|
|
145
|
+
*
|
|
146
|
+
* `withUrlKey(codec, 'q')` returns a codec carrying `urlKey: 'q'`, so the map
|
|
147
|
+
* alone is enough to reconstruct the aliases — `defineSearchParams` builds its
|
|
148
|
+
* own `urlKeys` from exactly this property.
|
|
149
|
+
*/
|
|
150
|
+
function deriveUrlKeys(codecs: Record<string, SearchParamCodec<unknown>>): Record<string, string> {
|
|
151
|
+
const result: Record<string, string> = {};
|
|
152
|
+
for (const key of Object.keys(codecs)) {
|
|
153
|
+
const alias = codecs[key]?.urlKey;
|
|
154
|
+
if (alias) result[key] = alias;
|
|
155
|
+
}
|
|
156
|
+
return result;
|
|
90
157
|
}
|
|
91
158
|
|
|
92
159
|
/**
|
|
@@ -95,12 +162,12 @@ function bridgeCodec<T>(codec: SearchParamCodec<T>): SingleParser<T> & { default
|
|
|
95
162
|
function bridgeCodecs<T extends Record<string, unknown>>(codecs: {
|
|
96
163
|
[K in keyof T]: SearchParamCodec<T[K]>;
|
|
97
164
|
}) {
|
|
98
|
-
const result: Record<string,
|
|
165
|
+
const result: Record<string, MultiParser<unknown> & { defaultValue: unknown }> = {};
|
|
99
166
|
for (const key of Object.keys(codecs)) {
|
|
100
167
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
101
168
|
result[key] = bridgeCodec(codecs[key as keyof T]) as any;
|
|
102
169
|
}
|
|
103
|
-
return result as { [K in keyof T]:
|
|
170
|
+
return result as { [K in keyof T]: MultiParser<T[K]> & { defaultValue: T[K] } };
|
|
104
171
|
}
|
|
105
172
|
|
|
106
173
|
// ─── Hook ─────────────────────────────────────────────────────────
|
|
@@ -113,7 +180,7 @@ function bridgeCodecs<T extends Record<string, unknown>>(codecs: {
|
|
|
113
180
|
*
|
|
114
181
|
* Usage:
|
|
115
182
|
* ```ts
|
|
116
|
-
* // Via a SearchParamsDefinition
|
|
183
|
+
* // Via a SearchParamsDefinition imported from the route's params.ts
|
|
117
184
|
* const [params, setParams] = definition.useQueryStates()
|
|
118
185
|
*
|
|
119
186
|
* // Standalone with inline codecs
|
|
@@ -121,30 +188,18 @@ function bridgeCodecs<T extends Record<string, unknown>>(codecs: {
|
|
|
121
188
|
* page: fromSchema(z.coerce.number().int().min(1).default(1)),
|
|
122
189
|
* })
|
|
123
190
|
* ```
|
|
191
|
+
*
|
|
192
|
+
* There is deliberately no route-string form (`useQueryStates('/products')`).
|
|
193
|
+
* Importing the definition from `params.ts` is the documented way to reach
|
|
194
|
+
* another route's codecs — it needs no runtime registry lookup and so has no
|
|
195
|
+
* "not registered yet" failure mode. See design/23-search-params.md
|
|
196
|
+
* §"Client Access".
|
|
124
197
|
*/
|
|
125
198
|
export function useQueryStates<T extends Record<string, unknown>>(
|
|
126
|
-
|
|
199
|
+
codecs: { [K in keyof T]: SearchParamCodec<T[K]> },
|
|
127
200
|
_options?: QueryStatesOptions,
|
|
128
201
|
urlKeys?: Readonly<Record<string, string>>
|
|
129
202
|
): [T, SetParams<T>] {
|
|
130
|
-
// Route-string overload: resolve codecs from the registry
|
|
131
|
-
let codecs: { [K in keyof T]: SearchParamCodec<T[K]> };
|
|
132
|
-
let resolvedUrlKeys = urlKeys;
|
|
133
|
-
if (typeof codecsOrRoute === 'string') {
|
|
134
|
-
const definition = getSearchParamsDefinition(codecsOrRoute);
|
|
135
|
-
if (!definition) {
|
|
136
|
-
throw new Error(
|
|
137
|
-
`useQueryStates('${codecsOrRoute}'): no search params registered for this route. ` +
|
|
138
|
-
`Either the route has no search-params.ts file, or it hasn't been loaded yet. ` +
|
|
139
|
-
`For cross-route usage, import the definition explicitly.`
|
|
140
|
-
);
|
|
141
|
-
}
|
|
142
|
-
codecs = definition.codecs as { [K in keyof T]: SearchParamCodec<T[K]> };
|
|
143
|
-
resolvedUrlKeys = definition.urlKeys;
|
|
144
|
-
} else {
|
|
145
|
-
codecs = codecsOrRoute;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
203
|
const bridged = bridgeCodecs(codecs);
|
|
149
204
|
|
|
150
205
|
// Forward hook-level options (shallow, scroll, history) to nuqs.
|
|
@@ -155,7 +210,15 @@ export function useQueryStates<T extends Record<string, unknown>>(
|
|
|
155
210
|
if (_options?.shallow !== undefined) nuqsOptions.shallow = _options.shallow;
|
|
156
211
|
if (_options?.scroll !== undefined) nuqsOptions.scroll = _options.scroll;
|
|
157
212
|
if (_options?.history !== undefined) nuqsOptions.history = _options.history;
|
|
158
|
-
|
|
213
|
+
// `withUrlKey` attaches the alias to the codec itself — that is the design's
|
|
214
|
+
// "URL keys travel with codecs" principle — so the aliases are derivable
|
|
215
|
+
// here and must be, for the inline codec-map form: nobody passes `urlKeys`
|
|
216
|
+
// on that path, and without this an aliased bundle silently read and wrote
|
|
217
|
+
// the property name instead of the alias. `bindUseQueryStates` still passes
|
|
218
|
+
// the definition's precomputed map, which wins on conflict; it is built from
|
|
219
|
+
// these same codecs, so the two agree by construction rather than by luck.
|
|
220
|
+
const resolvedUrlKeys = { ...deriveUrlKeys(codecs), ...urlKeys };
|
|
221
|
+
if (Object.keys(resolvedUrlKeys).length > 0) {
|
|
159
222
|
nuqsOptions.urlKeys = resolvedUrlKeys;
|
|
160
223
|
}
|
|
161
224
|
|
package/src/client/use-router.ts
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* In timber, navigation calls reactRoot.render() which is a root-level
|
|
15
15
|
* render — startTransition has no effect on root renders.
|
|
16
16
|
*
|
|
17
|
-
* Navigation state (
|
|
17
|
+
* Navigation state (pathname, search) is delivered atomically via
|
|
18
18
|
* NavigationContext embedded in the element tree passed to
|
|
19
19
|
* reactRoot.render(). See design/19-client-navigation.md §"NavigationContext".
|
|
20
20
|
*
|
|
@@ -18,11 +18,11 @@
|
|
|
18
18
|
* (populated by ssr-entry.ts) to ensure correct per-request isolation
|
|
19
19
|
* across concurrent requests with streaming Suspense.
|
|
20
20
|
*
|
|
21
|
-
* Reactivity: On the client, useParams() reads from
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
21
|
+
* Reactivity: On the client, useParams() reads from ParamsContext, published
|
|
22
|
+
* by the one provider the client renders above the merge point
|
|
23
|
+
* (`PayloadRoot`). Params update atomically with the tree because they travel
|
|
24
|
+
* on the same payload root — there is no separate channel that could be
|
|
25
|
+
* seeded a render early or late (TIM-1294, TIM-1297).
|
|
26
26
|
*
|
|
27
27
|
* All mutable state is delegated to client/state.ts for singleton guarantees.
|
|
28
28
|
* See design/18-build-system.md §"Singleton State Registry"
|
|
@@ -32,8 +32,15 @@
|
|
|
32
32
|
|
|
33
33
|
import type { Routes } from '../index.js';
|
|
34
34
|
import { getSsrData } from './ssr-data.js';
|
|
35
|
-
import {
|
|
36
|
-
|
|
35
|
+
import {
|
|
36
|
+
currentParams,
|
|
37
|
+
currentSlotParams,
|
|
38
|
+
_setCurrentParams,
|
|
39
|
+
_setCurrentSlotParams,
|
|
40
|
+
paramsListeners,
|
|
41
|
+
} from './state.js';
|
|
42
|
+
import { resolveSegmentParams, type SlotParamsRecord } from '../shared/slot-params.js';
|
|
43
|
+
import { useParamsContext } from './params-context.js';
|
|
37
44
|
|
|
38
45
|
// ---------------------------------------------------------------------------
|
|
39
46
|
// Module-level subscribe/notify pattern — kept for backward compat and tests
|
|
@@ -81,6 +88,18 @@ export function setCurrentParams(params: Record<string, string | string[]>): voi
|
|
|
81
88
|
_setCurrentParams(params);
|
|
82
89
|
}
|
|
83
90
|
|
|
91
|
+
/**
|
|
92
|
+
* Set the per-slot params snapshot in the module-level store.
|
|
93
|
+
*
|
|
94
|
+
* Paired with `setCurrentParams`: the router calls both on every navigation,
|
|
95
|
+
* including with `null` when a response carries no slot params, so a slot's
|
|
96
|
+
* params from the *previous* route cannot be read on the next one. Fill and
|
|
97
|
+
* serve are paired; so are fill and clear. See TIM-1285.
|
|
98
|
+
*/
|
|
99
|
+
export function setCurrentSlotParams(slotParams: SlotParamsRecord | null): void {
|
|
100
|
+
_setCurrentSlotParams(slotParams);
|
|
101
|
+
}
|
|
102
|
+
|
|
84
103
|
/**
|
|
85
104
|
* Notify all legacy subscribers that params have changed.
|
|
86
105
|
*
|
|
@@ -105,9 +124,9 @@ export function notifyParamsListeners(): void {
|
|
|
105
124
|
* The optional `_route` argument exists only for TypeScript narrowing —
|
|
106
125
|
* it does not affect the runtime return value.
|
|
107
126
|
*
|
|
108
|
-
* On the client, reads from
|
|
109
|
-
*
|
|
110
|
-
*
|
|
127
|
+
* On the client, reads from ParamsContext, published by `PayloadRoot` above
|
|
128
|
+
* everything the navigation renders. Params update atomically with the RSC
|
|
129
|
+
* tree — no timing gap.
|
|
111
130
|
*
|
|
112
131
|
* During SSR, reads from the ALS-backed SSR data context to ensure
|
|
113
132
|
* per-request isolation across concurrent requests with streaming Suspense.
|
|
@@ -123,15 +142,17 @@ export function useSegmentParams<R extends keyof Routes>(
|
|
|
123
142
|
segmentPath: R
|
|
124
143
|
): Routes[R] extends { segmentParams: infer P } ? P : Record<string, string | string[]>;
|
|
125
144
|
export function useSegmentParams(segmentPath?: string): Record<string, string | string[]>;
|
|
126
|
-
export function useSegmentParams(
|
|
127
|
-
// Try
|
|
128
|
-
//
|
|
129
|
-
//
|
|
145
|
+
export function useSegmentParams(segmentPath?: string): Record<string, string | string[]> {
|
|
146
|
+
// Try the client-owned provider first. It sits above everything a navigation
|
|
147
|
+
// renders, so any component on the page — initial document, full navigation,
|
|
148
|
+
// or a layout the server skipped — has one above it. Absent during SSR,
|
|
149
|
+
// where the ALS path below is the answer. When called outside a React
|
|
150
|
+
// component, useContext throws — caught below.
|
|
130
151
|
try {
|
|
131
152
|
// eslint-disable-next-line react-hooks/rules-of-hooks -- conditional on environment, not render path
|
|
132
|
-
const
|
|
133
|
-
if (
|
|
134
|
-
return
|
|
153
|
+
const paramsContext = useParamsContext();
|
|
154
|
+
if (paramsContext !== null) {
|
|
155
|
+
return resolveSegmentParams(paramsContext.params, paramsContext.slotParams, segmentPath);
|
|
135
156
|
}
|
|
136
157
|
} catch {
|
|
137
158
|
// No React dispatcher available (called outside a component).
|
|
@@ -140,5 +161,7 @@ export function useSegmentParams(_segmentPath?: string): Record<string, string |
|
|
|
140
161
|
|
|
141
162
|
// SSR path: read from ALS-backed SSR data context.
|
|
142
163
|
// Falls back to module-level currentParams for tests.
|
|
143
|
-
|
|
164
|
+
const ssrData = getSsrData();
|
|
165
|
+
if (ssrData) return resolveSegmentParams(ssrData.params, ssrData.slotParams, segmentPath);
|
|
166
|
+
return resolveSegmentParams(currentParams, currentSlotParams, segmentPath);
|
|
144
167
|
}
|
|
@@ -147,7 +147,12 @@ function deleteClientCookie(name: string, options?: ClientCookieOptions): void {
|
|
|
147
147
|
// ─── Standard Schema Auto-Detection ───────────────────────────────────────
|
|
148
148
|
|
|
149
149
|
function resolveCodec<T>(codecOrSchema: CookieCodec<T> | StandardSchemaV1<T>): CookieCodec<T> {
|
|
150
|
-
|
|
150
|
+
// 'cookie', not 'search': a cookie carries one string per name, so the
|
|
151
|
+
// repeated-key array shape the search bridge tolerates does not exist
|
|
152
|
+
// here — and `serialize` returning `null` means DELETE for a cookie
|
|
153
|
+
// where it means "omit the key" for a search param. See
|
|
154
|
+
// schema-bridge.ts §fromCookieSchema.
|
|
155
|
+
return resolveCodecOrSchema('codec', codecOrSchema, 'cookie') as CookieCodec<T>;
|
|
151
156
|
}
|
|
152
157
|
|
|
153
158
|
// ─── Factory ──────────────────────────────────────────────────────────────
|
package/src/index.ts
CHANGED
|
@@ -31,7 +31,7 @@ import { timberChunks } from './plugins/chunks';
|
|
|
31
31
|
import { clientChunkGroup } from './plugins/client-chunks';
|
|
32
32
|
import { timberServerBundle } from './plugins/server-bundle';
|
|
33
33
|
import { timberCacheTransform } from './plugins/cache';
|
|
34
|
-
import { timberRequestDep } from './plugins/request-dep';
|
|
34
|
+
import { timberRequestDep } from './plugins/request-dep/index.js';
|
|
35
35
|
import { timberPrebuilt } from './plugins/prebuilt';
|
|
36
36
|
import { timberPrerenderSugar } from './plugins/prerender-sugar';
|
|
37
37
|
import { timberCloudflareWasm } from './plugins/cloudflare-wasm';
|
|
@@ -42,7 +42,7 @@ import { resolveEncryptionKeyExpression, shouldEnableEncryption } from './server
|
|
|
42
42
|
import { createHoldingServer } from './dev-tools/holding-server.js';
|
|
43
43
|
import { resolveStartPort, startDevServerPort } from './server/port-resolution.js';
|
|
44
44
|
import type { TimberUserConfig } from './config-types.js';
|
|
45
|
-
import type { PluginContext } from './plugin-context.js';
|
|
45
|
+
import type { PluginContext, TimberPluginApi } from './plugin-context.js';
|
|
46
46
|
import {
|
|
47
47
|
createPluginContext,
|
|
48
48
|
loadTimberConfigFile,
|
|
@@ -69,7 +69,10 @@ export type { Metadata, MetadataRoute, MetadataHandler, MetadataResult } from '.
|
|
|
69
69
|
*
|
|
70
70
|
* Each key is a route path pattern. Values have:
|
|
71
71
|
* segmentParams: shape of URL segment params (e.g. { id: string })
|
|
72
|
-
*
|
|
72
|
+
*
|
|
73
|
+
* There is no `searchParams` member: since TIM-1343 the framework does not
|
|
74
|
+
* scan for search-param definitions, so it has nothing to type them with. A
|
|
75
|
+
* definition carries its own type to call sites through an ordinary import.
|
|
73
76
|
*
|
|
74
77
|
* This interface is empty by default and populated via codegen.
|
|
75
78
|
* See design/09-typescript.md §"Typed Routes".
|
|
@@ -245,6 +248,21 @@ export function timber(config?: TimberUserConfig): PluginOption[] {
|
|
|
245
248
|
// config() hook must NOT return a `plugins` field (Vite ignores it).
|
|
246
249
|
const rootSync: Plugin = {
|
|
247
250
|
name: 'timber-root-sync',
|
|
251
|
+
|
|
252
|
+
// The plugin context, published for out-of-band callers that need the
|
|
253
|
+
// *resolved* configuration rather than a second reading of the files it
|
|
254
|
+
// came from. `timber check` is the one today: it runs Vite's
|
|
255
|
+
// `resolveConfig()` and reads root, appDir, and pageExtensions from here,
|
|
256
|
+
// so it scans exactly the tree `timber build` builds — including config
|
|
257
|
+
// passed inline as `timber({ ... })`, which lives only in this closure and
|
|
258
|
+
// is invisible to anything that re-reads `timber.config.ts`. See
|
|
259
|
+
// `cli-check.ts` and design/11-platform.md §`timber check`.
|
|
260
|
+
//
|
|
261
|
+
// Valid from `configResolved` onward; `appDir` and `root` are unset before
|
|
262
|
+
// that, which is why the reader runs a full `resolveConfig()` rather than
|
|
263
|
+
// just loading the config file.
|
|
264
|
+
api: { getContext: () => ctx } satisfies TimberPluginApi,
|
|
265
|
+
|
|
248
266
|
async config(userConfig, { command, isPreview }) {
|
|
249
267
|
// ── Load timber.config.ts from the correct root ───────────────
|
|
250
268
|
// Vite's `config` hook fires before `configResolved`. The user's
|
|
@@ -388,7 +406,6 @@ export function timber(config?: TimberUserConfig): PluginOption[] {
|
|
|
388
406
|
'@timber-js/app/cookies',
|
|
389
407
|
'@timber-js/app/cache',
|
|
390
408
|
'@timber-js/app/search-params',
|
|
391
|
-
'@timber-js/app/segment-params',
|
|
392
409
|
'@timber-js/app/params',
|
|
393
410
|
'@timber-js/app/codec',
|
|
394
411
|
];
|
|
@@ -464,6 +481,10 @@ export function timber(config?: TimberUserConfig): PluginOption[] {
|
|
|
464
481
|
ctx.root = resolved.root;
|
|
465
482
|
ctx.appDir = resolveAppDir(resolved.root, ctx.config.appDir);
|
|
466
483
|
ctx.dev = resolved.command === 'serve';
|
|
484
|
+
// Vite's resolved base — the deployment path prefix. Captured once
|
|
485
|
+
// here so every sub-plugin that emits a URL (assets, fonts, RSC
|
|
486
|
+
// payloads) reads the same value. See TIM-1261.
|
|
487
|
+
ctx.base = resolved.base;
|
|
467
488
|
|
|
468
489
|
// Register all timber config file candidates as Vite config file
|
|
469
490
|
// dependencies so Vite's built-in restart-on-change handles them
|
package/src/plugin-context.ts
CHANGED
|
@@ -73,6 +73,21 @@ export interface PluginContext {
|
|
|
73
73
|
root: string;
|
|
74
74
|
/** Whether the dev server is running (set by timber-root-sync in configResolved) */
|
|
75
75
|
dev: boolean;
|
|
76
|
+
/**
|
|
77
|
+
* Vite's resolved `base` (set by timber-root-sync in configResolved).
|
|
78
|
+
* Always has a trailing slash; `'/'` unless the app is deployed under a
|
|
79
|
+
* sub-path. Every URL the framework emits — assets, fonts, RSC payloads —
|
|
80
|
+
* carries this prefix. This is the single copy: sub-plugins read it here
|
|
81
|
+
* rather than capturing `config.base` in their own configResolved.
|
|
82
|
+
*
|
|
83
|
+
* **Availability:** written by timber-root-sync, which has no `enforce`, so
|
|
84
|
+
* it is populated from `buildStart`/`load`/`generateBundle`/`configureServer`
|
|
85
|
+
* onward — but NOT during the `configResolved` of an `enforce: 'pre'`
|
|
86
|
+
* plugin, which Vite runs first. A pre plugin that needs the base inside
|
|
87
|
+
* its own `configResolved` must read `config.base` there (timber-fonts
|
|
88
|
+
* does). See TIM-1261.
|
|
89
|
+
*/
|
|
90
|
+
base: string;
|
|
76
91
|
/** CSS build manifest (populated by adapter after client build, null in dev) */
|
|
77
92
|
buildManifest: BuildManifest | null;
|
|
78
93
|
/** Per-build deployment ID for version skew detection (null in dev) */
|
|
@@ -98,6 +113,22 @@ export interface PluginContext {
|
|
|
98
113
|
* populate per-route modulepreload entries from clientReferenceDeps.
|
|
99
114
|
*/
|
|
100
115
|
routeClientRefKeys?: Map<string, Set<string>>;
|
|
116
|
+
/**
|
|
117
|
+
* Static request-dependency verdict per segment entry file, keyed by the
|
|
118
|
+
* absolute `filePath` the route scanner produced. Computed once by
|
|
119
|
+
* `timber-request-dep`'s RSC `buildEnd` and serialized into
|
|
120
|
+
* `buildManifest.requestDep` by `timber-build-manifest` (build only — dev
|
|
121
|
+
* answers the same question through the `Symbol.for('timber:request-dep')`
|
|
122
|
+
* bridge instead).
|
|
123
|
+
*
|
|
124
|
+
* `undefined` and `{}` are different states and the difference is the whole
|
|
125
|
+
* of TIM-1300: an empty object means the analysis ran and found no segments,
|
|
126
|
+
* `undefined` means it never ran, and the runtime cannot tell them apart —
|
|
127
|
+
* every key is absent either way, so every segment falls to the conservative
|
|
128
|
+
* `true` and nothing is ever skipped. The build fails loudly on `undefined`
|
|
129
|
+
* rather than shipping that silently.
|
|
130
|
+
*/
|
|
131
|
+
requestDepMap?: Record<string, boolean>;
|
|
101
132
|
/**
|
|
102
133
|
* Maps absolute module IDs of client references in non-facade RSC
|
|
103
134
|
* chunks to the absolute paths of their consuming facade modules.
|
|
@@ -217,6 +248,32 @@ export class ParseMemo {
|
|
|
217
248
|
|
|
218
249
|
// ── App directory resolution ──────────────────────────────────────────────
|
|
219
250
|
|
|
251
|
+
// ── Plugin API (Vite `plugin.api`) ────────────────────────────────────────
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* What `timber-root-sync` publishes on its Vite `plugin.api`.
|
|
255
|
+
*
|
|
256
|
+
* The single supported way to read timber's *resolved* configuration from
|
|
257
|
+
* outside the plugin pipeline. Re-reading `timber.config.ts` is not equivalent:
|
|
258
|
+
* config passed inline as `timber({ ... })` in `vite.config.ts` exists only in
|
|
259
|
+
* the plugin's closure, and `root`/`appDir` are resolved against Vite's root
|
|
260
|
+
* rather than the caller's cwd.
|
|
261
|
+
*/
|
|
262
|
+
export interface TimberPluginApi {
|
|
263
|
+
/** The live plugin context. Fully populated from `configResolved` onward. */
|
|
264
|
+
getContext(): PluginContext;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/** Narrow an unknown Vite `plugin.api` to timber's. */
|
|
268
|
+
export function isTimberPluginApi(api: unknown): api is TimberPluginApi {
|
|
269
|
+
return (
|
|
270
|
+
typeof api === 'object' &&
|
|
271
|
+
api !== null &&
|
|
272
|
+
'getContext' in api &&
|
|
273
|
+
typeof api.getContext === 'function'
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
|
|
220
277
|
/**
|
|
221
278
|
* Resolve the app directory. Checks (in order):
|
|
222
279
|
* 1. Explicit `configAppDir` from timber.config.ts
|
|
@@ -258,6 +315,7 @@ export function createPluginContext(config?: TimberUserConfig, root?: string): P
|
|
|
258
315
|
appDir: join(projectRoot, 'app'),
|
|
259
316
|
root: projectRoot,
|
|
260
317
|
dev: false,
|
|
318
|
+
base: '/',
|
|
261
319
|
buildManifest: null,
|
|
262
320
|
deploymentId: null,
|
|
263
321
|
timer: createStartupTimer(),
|
|
@@ -21,6 +21,7 @@ import type { PluginContext } from '../plugin-context.js';
|
|
|
21
21
|
import type { TimberPlatformAdapter, TimberConfig } from '../adapters/types.js';
|
|
22
22
|
import type { BuildManifest } from '../server/build-manifest.js';
|
|
23
23
|
import { swallow } from '../server/logger.js';
|
|
24
|
+
import { normalizeBasePath } from '../shared/base-path.js';
|
|
24
25
|
|
|
25
26
|
export function timberAdapterBuild(ctx: PluginContext): Plugin {
|
|
26
27
|
return {
|
|
@@ -85,6 +86,9 @@ export function timberAdapterBuild(ctx: PluginContext): Plugin {
|
|
|
85
86
|
|
|
86
87
|
const adapterConfig: TimberConfig = {
|
|
87
88
|
root: ctx.root,
|
|
89
|
+
// Normalized once here, not in each adapter: the platform files
|
|
90
|
+
// adapters write address deployed-URL space (TIM-1274).
|
|
91
|
+
base: normalizeBasePath(ctx.base),
|
|
88
92
|
output: ctx.config.output ?? 'server',
|
|
89
93
|
clientJavascriptDisabled: ctx.clientJavascript.disabled,
|
|
90
94
|
manifestInit,
|
|
@@ -20,7 +20,7 @@ import { randomUUID, createHash } from 'node:crypto';
|
|
|
20
20
|
import { readFileSync } from 'node:fs';
|
|
21
21
|
import type { Plugin, ResolvedConfig } from 'vite';
|
|
22
22
|
import type { PluginContext } from '../plugin-context.js';
|
|
23
|
-
import type
|
|
23
|
+
import { EMPTY_BUILD_MANIFEST, type BuildManifest } from '../server/build-manifest.js';
|
|
24
24
|
import type { SegmentNode, RouteFile } from '../routing/types.js';
|
|
25
25
|
import { isDynamicMetadataExtension } from '../server/metadata-routes.js';
|
|
26
26
|
|
|
@@ -335,14 +335,12 @@ function walkModuleImports(
|
|
|
335
335
|
* Hooks: configResolved, resolveId, load, generateBundle (client and RSC envs)
|
|
336
336
|
*/
|
|
337
337
|
export function timberBuildManifest(ctx: PluginContext): Plugin {
|
|
338
|
-
let resolvedBase = '/';
|
|
339
338
|
let isDev = false;
|
|
340
339
|
|
|
341
340
|
return {
|
|
342
341
|
name: 'timber-build-manifest',
|
|
343
342
|
|
|
344
343
|
configResolved(config: ResolvedConfig) {
|
|
345
|
-
resolvedBase = config.base;
|
|
346
344
|
isDev = config.command === 'serve';
|
|
347
345
|
|
|
348
346
|
// Generate a per-build deployment ID early so virtual:timber-config
|
|
@@ -373,13 +371,18 @@ export function timberBuildManifest(ctx: PluginContext): Plugin {
|
|
|
373
371
|
load(id: string) {
|
|
374
372
|
if (id !== RESOLVED_VIRTUAL_ID) return null;
|
|
375
373
|
|
|
374
|
+
// Serialized, not restated: an empty manifest is described once, in
|
|
375
|
+
// server/build-manifest.ts. Both branches below emitted their own object
|
|
376
|
+
// literal and had already drifted apart — see EMPTY_BUILD_MANIFEST.
|
|
377
|
+
const empty = JSON.stringify(EMPTY_BUILD_MANIFEST);
|
|
378
|
+
|
|
376
379
|
// In dev mode, return empty manifest — Vite HMR handles CSS.
|
|
377
380
|
if (isDev) {
|
|
378
381
|
return [
|
|
379
382
|
'// Auto-generated build manifest — do not edit.',
|
|
380
383
|
'// Dev mode: empty manifest (Vite HMR handles CSS/JS).',
|
|
381
384
|
'',
|
|
382
|
-
|
|
385
|
+
`const manifest = ${empty};`,
|
|
383
386
|
'',
|
|
384
387
|
'export default manifest;',
|
|
385
388
|
].join('\n');
|
|
@@ -389,11 +392,17 @@ export function timberBuildManifest(ctx: PluginContext): Plugin {
|
|
|
389
392
|
// The adapter writes a _timber-manifest-init.js that sets this global
|
|
390
393
|
// before the RSC handler imports this module. ESM evaluation order
|
|
391
394
|
// guarantees the global is set by the time this code runs.
|
|
395
|
+
//
|
|
396
|
+
// The literal is only reached when the global is unset — an app built
|
|
397
|
+
// with no adapter, which writes no init module. It is NOT the map the
|
|
398
|
+
// build computed; that lives in _timber-manifest-init.js (TIM-1300).
|
|
392
399
|
return [
|
|
393
400
|
'// Auto-generated build manifest — do not edit.',
|
|
394
401
|
'// Production: reads manifest from globalThis (set by _timber-manifest-init.js).',
|
|
402
|
+
'// The object below is only the fallback for when that global is unset —',
|
|
403
|
+
'// the real manifest, including the requestDep map, is in that init module.',
|
|
395
404
|
'',
|
|
396
|
-
|
|
405
|
+
`const manifest = globalThis.__TIMBER_BUILD_MANIFEST__ ?? ${empty};`,
|
|
397
406
|
'',
|
|
398
407
|
'export default manifest;',
|
|
399
408
|
].join('\n');
|
|
@@ -436,21 +445,33 @@ export function timberBuildManifest(ctx: PluginContext): Plugin {
|
|
|
436
445
|
}
|
|
437
446
|
|
|
438
447
|
if (envName === 'client') {
|
|
439
|
-
ctx.buildManifest = buildManifestFromBundle(bundle,
|
|
448
|
+
ctx.buildManifest = buildManifestFromBundle(bundle, ctx.base, ctx.root);
|
|
440
449
|
|
|
441
450
|
// Compute cache-busting hashes for metadata route files
|
|
442
451
|
if (ctx.routeTree) {
|
|
443
452
|
ctx.buildManifest.metadataRouteHashes = computeMetadataRouteHashes(ctx.routeTree.root);
|
|
444
453
|
}
|
|
445
454
|
|
|
446
|
-
// Attach static request-dependency map from the request-dep
|
|
447
|
-
//
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
455
|
+
// Attach the static request-dependency map from the request-dep
|
|
456
|
+
// plugin, computed in the RSC `buildEnd` hook. The RSC environment is
|
|
457
|
+
// built before the client one, so the field is populated by now.
|
|
458
|
+
//
|
|
459
|
+
// Absent means the RSC `buildEnd` never ran — a broken plugin pipeline,
|
|
460
|
+
// not an app without segments, which produces `{}`. Serializing that as
|
|
461
|
+
// an empty map is indistinguishable at runtime from an analysis that
|
|
462
|
+
// found nothing (`server/request-dep.ts` answers `true` for any absent
|
|
463
|
+
// key either way), so every segment and slot silently stops being a
|
|
464
|
+
// skip candidate and slot caching is off with nothing to show for it.
|
|
465
|
+
// Fail the build instead (TIM-1300).
|
|
466
|
+
if (ctx.requestDepMap === undefined) {
|
|
467
|
+
throw new Error(
|
|
468
|
+
'[timber] Build manifest: the request-dependency map was never computed. ' +
|
|
469
|
+
"The RSC environment's buildEnd hook did not run before the client build, " +
|
|
470
|
+
'so no segment or slot could be skipped on client navigation. This is a ' +
|
|
471
|
+
'plugin pipeline bug — timber-request-dep must run in the rsc environment.'
|
|
472
|
+
);
|
|
453
473
|
}
|
|
474
|
+
ctx.buildManifest.requestDep = ctx.requestDepMap;
|
|
454
475
|
|
|
455
476
|
// When client JavaScript is disabled, strip JS chunks from the bundle
|
|
456
477
|
// so Rollup never writes them to disk. CSS assets are preserved —
|
package/src/plugins/entries.ts
CHANGED
|
@@ -136,6 +136,10 @@ function generateConfigModule(ctx: PluginContext): string {
|
|
|
136
136
|
csrf: ctx.config.csrf ?? true,
|
|
137
137
|
allowedOrigins: ctx.config.allowedOrigins,
|
|
138
138
|
clientJavascript: ctx.clientJavascript,
|
|
139
|
+
// Vite's resolved `base` — the deployment path prefix. The client needs
|
|
140
|
+
// it to address pre-generated RSC payloads in static mode, which live
|
|
141
|
+
// below the base like every other emitted file (TIM-1261).
|
|
142
|
+
base: ctx.base,
|
|
139
143
|
dev: ctx.dev ?? false,
|
|
140
144
|
slowPhaseMs: ctx.config.dev?.slowPhaseMs ?? 200,
|
|
141
145
|
slowRequestMs: ctx.config.slowRequestMs ?? 3000,
|