@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
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
|
|
13
13
|
import type { ReactNode } from 'react';
|
|
14
14
|
import type { RouteFile, SegmentNode } from '../routing/types.js';
|
|
15
|
+
import { wrapSegmentWithErrorBoundaries } from './error-boundary-wrapper.js';
|
|
16
|
+
import type { LoadedComponent } from './utils/element-type.js';
|
|
15
17
|
|
|
16
18
|
// ─── Types ───────────────────────────────────────────────────────────────────
|
|
17
19
|
|
|
@@ -26,69 +28,6 @@ export interface LoadedModule {
|
|
|
26
28
|
/** Function that loads a route file's module. */
|
|
27
29
|
export type ModuleLoader = (file: RouteFile) => LoadedModule | Promise<LoadedModule>;
|
|
28
30
|
|
|
29
|
-
/**
|
|
30
|
-
* A React component reference loaded from a route module's default export.
|
|
31
|
-
*
|
|
32
|
-
* Loaded modules' `default` is typed as `unknown` (modules are dynamic), so
|
|
33
|
-
* call sites narrow it through `isValidElementType` (below) before treating
|
|
34
|
-
* it as a component. The signature is a callable returning `ReactNode` —
|
|
35
|
-
* TypeScript's view of every valid React component shape, including exotic
|
|
36
|
-
* components (`memo`, `forwardRef`, `lazy`) which the type system treats as
|
|
37
|
-
* callable even though their runtime values are objects with `$$typeof`
|
|
38
|
-
* markers rather than functions.
|
|
39
|
-
*/
|
|
40
|
-
export type LoadedComponent = (...args: unknown[]) => ReactNode;
|
|
41
|
-
|
|
42
|
-
// Marker symbols React stamps onto exotic component types. Mirrors the
|
|
43
|
-
// internal `isValidElementType` check in `react.development.js` — React
|
|
44
|
-
// doesn't export it, and we don't want to add `react-is` just for this one
|
|
45
|
-
// validation. Inlined the same way `isClientReference` in
|
|
46
|
-
// `route-element-builder.ts` inlines the client-reference marker.
|
|
47
|
-
const REACT_FORWARD_REF_TYPE = Symbol.for('react.forward_ref');
|
|
48
|
-
const REACT_MEMO_TYPE = Symbol.for('react.memo');
|
|
49
|
-
const REACT_LAZY_TYPE = Symbol.for('react.lazy');
|
|
50
|
-
const REACT_PROVIDER_TYPE = Symbol.for('react.provider');
|
|
51
|
-
const REACT_CONTEXT_TYPE = Symbol.for('react.context');
|
|
52
|
-
const REACT_SUSPENSE_TYPE = Symbol.for('react.suspense');
|
|
53
|
-
const REACT_SUSPENSE_LIST_TYPE = Symbol.for('react.suspense_list');
|
|
54
|
-
const REACT_CLIENT_REFERENCE_TYPE = Symbol.for('react.client.reference');
|
|
55
|
-
|
|
56
|
-
const REACT_COMPONENT_TYPE_MARKERS: ReadonlySet<symbol> = new Set([
|
|
57
|
-
REACT_FORWARD_REF_TYPE,
|
|
58
|
-
REACT_MEMO_TYPE,
|
|
59
|
-
REACT_LAZY_TYPE,
|
|
60
|
-
REACT_PROVIDER_TYPE,
|
|
61
|
-
REACT_CONTEXT_TYPE,
|
|
62
|
-
REACT_SUSPENSE_TYPE,
|
|
63
|
-
REACT_SUSPENSE_LIST_TYPE,
|
|
64
|
-
REACT_CLIENT_REFERENCE_TYPE,
|
|
65
|
-
]);
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Validate that a loaded module's `default` export is something React
|
|
69
|
-
* accepts as the first argument to `createElement` — i.e. a valid component
|
|
70
|
-
* type. React doesn't export `isValidElementType` (only `isValidElement`,
|
|
71
|
-
* which checks for *elements*, not *component types*), so this mirrors
|
|
72
|
-
* React's internal check:
|
|
73
|
-
*
|
|
74
|
-
* - functions → function or class components
|
|
75
|
-
* - objects with a `$$typeof` matching one of React's known component
|
|
76
|
-
* markers → exotic components (`memo`, `forwardRef`, `lazy`, context,
|
|
77
|
-
* suspense, client references via `@vitejs/plugin-rsc`)
|
|
78
|
-
*
|
|
79
|
-
* Strings (HTML tag names) are valid for `createElement` but never appear
|
|
80
|
-
* as a route module's default export, so they're not recognized here.
|
|
81
|
-
*
|
|
82
|
-
* Anything else (numbers, plain config objects, JSON, etc.) is rejected so
|
|
83
|
-
* the boundary wrapper is skipped rather than crashing inside React.
|
|
84
|
-
*/
|
|
85
|
-
function isValidElementType(value: unknown): value is LoadedComponent {
|
|
86
|
-
if (typeof value === 'function') return true;
|
|
87
|
-
if (typeof value !== 'object' || value === null) return false;
|
|
88
|
-
const marker = (value as { $$typeof?: unknown }).$$typeof;
|
|
89
|
-
return typeof marker === 'symbol' && REACT_COMPONENT_TYPE_MARKERS.has(marker);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
31
|
/**
|
|
93
32
|
* Function that creates a React element. Matches React.createElement signature.
|
|
94
33
|
*
|
|
@@ -143,22 +82,41 @@ export interface AccessGateProps {
|
|
|
143
82
|
/** Segment name for dev logging (e.g. "authenticated", "dashboard"). */
|
|
144
83
|
segmentName?: string;
|
|
145
84
|
/**
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
85
|
+
* Segment key of the gated segment (`computeSegmentKeys`). Decides whether
|
|
86
|
+
* a matched deny page renders here or is hoisted to the segment that owns
|
|
87
|
+
* it. Omitted by construction sites that build no deny chains — with no
|
|
88
|
+
* chain there is nothing to place. See TIM-1356.
|
|
150
89
|
*/
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
90
|
+
segmentKey?: string;
|
|
91
|
+
/**
|
|
92
|
+
* Index of this segment in the matched segment chain. Recorded in ALS
|
|
93
|
+
* when the gate catches a DenySignal so post-render consumers
|
|
94
|
+
* (buildSegmentInfo, X-Timber-Segments) can bound the segment list
|
|
95
|
+
* without a pre-render access pass. See TIM-1363.
|
|
96
|
+
*/
|
|
97
|
+
segmentIndex?: number;
|
|
155
98
|
/**
|
|
156
99
|
* Deny page fallback chain. When provided and a DenySignal is caught,
|
|
157
100
|
* AccessGate renders the matching deny page in-tree instead of throwing.
|
|
158
101
|
* This prevents the error from reaching React Flight, eliminating the
|
|
159
102
|
* second render pass. See TIM-666.
|
|
103
|
+
*
|
|
104
|
+
* Omitted for skipped segments — a deny there must hard-navigate to
|
|
105
|
+
* avoid rendering the deny page inside cached layout chrome (TIM-1074).
|
|
160
106
|
*/
|
|
161
107
|
denyPages?: import('./deny-boundary.js').DenyPageEntry[];
|
|
108
|
+
/**
|
|
109
|
+
* When true, this gate wraps a skipped segment. On deny, the gate
|
|
110
|
+
* records the deny in ALS and rethrows so the response path can
|
|
111
|
+
* return rscErrorEnvelope for a client hard-navigate.
|
|
112
|
+
*/
|
|
113
|
+
skippedSegment?: boolean;
|
|
114
|
+
/**
|
|
115
|
+
* Shell settlement callback. Called when the gate finishes (pass or
|
|
116
|
+
* deny). Tracked by shellSettled so the HTTP status is not committed
|
|
117
|
+
* before async access checks complete. See TIM-1045, TIM-1363.
|
|
118
|
+
*/
|
|
119
|
+
onSettled?: () => void;
|
|
162
120
|
children: ReactNode;
|
|
163
121
|
}
|
|
164
122
|
|
|
@@ -192,26 +150,6 @@ export interface SlotAccessGateProps {
|
|
|
192
150
|
| import('./primitives.js').RedirectSignal;
|
|
193
151
|
}
|
|
194
152
|
|
|
195
|
-
/**
|
|
196
|
-
* Framework-injected error boundary wrapper.
|
|
197
|
-
* Wraps content with status-code error boundary handling.
|
|
198
|
-
*
|
|
199
|
-
* Field types must agree with `TimberErrorBoundaryProps` in
|
|
200
|
-
* `client/error-boundary.tsx`. The two are kept structurally compatible by
|
|
201
|
-
* convention rather than by direct type import — tree-builder.ts is the
|
|
202
|
-
* server-side construction site and may not import types from a 'use client'
|
|
203
|
-
* module to keep the server barrel free of client coupling.
|
|
204
|
-
*/
|
|
205
|
-
export interface ErrorBoundaryProps {
|
|
206
|
-
/** The component to render when an error is caught (TSX status files). */
|
|
207
|
-
fallbackComponent?: LoadedComponent;
|
|
208
|
-
/** Pre-rendered fallback element (MDX status files — see TIM-503). */
|
|
209
|
-
fallbackElement?: ReactNode;
|
|
210
|
-
/** Status code filter: 400 = any 4xx, 500 = any 5xx, specific number = exact match. */
|
|
211
|
-
status?: number;
|
|
212
|
-
children: ReactNode;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
153
|
// ─── Tree Builder ────────────────────────────────────────────────────────────
|
|
216
154
|
|
|
217
155
|
/**
|
|
@@ -272,13 +210,11 @@ export async function buildElementTree(config: TreeBuilderConfig): Promise<TreeB
|
|
|
272
210
|
const segment = segments[i];
|
|
273
211
|
|
|
274
212
|
// Wrap in error boundaries (status-code files + error.tsx)
|
|
275
|
-
element = await
|
|
276
|
-
segment,
|
|
277
|
-
element,
|
|
213
|
+
element = await wrapSegmentWithErrorBoundaries(segment, element, {
|
|
278
214
|
loadModule,
|
|
279
215
|
createElement,
|
|
280
|
-
errorBoundaryComponent
|
|
281
|
-
);
|
|
216
|
+
errorBoundaryComponent,
|
|
217
|
+
});
|
|
282
218
|
|
|
283
219
|
// Wrap in AccessGate if segment has access.ts
|
|
284
220
|
if (segment.access) {
|
|
@@ -355,13 +291,11 @@ async function buildSlotElement(
|
|
|
355
291
|
let element: ReactNode = createElement(PageComponent, {});
|
|
356
292
|
|
|
357
293
|
// Wrap in error boundaries
|
|
358
|
-
element = await
|
|
359
|
-
slotNode,
|
|
360
|
-
element,
|
|
294
|
+
element = await wrapSegmentWithErrorBoundaries(slotNode, element, {
|
|
361
295
|
loadModule,
|
|
362
296
|
createElement,
|
|
363
|
-
errorBoundaryComponent
|
|
364
|
-
);
|
|
297
|
+
errorBoundaryComponent,
|
|
298
|
+
});
|
|
365
299
|
|
|
366
300
|
// Wrap in SlotAccessGate if slot has access.ts
|
|
367
301
|
if (slotNode.access) {
|
|
@@ -387,120 +321,3 @@ async function buildSlotElement(
|
|
|
387
321
|
|
|
388
322
|
return element;
|
|
389
323
|
}
|
|
390
|
-
|
|
391
|
-
// ─── Error Boundary Wrapping ─────────────────────────────────────────────────
|
|
392
|
-
|
|
393
|
-
/** MDX/markdown extensions — these are server components that cannot be passed as function props. */
|
|
394
|
-
const MDX_EXTENSIONS = new Set(['mdx', 'md']);
|
|
395
|
-
|
|
396
|
-
/**
|
|
397
|
-
* Check if a route file is an MDX/markdown file based on its extension.
|
|
398
|
-
* MDX components are server components by default and cannot cross the
|
|
399
|
-
* RSC→client boundary as function props. They must be pre-rendered as
|
|
400
|
-
* elements and passed as fallbackElement instead of fallbackComponent.
|
|
401
|
-
*/
|
|
402
|
-
function isMdxFile(file: RouteFile): boolean {
|
|
403
|
-
return MDX_EXTENSIONS.has(file.extension);
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
/**
|
|
407
|
-
* Wrap an element with error boundaries from a segment's status-code files.
|
|
408
|
-
*
|
|
409
|
-
* Wrapping order (innermost to outermost):
|
|
410
|
-
* 1. Specific status files (503.tsx, 429.tsx, etc.)
|
|
411
|
-
* 2. Category catch-alls (4xx.tsx, 5xx.tsx)
|
|
412
|
-
* 3. error.tsx (general error boundary)
|
|
413
|
-
*
|
|
414
|
-
* This creates the fallback chain described in design/10-error-handling.md.
|
|
415
|
-
*
|
|
416
|
-
* MDX status files are server components and cannot be passed as function
|
|
417
|
-
* props to TimberErrorBoundary (a 'use client' component). Instead, they
|
|
418
|
-
* are pre-rendered as elements and passed as fallbackElement. The error
|
|
419
|
-
* boundary renders the element directly when an error is caught.
|
|
420
|
-
* See TIM-503.
|
|
421
|
-
*/
|
|
422
|
-
async function wrapWithErrorBoundaries(
|
|
423
|
-
segment: SegmentNode,
|
|
424
|
-
element: ReactNode,
|
|
425
|
-
loadModule: ModuleLoader,
|
|
426
|
-
createElement: CreateElement,
|
|
427
|
-
errorBoundaryComponent: unknown
|
|
428
|
-
): Promise<ReactNode> {
|
|
429
|
-
// Wrapping is applied inside-out. The last wrap call produces the outermost boundary.
|
|
430
|
-
// Order: specific status → category → error.tsx (outermost)
|
|
431
|
-
|
|
432
|
-
if (segment.statusFiles) {
|
|
433
|
-
// Wrap with specific status files (innermost — highest priority at runtime)
|
|
434
|
-
for (const [key, file] of Object.entries(segment.statusFiles)) {
|
|
435
|
-
if (key !== '4xx' && key !== '5xx') {
|
|
436
|
-
const status = parseInt(key, 10);
|
|
437
|
-
if (!isNaN(status)) {
|
|
438
|
-
const mod = await loadModule(file);
|
|
439
|
-
// mod.default is `unknown` — narrow to a component reference.
|
|
440
|
-
// `isValidElementType` accepts memo/forwardRef objects in addition to
|
|
441
|
-
// bare functions; non-component values fall through.
|
|
442
|
-
const Component = isValidElementType(mod.default) ? mod.default : null;
|
|
443
|
-
if (Component) {
|
|
444
|
-
const boundaryProps: ErrorBoundaryProps = isMdxFile(file)
|
|
445
|
-
? {
|
|
446
|
-
fallbackElement: createElement(Component, { status }),
|
|
447
|
-
status,
|
|
448
|
-
children: element,
|
|
449
|
-
}
|
|
450
|
-
: {
|
|
451
|
-
fallbackComponent: Component,
|
|
452
|
-
status,
|
|
453
|
-
children: element,
|
|
454
|
-
};
|
|
455
|
-
element = createElement(errorBoundaryComponent, boundaryProps);
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
// Wrap with category catch-alls (4xx.tsx, 5xx.tsx)
|
|
462
|
-
for (const [key, file] of Object.entries(segment.statusFiles)) {
|
|
463
|
-
if (key === '4xx' || key === '5xx') {
|
|
464
|
-
const mod = await loadModule(file);
|
|
465
|
-
const Component = isValidElementType(mod.default) ? mod.default : null;
|
|
466
|
-
if (Component) {
|
|
467
|
-
const categoryStatus = key === '4xx' ? 400 : 500;
|
|
468
|
-
const boundaryProps: ErrorBoundaryProps = isMdxFile(file)
|
|
469
|
-
? {
|
|
470
|
-
fallbackElement: createElement(Component, {}),
|
|
471
|
-
status: categoryStatus,
|
|
472
|
-
children: element,
|
|
473
|
-
}
|
|
474
|
-
: {
|
|
475
|
-
fallbackComponent: Component,
|
|
476
|
-
status: categoryStatus,
|
|
477
|
-
children: element,
|
|
478
|
-
};
|
|
479
|
-
element = createElement(errorBoundaryComponent, boundaryProps);
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
// Wrap with error.tsx (outermost — catches anything not matched by status files)
|
|
486
|
-
// Note: error.tsx/error.mdx receives { error, digest, reset } props.
|
|
487
|
-
// MDX error files are pre-rendered without those props (they're static content).
|
|
488
|
-
if (segment.error) {
|
|
489
|
-
const errorModule = await loadModule(segment.error);
|
|
490
|
-
const ErrorComponent = isValidElementType(errorModule.default) ? errorModule.default : null;
|
|
491
|
-
if (ErrorComponent) {
|
|
492
|
-
const boundaryProps: ErrorBoundaryProps = isMdxFile(segment.error)
|
|
493
|
-
? {
|
|
494
|
-
fallbackElement: createElement(ErrorComponent, {}),
|
|
495
|
-
children: element,
|
|
496
|
-
}
|
|
497
|
-
: {
|
|
498
|
-
fallbackComponent: ErrorComponent,
|
|
499
|
-
children: element,
|
|
500
|
-
};
|
|
501
|
-
element = createElement(errorBoundaryComponent, boundaryProps);
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
return element;
|
|
506
|
-
}
|
package/src/server/types.ts
CHANGED
|
@@ -33,21 +33,26 @@ export interface MiddlewareContext {
|
|
|
33
33
|
* `req` is the original incoming Request; `headers` is the response-headers
|
|
34
34
|
* container the framework will apply to the final Response.
|
|
35
35
|
*
|
|
36
|
-
* Segment params and query parameters are NOT on this context — they are
|
|
37
|
-
*
|
|
36
|
+
* Segment params and query parameters are NOT on this context — they are read
|
|
37
|
+
* the same way pages read them:
|
|
38
38
|
*
|
|
39
39
|
* ```ts
|
|
40
|
-
* // app/
|
|
41
|
-
* export
|
|
40
|
+
* // app/schema.ts — every dynamic segment's codec, keyed by bracket name
|
|
41
|
+
* export default defineSchema({ segmentParams: { '[id]': z.coerce.number() } });
|
|
42
|
+
*
|
|
42
43
|
* // app/api/users/[id]/route.ts
|
|
43
|
-
* import {
|
|
44
|
+
* import { getSegmentParams } from '@timber-js/app/server';
|
|
45
|
+
* import { SEGMENT_PATH } from './$segment';
|
|
44
46
|
* export async function GET() {
|
|
45
|
-
* const { id } =
|
|
47
|
+
* const { id } = getSegmentParams(SEGMENT_PATH); // typed number — 404 on bad input
|
|
46
48
|
* }
|
|
47
49
|
* ```
|
|
48
50
|
*
|
|
51
|
+
* For query parameters, import a `defineSearchParams` definition and call
|
|
52
|
+
* `.get()` on it.
|
|
53
|
+
*
|
|
49
54
|
* See design/07-routing.md §"RouteContext", design/23-search-params.md,
|
|
50
|
-
* design/
|
|
55
|
+
* design/41-global-params.md.
|
|
51
56
|
*/
|
|
52
57
|
export interface RouteContext {
|
|
53
58
|
req: Request;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Component-type validation for values loaded from route modules.
|
|
3
|
+
*
|
|
4
|
+
* Route modules are loaded dynamically, so their `default` export is
|
|
5
|
+
* `unknown`. Every construction site that wants to pass one to
|
|
6
|
+
* `createElement` narrows it through `isValidElementType` first.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { ReactNode } from 'react';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* A React component reference loaded from a route module's default export.
|
|
13
|
+
*
|
|
14
|
+
* Loaded modules' `default` is typed as `unknown` (modules are dynamic), so
|
|
15
|
+
* call sites narrow it through `isValidElementType` (below) before treating
|
|
16
|
+
* it as a component. The signature is a callable returning `ReactNode` —
|
|
17
|
+
* TypeScript's view of every valid React component shape, including exotic
|
|
18
|
+
* components (`memo`, `forwardRef`, `lazy`) which the type system treats as
|
|
19
|
+
* callable even though their runtime values are objects with `$$typeof`
|
|
20
|
+
* markers rather than functions.
|
|
21
|
+
*/
|
|
22
|
+
export type LoadedComponent = (...args: unknown[]) => ReactNode;
|
|
23
|
+
|
|
24
|
+
// Marker symbols React stamps onto exotic component types. Mirrors the
|
|
25
|
+
// internal `isValidElementType` check in `react.development.js` — React
|
|
26
|
+
// doesn't export it, and we don't want to add `react-is` just for this one
|
|
27
|
+
// validation. Inlined the same way `isClientReference` in
|
|
28
|
+
// `route-element-builder.ts` inlines the client-reference marker.
|
|
29
|
+
const REACT_FORWARD_REF_TYPE = Symbol.for('react.forward_ref');
|
|
30
|
+
const REACT_MEMO_TYPE = Symbol.for('react.memo');
|
|
31
|
+
const REACT_LAZY_TYPE = Symbol.for('react.lazy');
|
|
32
|
+
const REACT_PROVIDER_TYPE = Symbol.for('react.provider');
|
|
33
|
+
const REACT_CONTEXT_TYPE = Symbol.for('react.context');
|
|
34
|
+
const REACT_SUSPENSE_TYPE = Symbol.for('react.suspense');
|
|
35
|
+
const REACT_SUSPENSE_LIST_TYPE = Symbol.for('react.suspense_list');
|
|
36
|
+
const REACT_CLIENT_REFERENCE_TYPE = Symbol.for('react.client.reference');
|
|
37
|
+
|
|
38
|
+
const REACT_COMPONENT_TYPE_MARKERS: ReadonlySet<symbol> = new Set([
|
|
39
|
+
REACT_FORWARD_REF_TYPE,
|
|
40
|
+
REACT_MEMO_TYPE,
|
|
41
|
+
REACT_LAZY_TYPE,
|
|
42
|
+
REACT_PROVIDER_TYPE,
|
|
43
|
+
REACT_CONTEXT_TYPE,
|
|
44
|
+
REACT_SUSPENSE_TYPE,
|
|
45
|
+
REACT_SUSPENSE_LIST_TYPE,
|
|
46
|
+
REACT_CLIENT_REFERENCE_TYPE,
|
|
47
|
+
]);
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Validate that a loaded module's `default` export is something React
|
|
51
|
+
* accepts as the first argument to `createElement` — i.e. a valid component
|
|
52
|
+
* type. React doesn't export `isValidElementType` (only `isValidElement`,
|
|
53
|
+
* which checks for *elements*, not *component types*), so this mirrors
|
|
54
|
+
* React's internal check:
|
|
55
|
+
*
|
|
56
|
+
* - functions → function or class components
|
|
57
|
+
* - objects with a `$$typeof` matching one of React's known component
|
|
58
|
+
* markers → exotic components (`memo`, `forwardRef`, `lazy`, context,
|
|
59
|
+
* suspense, client references via `@vitejs/plugin-rsc`)
|
|
60
|
+
*
|
|
61
|
+
* Strings (HTML tag names) are valid for `createElement` but never appear
|
|
62
|
+
* as a route module's default export, so they're not recognized here.
|
|
63
|
+
*
|
|
64
|
+
* Anything else (numbers, plain config objects, JSON, etc.) is rejected so
|
|
65
|
+
* the boundary wrapper is skipped rather than crashing inside React.
|
|
66
|
+
*/
|
|
67
|
+
export function isValidElementType(value: unknown): value is LoadedComponent {
|
|
68
|
+
if (typeof value === 'function') return true;
|
|
69
|
+
if (typeof value !== 'object' || value === null) return false;
|
|
70
|
+
const marker = (value as { $$typeof?: unknown }).$$typeof;
|
|
71
|
+
return typeof marker === 'symbol' && REACT_COMPONENT_TYPE_MARKERS.has(marker);
|
|
72
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ALS getter slots for the isomorphic `define*` modules.
|
|
3
|
+
*
|
|
4
|
+
* `searchParams.get()` and `segmentParams.get()` read per-request state out of
|
|
5
|
+
* `server/als-registry.ts`, but the modules that expose them are *isomorphic*:
|
|
6
|
+
* `search-params/define.ts` and `segment-params/define.ts` are imported by
|
|
7
|
+
* `'use client'` components for their hooks, so neither may import
|
|
8
|
+
* `node:async_hooks` — not even transitively, because the dep optimizer
|
|
9
|
+
* pre-bundles them before per-environment resolution runs. So the server
|
|
10
|
+
* registers its getter into a slot at module-init time and the define modules
|
|
11
|
+
* read the slot.
|
|
12
|
+
*
|
|
13
|
+
* The slots live here, in a module with **no imports at all**, rather than in
|
|
14
|
+
* the define modules themselves. That is the whole point: `request-context.ts`
|
|
15
|
+
* has to reach the setter, and when the setter lived in
|
|
16
|
+
* `search-params/define.ts` every server entry that touched
|
|
17
|
+
* `@timber-js/app/server` pulled that module — and therefore its `'use client'`
|
|
18
|
+
* import of `client/use-query-states.ts`, and therefore `nuqs` — into the
|
|
19
|
+
* server graph. `nuqs` named-imports `createContext`/`useContext` from React,
|
|
20
|
+
* which React's `react-server` export withholds, so `@timber-js/app`,
|
|
21
|
+
* `@timber-js/app/server`, `@timber-js/app/cookies` and `@timber-js/app/cache`
|
|
22
|
+
* all failed to instantiate under the `react-server` condition (TIM-1298).
|
|
23
|
+
* A leaf module breaks the edge without a registration ceremony on either side.
|
|
24
|
+
*
|
|
25
|
+
* Registration must be eager, not a call-time `await import()`: the async
|
|
26
|
+
* microtask a dynamic import introduces loses AsyncLocalStorage context inside
|
|
27
|
+
* React's RSC Flight renderer, which broke `getSearchParams()` in parallel slot
|
|
28
|
+
* pages (TIM-523).
|
|
29
|
+
*
|
|
30
|
+
* See design/23-search-params.md §"defineSearchParams — The Factory" and
|
|
31
|
+
* design/41-global-params.md.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
interface AlsSlot<T> {
|
|
35
|
+
/** Register the server-side getter. Called once at module-init time. */
|
|
36
|
+
set(fn: () => T): void;
|
|
37
|
+
/** Read through to the registered getter, or throw the client-side message. */
|
|
38
|
+
get(): T;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function createAlsSlot<T>(message: string): AlsSlot<T> {
|
|
42
|
+
let fn: (() => T) | undefined;
|
|
43
|
+
return {
|
|
44
|
+
set(next) {
|
|
45
|
+
fn = next;
|
|
46
|
+
},
|
|
47
|
+
get() {
|
|
48
|
+
if (!fn) throw new Error(message);
|
|
49
|
+
return fn();
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const searchParamsSlot = createAlsSlot<URLSearchParams>(
|
|
55
|
+
'[timber] searchParams.get() is only available on the server. ' +
|
|
56
|
+
'Use searchParams.useQueryStates() on the client.'
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
const segmentParamsSlot = createAlsSlot<Record<string, string | string[]>>(
|
|
60
|
+
'[timber] segmentParams.get() is only available on the server. ' +
|
|
61
|
+
'Use segmentParams.useSegmentParams() on the client.'
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
/** @internal Called from `server/request-context.ts` at module init. */
|
|
65
|
+
export const _setGetSearchParamsFn = searchParamsSlot.set;
|
|
66
|
+
/** @internal Read by `search-params/define.ts` inside `.get()`. */
|
|
67
|
+
export const getSearchParamsFromAls = searchParamsSlot.get;
|
|
68
|
+
|
|
69
|
+
/** @internal Called from `server/request-context.ts` at module init. */
|
|
70
|
+
export const _setGetSegmentParamsFn = segmentParamsSlot.set;
|
|
71
|
+
/** @internal Read by `segment-params/define.ts` inside `.get()`. */
|
|
72
|
+
export const getSegmentParamsFromAls = segmentParamsSlot.get;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deployment base path — Vite's resolved `base`, as it applies to the URLs
|
|
3
|
+
* timber addresses at runtime.
|
|
4
|
+
*
|
|
5
|
+
* A static build deployed under a sub-path (`base: '/repo/'`, the GitHub
|
|
6
|
+
* Pages project-site layout) serves every generated file below that prefix:
|
|
7
|
+
* the document for `/about` lives at `/repo/about/index.html`, its flight
|
|
8
|
+
* payload at `/repo/_rsc/about/index.rsc`. The client works in *route space* — the
|
|
9
|
+
* paths the app declares — so both a strip (browser URL → route path) and a
|
|
10
|
+
* prefix (route-space path → URL) are needed, and this module owns both.
|
|
11
|
+
*
|
|
12
|
+
* Pure functions, no state: the caller supplies the base. `client/rsc-fetch.ts`
|
|
13
|
+
* holds the client's copy, set at bootstrap from `virtual:timber-config`.
|
|
14
|
+
*
|
|
15
|
+
* See design/11-platform.md §"Deploying under a non-root base" (TIM-1261).
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/** `https://cdn.example.com/`, `//cdn.example.com/` — a base pointing off-origin. */
|
|
19
|
+
function isAbsoluteUrlBase(base: string): boolean {
|
|
20
|
+
return base.startsWith('//') || /^[a-z][a-z0-9+.-]*:\/\//i.test(base);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* True when `base` is document-relative (`'./'`, `'foo/'`) — it makes asset
|
|
25
|
+
* URLs resolve against whatever document loaded them, which says nothing
|
|
26
|
+
* about where the deployment sits, so no prefix can be computed from it.
|
|
27
|
+
*/
|
|
28
|
+
export function isRelativeBase(base: string | undefined): boolean {
|
|
29
|
+
if (!base) return false;
|
|
30
|
+
return !base.startsWith('/') && !isAbsoluteUrlBase(base);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Normalize Vite's `base` into a path prefix. Always returns a value with a
|
|
35
|
+
* leading and trailing slash.
|
|
36
|
+
*
|
|
37
|
+
* Two forms carry no usable deployment prefix and normalize to `/`:
|
|
38
|
+
*
|
|
39
|
+
* - **An absolute-URL base** points *assets* at a CDN. The HTML documents and
|
|
40
|
+
* `.rsc` payloads are still served from the deployment origin, so their
|
|
41
|
+
* URLs stay root-relative. This is correct, not a degradation.
|
|
42
|
+
* - **A relative base** — see `isRelativeBase`. The static build warns,
|
|
43
|
+
* because SPA navigation then only works at the domain root.
|
|
44
|
+
*/
|
|
45
|
+
export function normalizeBasePath(base: string | undefined): string {
|
|
46
|
+
if (!base) return '/';
|
|
47
|
+
if (isAbsoluteUrlBase(base) || isRelativeBase(base)) return '/';
|
|
48
|
+
return base.endsWith('/') ? base : `${base}/`;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Strip the base prefix from a browser pathname, returning the route-space
|
|
53
|
+
* path. With base `/repo/`: `/repo/about` → `/about`, `/repo/` and `/repo`
|
|
54
|
+
* → `/`.
|
|
55
|
+
*
|
|
56
|
+
* A pathname outside the base is returned unchanged. It cannot be served by
|
|
57
|
+
* this deployment at all, so there is no better answer than letting the
|
|
58
|
+
* resulting fetch 404 and the router hard-navigate — visibly wrong beats
|
|
59
|
+
* silently rewritten.
|
|
60
|
+
*
|
|
61
|
+
* @param base A normalized base (see `normalizeBasePath`).
|
|
62
|
+
*/
|
|
63
|
+
export function stripBasePath(base: string, pathname: string): string {
|
|
64
|
+
if (base === '/') return pathname;
|
|
65
|
+
const withoutTrailingSlash = base.slice(0, -1);
|
|
66
|
+
if (pathname === withoutTrailingSlash) return '/';
|
|
67
|
+
if (!pathname.startsWith(base)) return pathname;
|
|
68
|
+
return pathname.slice(withoutTrailingSlash.length);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Prefix a route-space, root-relative path with the base.
|
|
73
|
+
* `/_rsc/about/index.rsc` → `/repo/_rsc/about/index.rsc`.
|
|
74
|
+
*
|
|
75
|
+
* @param base A normalized base (see `normalizeBasePath`).
|
|
76
|
+
*/
|
|
77
|
+
export function withBasePath(base: string, path: string): string {
|
|
78
|
+
if (base === '/') return path;
|
|
79
|
+
return path.startsWith('/') ? base.slice(0, -1) + path : `${base}${path}`;
|
|
80
|
+
}
|