@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
|
@@ -19,7 +19,10 @@ import { createElement, Fragment } from 'react';
|
|
|
19
19
|
import { renderToReadableStream } from '../rsc-runtime/rsc.js';
|
|
20
20
|
|
|
21
21
|
import { DenySignal } from './primitives.js';
|
|
22
|
-
import {
|
|
22
|
+
import { appVisibleSearch } from '../shared/rsc-cache-key.js';
|
|
23
|
+
import { getSlotParamsForClient } from './request-context.js';
|
|
24
|
+
import { withPublishedParams } from './publish-params.js';
|
|
25
|
+
import { renderDenyEntry, type DenyEntryShape } from './deny-boundary.js';
|
|
23
26
|
import { getCookiesForSsr } from './cookie-context.js';
|
|
24
27
|
import { logRenderError } from './logger.js';
|
|
25
28
|
import { loadModule } from './safe-load.js';
|
|
@@ -28,6 +31,8 @@ import { isDebug } from './debug.js';
|
|
|
28
31
|
import { resolveMetadata, renderMetadataToElements } from './metadata.js';
|
|
29
32
|
import { headElementsToReact } from './metadata.js';
|
|
30
33
|
import { resolveStatusFile } from './status-code-resolver.js';
|
|
34
|
+
import { defaultStatusPageResponse } from './default-status-page.js';
|
|
35
|
+
import { rscErrorEnvelope } from '../shared/rsc-error-envelope.js';
|
|
31
36
|
import type { ManifestSegmentNode } from './route-matcher.js';
|
|
32
37
|
import type { RouteMatch } from './pipeline.js';
|
|
33
38
|
import type { NavContext } from './ssr-bridge-types.js';
|
|
@@ -35,9 +40,7 @@ import { flightInitScript } from './flight-scripts.js';
|
|
|
35
40
|
import type { ClientBootstrapConfig } from './html-injectors.js';
|
|
36
41
|
import type { Metadata } from './types.js';
|
|
37
42
|
import { teeWithErrorPropagation } from './stream-utils.js';
|
|
38
|
-
|
|
39
|
-
/** RSC content type for client navigation payload requests. */
|
|
40
|
-
const RSC_CONTENT_TYPE = 'text/x-component';
|
|
43
|
+
import { RSC_CONTENT_TYPE } from '../shared/rsc-media-type.js';
|
|
41
44
|
|
|
42
45
|
/** Layout component entry for deny page wrapping. */
|
|
43
46
|
export interface LayoutEntry {
|
|
@@ -79,8 +82,7 @@ function buildDenyElement(
|
|
|
79
82
|
resolutionKind: 'exact' | 'category' | 'error',
|
|
80
83
|
filePath: string
|
|
81
84
|
): React.ReactElement {
|
|
82
|
-
const entry:
|
|
83
|
-
status: deny.status,
|
|
85
|
+
const entry: DenyEntryShape = {
|
|
84
86
|
component,
|
|
85
87
|
kind: resolutionKind === 'error' ? 'error' : 'status',
|
|
86
88
|
isMdx: isMdxFilePath(filePath),
|
|
@@ -88,12 +90,24 @@ function buildDenyElement(
|
|
|
88
90
|
return renderDenyEntry(entry, deny.status, deny.data);
|
|
89
91
|
}
|
|
90
92
|
|
|
93
|
+
/**
|
|
94
|
+
* Supplies a replacement for the framework default page at the end of the
|
|
95
|
+
* chain. Returning `null` keeps the framework default.
|
|
96
|
+
*
|
|
97
|
+
* The dev server uses this to substitute its route-listing 404 page. It is a
|
|
98
|
+
* parameter rather than a check on the produced Response because "the app
|
|
99
|
+
* authored no status page" is a fact about the *chain*, and inspecting the
|
|
100
|
+
* result for it (e.g. an empty body) stops being true the moment the chain
|
|
101
|
+
* grows a real terminal — which is exactly what TIM-1258 did.
|
|
102
|
+
*/
|
|
103
|
+
export type DefaultPageRenderer = (status: number, responseHeaders: Headers) => Response | null;
|
|
104
|
+
|
|
91
105
|
/**
|
|
92
106
|
* Render a status-code error page for a DenySignal.
|
|
93
107
|
*
|
|
94
108
|
* Resolves the appropriate status-code file from the segment chain based
|
|
95
|
-
* on format preference. Returns an HTML Response (component), JSON Response,
|
|
96
|
-
* or
|
|
109
|
+
* on format preference. Returns an HTML Response (component), a JSON Response,
|
|
110
|
+
* or the framework default status page.
|
|
97
111
|
*/
|
|
98
112
|
export async function renderDenyPage(
|
|
99
113
|
deny: DenySignal,
|
|
@@ -104,23 +118,35 @@ export async function renderDenyPage(
|
|
|
104
118
|
responseHeaders: Headers,
|
|
105
119
|
clientBootstrap: ClientBootstrapConfig,
|
|
106
120
|
createDebugChannelSink: DebugChannelFactory,
|
|
107
|
-
callSsr: CallSsrFn
|
|
121
|
+
callSsr: CallSsrFn,
|
|
122
|
+
defaultPage?: DefaultPageRenderer,
|
|
123
|
+
firstDeniedIndex = Infinity
|
|
108
124
|
): Promise<Response> {
|
|
125
|
+
// Clamp the resolution walk to the denied segment — a status file below
|
|
126
|
+
// the denial is invisible to the in-tree chain and must not be selected
|
|
127
|
+
// by the fallback. The denying segment itself IS included (matching
|
|
128
|
+
// buildDenyPageChain's start-at-i semantics), but its layout is not
|
|
129
|
+
// (the gate-outside-layout rule from TIM-1074). See TIM-1358.
|
|
130
|
+
const maxIndex = firstDeniedIndex < Infinity ? firstDeniedIndex : undefined;
|
|
131
|
+
|
|
109
132
|
// API routes (route.ts) → JSON only, never render components
|
|
110
133
|
if (isApiRoute(segments)) {
|
|
111
|
-
const jsonResponse = await renderDenyPageJson(deny, segments, responseHeaders);
|
|
134
|
+
const jsonResponse = await renderDenyPageJson(deny, segments, responseHeaders, maxIndex);
|
|
112
135
|
if (jsonResponse) return jsonResponse;
|
|
113
136
|
return bareJsonResponse(deny.status, responseHeaders);
|
|
114
137
|
}
|
|
115
138
|
|
|
116
139
|
// Page routes → component chain first, JSON fallback only if no component found.
|
|
117
|
-
const resolution = resolveStatusFile(deny.status, segments, 'component');
|
|
140
|
+
const resolution = resolveStatusFile(deny.status, segments, 'component', maxIndex);
|
|
118
141
|
|
|
119
|
-
// No component status file — try JSON chain
|
|
142
|
+
// No component status file — try JSON chain, then the framework default page.
|
|
120
143
|
if (!resolution) {
|
|
121
|
-
const jsonResponse = await renderDenyPageJson(deny, segments, responseHeaders);
|
|
144
|
+
const jsonResponse = await renderDenyPageJson(deny, segments, responseHeaders, maxIndex);
|
|
122
145
|
if (jsonResponse) return jsonResponse;
|
|
123
|
-
return
|
|
146
|
+
return (
|
|
147
|
+
defaultPage?.(deny.status, responseHeaders) ??
|
|
148
|
+
defaultStatusPageResponse(deny.status, responseHeaders)
|
|
149
|
+
);
|
|
124
150
|
}
|
|
125
151
|
|
|
126
152
|
// Dev warning: JSON status file exists but is shadowed by the component chain.
|
|
@@ -137,10 +163,20 @@ export async function renderDenyPage(
|
|
|
137
163
|
}
|
|
138
164
|
}
|
|
139
165
|
|
|
140
|
-
// Load the status-code page component
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
166
|
+
// Load the status-code page component. A file that resolved but exports no
|
|
167
|
+
// default — or whose module fails to import or evaluate — is not a usable
|
|
168
|
+
// component match: continue down the documented chain (JSON, then framework
|
|
169
|
+
// default) rather than returning an empty body or letting the loader's
|
|
170
|
+
// rejection escape request handling. Mirrors buildDenyPageChain and the
|
|
171
|
+
// error-file resolver, which both swallow the load failure.
|
|
172
|
+
const mod = await loadModule(resolution.file).catch(() => null);
|
|
173
|
+
if (!mod?.default) {
|
|
174
|
+
const jsonResponse = await renderDenyPageJson(deny, segments, responseHeaders, maxIndex);
|
|
175
|
+
if (jsonResponse) return jsonResponse;
|
|
176
|
+
return (
|
|
177
|
+
defaultPage?.(deny.status, responseHeaders) ??
|
|
178
|
+
defaultStatusPageResponse(deny.status, responseHeaders)
|
|
179
|
+
);
|
|
144
180
|
}
|
|
145
181
|
|
|
146
182
|
const ErrorPageComponent = mod.default as (...args: unknown[]) => unknown;
|
|
@@ -156,10 +192,12 @@ export async function renderDenyPage(
|
|
|
156
192
|
resolution.file.filePath
|
|
157
193
|
);
|
|
158
194
|
|
|
159
|
-
//
|
|
160
|
-
//
|
|
161
|
-
//
|
|
162
|
-
|
|
195
|
+
// Wrap in layout shell, clamped so a denied segment's layout never
|
|
196
|
+
// executes — the gate-outside-layout rule from TIM-1074. The denied
|
|
197
|
+
// segment's layout was loaded into `layoutComponents` but must not
|
|
198
|
+
// appear in the fallback response. See TIM-1358.
|
|
199
|
+
const layoutCeiling = Math.min(resolution.segmentIndex, firstDeniedIndex - 1);
|
|
200
|
+
const resolvedSegments = new Set(segments.slice(0, layoutCeiling + 1));
|
|
163
201
|
const layoutsToWrap = layoutComponents.filter((lc) => resolvedSegments.has(lc.segment));
|
|
164
202
|
for (let i = layoutsToWrap.length - 1; i >= 0; i--) {
|
|
165
203
|
const { component } = layoutsToWrap[i];
|
|
@@ -176,7 +214,7 @@ export async function renderDenyPage(
|
|
|
176
214
|
}
|
|
177
215
|
|
|
178
216
|
// Render the error page to a fresh RSC Flight stream.
|
|
179
|
-
const rscStream = renderToReadableStream(element, {
|
|
217
|
+
const rscStream = renderToReadableStream(withPublishedParams(element), {
|
|
180
218
|
signal: req.signal,
|
|
181
219
|
onError(error: unknown) {
|
|
182
220
|
logRenderError({ method: req.method, path: new URL(req.url).pathname, error });
|
|
@@ -186,10 +224,13 @@ export async function renderDenyPage(
|
|
|
186
224
|
|
|
187
225
|
const [ssrStream, inlineStream] = teeWithErrorPropagation(rscStream);
|
|
188
226
|
|
|
227
|
+
const slotParams = getSlotParamsForClient();
|
|
228
|
+
|
|
189
229
|
const navContext: NavContext = {
|
|
190
230
|
pathname: new URL(req.url).pathname,
|
|
191
231
|
segmentParams: match.segmentParams,
|
|
192
|
-
searchParams: Object.fromEntries(new URL(req.url).
|
|
232
|
+
searchParams: Object.fromEntries(appVisibleSearch(new URL(req.url)).params),
|
|
233
|
+
slotParams,
|
|
193
234
|
statusCode: deny.status,
|
|
194
235
|
responseHeaders,
|
|
195
236
|
headHtml: flightInitScript(),
|
|
@@ -199,7 +240,32 @@ export async function renderDenyPage(
|
|
|
199
240
|
cookies: getCookiesForSsr(),
|
|
200
241
|
};
|
|
201
242
|
|
|
202
|
-
|
|
243
|
+
try {
|
|
244
|
+
// `await` inside the try on purpose — see the same note in
|
|
245
|
+
// rsc-entry/error-renderer.ts. A status page that crashes during SSR
|
|
246
|
+
// ends in the framework default page, not a blank body: the pipeline's
|
|
247
|
+
// own deny fallback catches this and can only produce an empty response,
|
|
248
|
+
// and a crashing 404.tsx is exactly when the reader has nothing else to
|
|
249
|
+
// go on (TIM-1258).
|
|
250
|
+
return await callSsr(ssrStream, navContext);
|
|
251
|
+
} catch (renderError) {
|
|
252
|
+
logRenderError({ method: req.method, path: new URL(req.url).pathname, error: renderError });
|
|
253
|
+
return defaultStatusPageResponse(deny.status, responseHeaders);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Terminal fallback for a client-navigation deny with no status-code file.
|
|
259
|
+
*
|
|
260
|
+
* The HTML path answers this case with the framework default page, but a
|
|
261
|
+
* client-navigation response cannot carry HTML — the Flight decoder would
|
|
262
|
+
* choke on it. Emit the hard-navigate envelope instead: the client abandons
|
|
263
|
+
* SPA navigation and the resulting document request renders that same default
|
|
264
|
+
* page. Before TIM-1258 this returned an empty Flight body, which the decoder
|
|
265
|
+
* hit as a malformed stream.
|
|
266
|
+
*/
|
|
267
|
+
function denyHardNavigateResponse(status: number, responseHeaders: Headers): Response {
|
|
268
|
+
return rscErrorEnvelope(status, responseHeaders);
|
|
203
269
|
}
|
|
204
270
|
|
|
205
271
|
/**
|
|
@@ -214,19 +280,19 @@ export async function renderDenyPageAsRsc(
|
|
|
214
280
|
layoutComponents: LayoutEntry[],
|
|
215
281
|
req: Request,
|
|
216
282
|
responseHeaders: Headers,
|
|
217
|
-
createDebugChannelSink: DebugChannelFactory
|
|
283
|
+
createDebugChannelSink: DebugChannelFactory,
|
|
284
|
+
firstDeniedIndex = Infinity
|
|
218
285
|
): Promise<Response> {
|
|
219
|
-
const
|
|
286
|
+
const maxIndex = firstDeniedIndex < Infinity ? firstDeniedIndex : undefined;
|
|
287
|
+
const resolution = resolveStatusFile(deny.status, segments, 'component', maxIndex);
|
|
220
288
|
|
|
221
289
|
if (!resolution) {
|
|
222
|
-
|
|
223
|
-
return new Response(null, { status: deny.status, headers: responseHeaders });
|
|
290
|
+
return denyHardNavigateResponse(deny.status, responseHeaders);
|
|
224
291
|
}
|
|
225
292
|
|
|
226
|
-
const mod = await loadModule(resolution.file);
|
|
227
|
-
if (!mod
|
|
228
|
-
|
|
229
|
-
return new Response(null, { status: deny.status, headers: responseHeaders });
|
|
293
|
+
const mod = await loadModule(resolution.file).catch(() => null);
|
|
294
|
+
if (!mod?.default) {
|
|
295
|
+
return denyHardNavigateResponse(deny.status, responseHeaders);
|
|
230
296
|
}
|
|
231
297
|
|
|
232
298
|
const ErrorPageComponent = mod.default as (...args: unknown[]) => unknown;
|
|
@@ -239,15 +305,16 @@ export async function renderDenyPageAsRsc(
|
|
|
239
305
|
resolution.file.filePath
|
|
240
306
|
);
|
|
241
307
|
|
|
242
|
-
//
|
|
243
|
-
const
|
|
308
|
+
// Wrap in layout shell, clamped to exclude denied segment layouts. TIM-1358.
|
|
309
|
+
const layoutCeiling = Math.min(resolution.segmentIndex, firstDeniedIndex - 1);
|
|
310
|
+
const resolvedSegments = new Set(segments.slice(0, layoutCeiling + 1));
|
|
244
311
|
const layoutsToWrap = layoutComponents.filter((lc) => resolvedSegments.has(lc.segment));
|
|
245
312
|
for (let i = layoutsToWrap.length - 1; i >= 0; i--) {
|
|
246
313
|
const { component } = layoutsToWrap[i];
|
|
247
314
|
element = h(component, null, element);
|
|
248
315
|
}
|
|
249
316
|
|
|
250
|
-
const rscStream = renderToReadableStream(element, {
|
|
317
|
+
const rscStream = renderToReadableStream(withPublishedParams(element), {
|
|
251
318
|
signal: req.signal,
|
|
252
319
|
onError(error: unknown) {
|
|
253
320
|
console.error('[timber] Error page RSC render error:', error);
|
|
@@ -275,9 +342,10 @@ export async function renderDenyPageAsRsc(
|
|
|
275
342
|
async function renderDenyPageJson(
|
|
276
343
|
deny: DenySignal,
|
|
277
344
|
segments: ManifestSegmentNode[],
|
|
278
|
-
responseHeaders: Headers
|
|
345
|
+
responseHeaders: Headers,
|
|
346
|
+
maxIndex?: number
|
|
279
347
|
): Promise<Response | null> {
|
|
280
|
-
const resolution = resolveStatusFile(deny.status, segments, 'json');
|
|
348
|
+
const resolution = resolveStatusFile(deny.status, segments, 'json', maxIndex);
|
|
281
349
|
|
|
282
350
|
if (!resolution) {
|
|
283
351
|
return null;
|
|
@@ -286,7 +354,11 @@ async function renderDenyPageJson(
|
|
|
286
354
|
// JSON status files are loaded as modules that export the JSON content.
|
|
287
355
|
// The manifest's load() imports the .json file, which Vite handles as a
|
|
288
356
|
// default export of the parsed JSON object.
|
|
289
|
-
|
|
357
|
+
// A .json status file that fails to load is not a usable match — return
|
|
358
|
+
// null so the caller continues to the framework default rather than
|
|
359
|
+
// rejecting out of the chain.
|
|
360
|
+
const mod = await loadModule(resolution.file).catch(() => null);
|
|
361
|
+
if (!mod) return null;
|
|
290
362
|
const jsonContent = mod.default ?? mod;
|
|
291
363
|
|
|
292
364
|
responseHeaders.set('content-type', 'application/json; charset=utf-8');
|
|
@@ -1,106 +1,193 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Error boundary wrapper — wraps a React element in error boundaries
|
|
2
|
+
* Error boundary wrapper — wraps a React element in the error boundaries
|
|
3
|
+
* declared by a route segment (`{status}.tsx`, `4xx.tsx`/`5xx.tsx`, `error.tsx`).
|
|
3
4
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
5
|
+
* This is the single implementation of that walk. It is driven by both
|
|
6
|
+
* construction sites:
|
|
7
|
+
*
|
|
8
|
+
* - `route-element-builder.ts` / `slot-resolver.ts` — the request-time
|
|
9
|
+
* renderer, walking the runtime manifest (`SegmentNode<ManifestFile>`).
|
|
10
|
+
* - `tree-builder.ts` — the build-time tree walker
|
|
11
|
+
* (`SegmentNode<RouteFile>`), with its loader and `createElement` injected.
|
|
12
|
+
*
|
|
13
|
+
* `errorBoundaryComponent` is injected rather than imported: `TimberErrorBoundary`
|
|
14
|
+
* is a `'use client'` module, and importing it here would pull client code into
|
|
15
|
+
* every consumer — including `tree-builder.ts`, which the server barrel reaches.
|
|
16
|
+
* `tests/use-client-pipeline.test.ts` walks the import graph to enforce this.
|
|
17
|
+
*
|
|
18
|
+
* See design/10-error-handling.md §"Status-Code File Variants".
|
|
6
19
|
*/
|
|
7
20
|
|
|
8
|
-
import {
|
|
9
|
-
import type {
|
|
10
|
-
import {
|
|
21
|
+
import type { ReactNode } from 'react';
|
|
22
|
+
import type { SegmentNode } from '../routing/types.js';
|
|
23
|
+
import { isValidElementType, type LoadedComponent } from './utils/element-type.js';
|
|
11
24
|
import { isMdxFilePath } from './utils/mdx-file.js';
|
|
12
25
|
|
|
26
|
+
/** The minimum a route file must carry for the walk: a path to classify as MDX. */
|
|
27
|
+
interface BoundaryFile {
|
|
28
|
+
filePath: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
13
31
|
/**
|
|
14
|
-
*
|
|
32
|
+
* Framework-injected error boundary wrapper.
|
|
33
|
+
* Wraps content with status-code error boundary handling.
|
|
15
34
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
35
|
+
* Field types must agree with `TimberErrorBoundaryProps` in
|
|
36
|
+
* `client/error-boundary.tsx`. The two are kept structurally compatible by
|
|
37
|
+
* convention rather than by direct type import — this is the server-side
|
|
38
|
+
* construction site and may not import types from a 'use client' module.
|
|
39
|
+
*/
|
|
40
|
+
export interface ErrorBoundaryProps {
|
|
41
|
+
/** The component to render when an error is caught (TSX status files). */
|
|
42
|
+
fallbackComponent?: LoadedComponent;
|
|
43
|
+
/** Pre-rendered fallback element (MDX status files — see TIM-503). */
|
|
44
|
+
fallbackElement?: ReactNode;
|
|
45
|
+
/** Status code filter: 400 = any 4xx, 500 = any 5xx, specific number = exact match. */
|
|
46
|
+
status?: number;
|
|
47
|
+
/**
|
|
48
|
+
* Segment key of the segment that declared this boundary. An in-tree deny
|
|
49
|
+
* catch site that matched a file it may not render in place re-throws with
|
|
50
|
+
* that file's owning key on the signal; boundaries whose key differs
|
|
51
|
+
* decline, so the deny page lands at its owner rather than at the first
|
|
52
|
+
* boundary the throw happens to pass. Unset for slot boundaries and for
|
|
53
|
+
* construction sites with no deny chains — an unkeyed boundary declines
|
|
54
|
+
* every owner-addressed deny. See TIM-1356.
|
|
55
|
+
*/
|
|
56
|
+
segmentKey?: string;
|
|
57
|
+
children: ReactNode;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** How to load a route file's module. Only `default` is read. */
|
|
61
|
+
type BoundaryModuleLoader<TFile> = (
|
|
62
|
+
file: TFile
|
|
63
|
+
) => { default?: unknown } | Promise<{ default?: unknown }>;
|
|
64
|
+
|
|
65
|
+
/** Everything the walk needs from its host environment. */
|
|
66
|
+
export interface ErrorBoundaryWrapConfig<TFile, TElement> {
|
|
67
|
+
/** `React.createElement` or an equivalent element factory. */
|
|
68
|
+
createElement: (type: unknown, props: object) => TElement;
|
|
69
|
+
/** Loads a route file's module. Failures skip the boundary — see below. */
|
|
70
|
+
loadModule: BoundaryModuleLoader<TFile>;
|
|
71
|
+
/**
|
|
72
|
+
* The error boundary component to instantiate (`TimberErrorBoundary`, or a
|
|
73
|
+
* host-specific stand-in). Injected — see the module docstring.
|
|
74
|
+
*/
|
|
75
|
+
errorBoundaryComponent: unknown;
|
|
76
|
+
/** When true, skip 4xx error boundaries — deny catching handles them in-tree. See TIM-666. */
|
|
77
|
+
skipDenyBoundaries?: boolean;
|
|
78
|
+
/** Segment key stamped on every boundary this walk creates. See `ErrorBoundaryProps`. */
|
|
79
|
+
segmentKey?: string;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Load a status/error file's component, or `null` if the boundary should be skipped.
|
|
84
|
+
*
|
|
85
|
+
* Two ways to get `null`, both deliberate:
|
|
86
|
+
* - the module fails to load (syntax error in the error page) — building an
|
|
87
|
+
* error boundary must not itself throw, so the boundary is skipped (TIM-584);
|
|
88
|
+
* - the default export is not a valid React component type, which would
|
|
89
|
+
* otherwise crash inside `createElement`.
|
|
90
|
+
*/
|
|
91
|
+
async function loadBoundaryComponent<TFile>(
|
|
92
|
+
file: TFile,
|
|
93
|
+
loadModule: BoundaryModuleLoader<TFile>
|
|
94
|
+
): Promise<LoadedComponent | null> {
|
|
95
|
+
let mod: { default?: unknown };
|
|
96
|
+
try {
|
|
97
|
+
mod = await loadModule(file);
|
|
98
|
+
} catch {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
return isValidElementType(mod?.default) ? mod.default : null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Wrap `element` in one error boundary rendering `Component` on failure.
|
|
20
106
|
*
|
|
21
107
|
* MDX status files are server components and cannot be passed as function
|
|
22
|
-
* props to TimberErrorBoundary (a 'use client' component).
|
|
23
|
-
*
|
|
108
|
+
* props to `TimberErrorBoundary` (a 'use client' component). They are
|
|
109
|
+
* pre-rendered as elements and passed as `fallbackElement` instead. See TIM-503.
|
|
110
|
+
*
|
|
111
|
+
* @param status boundary status filter — omitted entirely for `error.tsx`
|
|
112
|
+
* @param fallbackProps props handed to an MDX fallback when it is pre-rendered
|
|
24
113
|
*/
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
114
|
+
function wrapInBoundary<TFile extends BoundaryFile, TElement extends ReactNode>(
|
|
115
|
+
element: TElement,
|
|
116
|
+
Component: LoadedComponent,
|
|
117
|
+
file: TFile,
|
|
118
|
+
status: number | undefined,
|
|
119
|
+
fallbackProps: object,
|
|
120
|
+
config: ErrorBoundaryWrapConfig<TFile, TElement>
|
|
121
|
+
): TElement {
|
|
122
|
+
const props: ErrorBoundaryProps = isMdxFilePath(file.filePath)
|
|
123
|
+
? { fallbackElement: config.createElement(Component, fallbackProps), children: element }
|
|
124
|
+
: { fallbackComponent: Component, children: element };
|
|
125
|
+
if (status !== undefined) props.status = status;
|
|
126
|
+
if (config.segmentKey !== undefined) props.segmentKey = config.segmentKey;
|
|
127
|
+
return config.createElement(config.errorBoundaryComponent, props);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Wrap an element in the error boundaries declared by a route segment.
|
|
132
|
+
*
|
|
133
|
+
* Wrapping is applied inside-out — the last wrap produces the outermost
|
|
134
|
+
* boundary — so the processing order below is innermost to outermost:
|
|
135
|
+
*
|
|
136
|
+
* 1. Specific status files (e.g. `404.tsx`, `503.tsx`) — highest priority at runtime
|
|
137
|
+
* 2. Category catch-alls (`4xx.tsx`, `5xx.tsx`)
|
|
138
|
+
* 3. `error.tsx` — catches anything not matched by a status file
|
|
139
|
+
*
|
|
140
|
+
* The order is load-bearing: it decides which boundary catches a given throw.
|
|
141
|
+
*
|
|
142
|
+
* See design/10-error-handling.md §"Format-Aware Fallback Chains".
|
|
143
|
+
*/
|
|
144
|
+
export async function wrapSegmentWithErrorBoundaries<
|
|
145
|
+
TFile extends BoundaryFile,
|
|
146
|
+
TElement extends ReactNode,
|
|
147
|
+
>(
|
|
148
|
+
segment: SegmentNode<TFile>,
|
|
149
|
+
element: TElement,
|
|
150
|
+
config: ErrorBoundaryWrapConfig<TFile, TElement>
|
|
151
|
+
): Promise<TElement> {
|
|
152
|
+
const { loadModule, skipDenyBoundaries = false } = config;
|
|
153
|
+
|
|
33
154
|
if (segment.statusFiles) {
|
|
155
|
+
// Specific status files (innermost — highest priority at runtime)
|
|
34
156
|
for (const [key, file] of Object.entries(segment.statusFiles)) {
|
|
35
|
-
if (key
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
if (isMdxFilePath(file.filePath)) {
|
|
46
|
-
// MDX: pre-render as element (server component can't be a function prop)
|
|
47
|
-
element = h(TimberErrorBoundary, {
|
|
48
|
-
fallbackElement: h(mod.default as never, { status }),
|
|
49
|
-
status,
|
|
50
|
-
children: element,
|
|
51
|
-
});
|
|
52
|
-
} else {
|
|
53
|
-
element = h(TimberErrorBoundary, {
|
|
54
|
-
fallbackComponent: mod.default,
|
|
55
|
-
status,
|
|
56
|
-
children: element,
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
157
|
+
if (key === '4xx' || key === '5xx') continue;
|
|
158
|
+
const status = parseInt(key, 10);
|
|
159
|
+
if (isNaN(status)) continue;
|
|
160
|
+
// Skip 4xx boundaries when deny catching is active — the deny
|
|
161
|
+
// page is rendered by AccessGate/PageDenyBoundary instead.
|
|
162
|
+
if (skipDenyBoundaries && status >= 400 && status <= 499) continue;
|
|
163
|
+
|
|
164
|
+
const Component = await loadBoundaryComponent(file, loadModule);
|
|
165
|
+
if (Component) {
|
|
166
|
+
element = wrapInBoundary(element, Component, file, status, { status }, config);
|
|
61
167
|
}
|
|
62
168
|
}
|
|
63
169
|
|
|
64
170
|
// Category catch-alls (4xx.tsx, 5xx.tsx)
|
|
65
171
|
for (const [key, file] of Object.entries(segment.statusFiles)) {
|
|
172
|
+
if (key !== '4xx' && key !== '5xx') continue;
|
|
66
173
|
if (skipDenyBoundaries && key === '4xx') continue;
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
element = h(TimberErrorBoundary, {
|
|
73
|
-
fallbackElement: h(mod.default as never, {}),
|
|
74
|
-
status: categoryStatus,
|
|
75
|
-
children: element,
|
|
76
|
-
});
|
|
77
|
-
} else {
|
|
78
|
-
element = h(TimberErrorBoundary, {
|
|
79
|
-
fallbackComponent: mod.default,
|
|
80
|
-
status: categoryStatus,
|
|
81
|
-
children: element,
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
}
|
|
174
|
+
|
|
175
|
+
const Component = await loadBoundaryComponent(file, loadModule);
|
|
176
|
+
if (Component) {
|
|
177
|
+
const categoryStatus = key === '4xx' ? 400 : 500;
|
|
178
|
+
element = wrapInBoundary(element, Component, file, categoryStatus, {}, config);
|
|
85
179
|
}
|
|
86
180
|
}
|
|
87
181
|
}
|
|
88
182
|
|
|
89
|
-
// error.tsx (outermost — catches anything not matched by status files)
|
|
183
|
+
// error.tsx (outermost — catches anything not matched by status files).
|
|
184
|
+
// error.tsx/error.mdx receives { error, digest, reset } props from the
|
|
185
|
+
// boundary at catch time; MDX error files are pre-rendered without them
|
|
186
|
+
// (they're static content).
|
|
90
187
|
if (segment.error) {
|
|
91
|
-
const
|
|
92
|
-
if (
|
|
93
|
-
|
|
94
|
-
element = h(TimberErrorBoundary, {
|
|
95
|
-
fallbackElement: h(mod.default as never, {}),
|
|
96
|
-
children: element,
|
|
97
|
-
});
|
|
98
|
-
} else {
|
|
99
|
-
element = h(TimberErrorBoundary, {
|
|
100
|
-
fallbackComponent: mod.default,
|
|
101
|
-
children: element,
|
|
102
|
-
});
|
|
103
|
-
}
|
|
188
|
+
const Component = await loadBoundaryComponent(segment.error, loadModule);
|
|
189
|
+
if (Component) {
|
|
190
|
+
element = wrapInBoundary(element, Component, segment.error, undefined, {}, config);
|
|
104
191
|
}
|
|
105
192
|
}
|
|
106
193
|
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HEAD body stripping — RFC 9110 §9.3.2.
|
|
3
|
+
*
|
|
4
|
+
* "The HEAD method is identical to GET except that the server MUST NOT send
|
|
5
|
+
* content in the response." The headers, however, must be the ones the
|
|
6
|
+
* corresponding GET would have produced — which is why timber renders the
|
|
7
|
+
* route in full and discards the body here rather than short-circuiting the
|
|
8
|
+
* render. Content-Type, Content-Length, Set-Cookie, cache directives and
|
|
9
|
+
* everything else ride through untouched.
|
|
10
|
+
*
|
|
11
|
+
* Node's `ServerResponse` happens to discard writes for HEAD, so the wire is
|
|
12
|
+
* usually correct even without this. That is a property of one adapter, not of
|
|
13
|
+
* the `Response` object: static generation, the Cloudflare and Nitro adapters,
|
|
14
|
+
* tests, and anything calling the pipeline handler as a function all observe
|
|
15
|
+
* the `Response` directly and saw the full body before TIM-1324.
|
|
16
|
+
*
|
|
17
|
+
* The pipeline applies this at its single exit so every response shape is
|
|
18
|
+
* covered — page render, API route, metadata route, deny page, error page,
|
|
19
|
+
* proxy short-circuit. The two unit-level producers that are also reachable as
|
|
20
|
+
* standalone functions (`handleRouteRequest`, `handleApiRoute`) call it too, so
|
|
21
|
+
* each honours HEAD on its own; they share this implementation rather than
|
|
22
|
+
* repeating it, and applying it twice is a no-op.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Return a bodyless copy of `response` when `method` is HEAD.
|
|
27
|
+
*
|
|
28
|
+
* A no-op for every other method and for responses that already carry no body
|
|
29
|
+
* (204, 304, redirects), so callers do not need to pre-check either.
|
|
30
|
+
*
|
|
31
|
+
* The discarded stream is cancelled: an SSR render that reached this point has
|
|
32
|
+
* a live producer attached, and dropping the reference without cancelling
|
|
33
|
+
* leaks it for the lifetime of the render (design/13-security.md A4).
|
|
34
|
+
*/
|
|
35
|
+
export function stripHeadBody(response: Response, method: string): Response {
|
|
36
|
+
if (method.toUpperCase() !== 'HEAD') return response;
|
|
37
|
+
const body = response.body;
|
|
38
|
+
if (body === null) return response;
|
|
39
|
+
|
|
40
|
+
// `cancel()` rejects if the stream is already errored and throws
|
|
41
|
+
// synchronously if it is locked — neither is actionable here, the body is
|
|
42
|
+
// being discarded either way.
|
|
43
|
+
try {
|
|
44
|
+
body.cancel().catch(() => {});
|
|
45
|
+
} catch {
|
|
46
|
+
/* stream already locked or disturbed */
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return new Response(null, {
|
|
50
|
+
status: response.status,
|
|
51
|
+
statusText: response.statusText,
|
|
52
|
+
headers: response.headers,
|
|
53
|
+
});
|
|
54
|
+
}
|
package/src/server/index.ts
CHANGED
|
@@ -10,7 +10,7 @@ export type { RouteContext } from './types';
|
|
|
10
10
|
export type { Metadata, MetadataRoute, MetadataHandler, MetadataResult } from './types';
|
|
11
11
|
|
|
12
12
|
// Request Context — ALS-backed accessors (all sync)
|
|
13
|
-
// Prefer defineSearchParams().get() and
|
|
13
|
+
// Prefer defineSearchParams().get() and getSegmentParams(SEGMENT_PATH) for typed access.
|
|
14
14
|
// Design doc: design/04-authorization.md §"AccessContext does not include cookies or headers"
|
|
15
15
|
export { getHeaders, getSegmentParams } from './request-context';
|
|
16
16
|
export type { ReadonlyHeaders } from './request-context';
|
|
@@ -65,5 +65,3 @@ export { revalidatePath, revalidateTag } from './actions';
|
|
|
65
65
|
export { getTraceId, getSpanId, withSpan, addSpanEvent } from './tracing';
|
|
66
66
|
|
|
67
67
|
// Segment params types — re-exported for convenience.
|
|
68
|
-
// defineSegmentParams itself lives at @timber-js/app/segment-params.
|
|
69
|
-
export type { ParamsDefinition, InferParamField, ParamField } from '../segment-params/define.js';
|
package/src/server/internal.ts
CHANGED
|
@@ -66,12 +66,12 @@ export type {
|
|
|
66
66
|
TreeBuilderConfig,
|
|
67
67
|
TreeBuildResult,
|
|
68
68
|
LoadedModule,
|
|
69
|
-
LoadedComponent,
|
|
70
69
|
ModuleLoader,
|
|
71
70
|
AccessGateProps,
|
|
72
71
|
SlotAccessGateProps,
|
|
73
|
-
ErrorBoundaryProps,
|
|
74
72
|
} from './tree-builder.js';
|
|
73
|
+
export type { LoadedComponent } from './utils/element-type.js';
|
|
74
|
+
export type { ErrorBoundaryProps } from './error-boundary-wrapper.js';
|
|
75
75
|
|
|
76
76
|
// ── Access Gates ─────────────────────────────────────────────────────────
|
|
77
77
|
export { AccessGate, SlotAccessGate } from './access-gate.js';
|