@timber-js/app 0.2.0-alpha.12 → 0.2.0-alpha.121
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks/actions-Dy8vOjFt.js +1101 -0
- package/dist/_chunks/actions-Dy8vOjFt.js.map +1 -0
- package/dist/_chunks/build-output-helper-B1n0sUqj.js +61 -0
- package/dist/_chunks/build-output-helper-B1n0sUqj.js.map +1 -0
- package/dist/_chunks/cli-schema-sync-ByZPGGmS.js +724 -0
- package/dist/_chunks/cli-schema-sync-ByZPGGmS.js.map +1 -0
- package/dist/_chunks/cli-schema-sync-DHQLjFu3.js +2 -0
- package/dist/_chunks/codec-registry-G9hD5LOq.js +21 -0
- package/dist/_chunks/codec-registry-G9hD5LOq.js.map +1 -0
- package/dist/_chunks/define-CPVQaWbx.js +124 -0
- package/dist/_chunks/define-CPVQaWbx.js.map +1 -0
- package/dist/_chunks/define-jeHDXZGq.js +195 -0
- package/dist/_chunks/define-jeHDXZGq.js.map +1 -0
- package/dist/_chunks/format-BjN9HLu9.js +14 -0
- package/dist/_chunks/format-BjN9HLu9.js.map +1 -0
- package/dist/_chunks/handler-store-CcwNX-gk.js +54 -0
- package/dist/_chunks/handler-store-CcwNX-gk.js.map +1 -0
- package/dist/_chunks/logger-DDmK5skc.js +291 -0
- package/dist/_chunks/logger-DDmK5skc.js.map +1 -0
- package/dist/_chunks/merge-search-params-az6ZiBeU.js +41 -0
- package/dist/_chunks/merge-search-params-az6ZiBeU.js.map +1 -0
- package/dist/_chunks/navigation-root-DoRTeBm5.js +96 -0
- package/dist/_chunks/navigation-root-DoRTeBm5.js.map +1 -0
- package/dist/_chunks/registry-BI9cgCt7.js +20 -0
- package/dist/_chunks/registry-BI9cgCt7.js.map +1 -0
- package/dist/_chunks/resolve-schema-Bf8eC6q6.js +73 -0
- package/dist/_chunks/resolve-schema-Bf8eC6q6.js.map +1 -0
- package/dist/_chunks/router-ref-CpvjBqdu.js +28 -0
- package/dist/_chunks/router-ref-CpvjBqdu.js.map +1 -0
- package/dist/_chunks/schema-bridge-o0SwFtXW.js +86 -0
- package/dist/_chunks/schema-bridge-o0SwFtXW.js.map +1 -0
- package/dist/_chunks/segment-classify-CnfLLvir.js +137 -0
- package/dist/_chunks/segment-classify-CnfLLvir.js.map +1 -0
- package/dist/_chunks/segment-context-EsfQpS--.js +34 -0
- package/dist/_chunks/segment-context-EsfQpS--.js.map +1 -0
- package/dist/_chunks/{ssr-data-MjmprTmO.js → ssr-data-m9-cNEIw.js} +1 -1
- package/dist/_chunks/ssr-data-m9-cNEIw.js.map +1 -0
- package/dist/_chunks/stale-reload-BN2kcE06.js +64 -0
- package/dist/_chunks/stale-reload-BN2kcE06.js.map +1 -0
- package/dist/_chunks/tracing-DvKLzCFa.js +329 -0
- package/dist/_chunks/tracing-DvKLzCFa.js.map +1 -0
- package/dist/_chunks/{use-query-states-D5KaffOK.js → use-query-states-C9G6LP0F.js} +7 -20
- package/dist/_chunks/use-query-states-C9G6LP0F.js.map +1 -0
- package/dist/_chunks/use-segment-params-CtIAjqK0.js +185 -0
- package/dist/_chunks/use-segment-params-CtIAjqK0.js.map +1 -0
- package/dist/_chunks/validation-BMU5MPzP.js +84 -0
- package/dist/_chunks/validation-BMU5MPzP.js.map +1 -0
- package/dist/_chunks/walkers-DNp9tHyV.js +719 -0
- package/dist/_chunks/walkers-DNp9tHyV.js.map +1 -0
- package/dist/_chunks/{format-DviM89f0.js → warnings-B30wpfaS.js} +6 -45
- package/dist/_chunks/warnings-B30wpfaS.js.map +1 -0
- package/dist/adapters/build-output-helper.d.ts +28 -0
- package/dist/adapters/build-output-helper.d.ts.map +1 -0
- package/dist/adapters/cloudflare-dev.d.ts +109 -0
- package/dist/adapters/cloudflare-dev.d.ts.map +1 -0
- package/dist/adapters/cloudflare-dev.js +73 -0
- package/dist/adapters/cloudflare-dev.js.map +1 -0
- package/dist/adapters/cloudflare-kv-cache.d.ts +64 -0
- package/dist/adapters/cloudflare-kv-cache.d.ts.map +1 -0
- package/dist/adapters/cloudflare-kv-cache.js +95 -0
- package/dist/adapters/cloudflare-kv-cache.js.map +1 -0
- package/dist/adapters/cloudflare.d.ts +148 -12
- package/dist/adapters/cloudflare.d.ts.map +1 -1
- package/dist/adapters/cloudflare.js +142 -38
- package/dist/adapters/cloudflare.js.map +1 -1
- package/dist/adapters/compress-module.d.ts.map +1 -1
- package/dist/adapters/nitro.d.ts +17 -1
- package/dist/adapters/nitro.d.ts.map +1 -1
- package/dist/adapters/nitro.js +143 -45
- package/dist/adapters/nitro.js.map +1 -1
- package/dist/adapters/shared.d.ts +16 -0
- package/dist/adapters/shared.d.ts.map +1 -0
- package/dist/cache/cache-api.d.ts +24 -0
- package/dist/cache/cache-api.d.ts.map +1 -0
- package/dist/cache/handler-store.d.ts +31 -0
- package/dist/cache/handler-store.d.ts.map +1 -0
- package/dist/cache/index.d.ts +23 -7
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +151 -81
- package/dist/cache/index.js.map +1 -1
- package/dist/cache/singleflight.d.ts +18 -1
- package/dist/cache/singleflight.d.ts.map +1 -1
- package/dist/cache/sizeof.d.ts +22 -0
- package/dist/cache/sizeof.d.ts.map +1 -0
- package/dist/cache/timber-cache.d.ts +1 -1
- package/dist/cache/timber-cache.d.ts.map +1 -1
- package/dist/cli-schema-sync.d.ts +37 -0
- package/dist/cli-schema-sync.d.ts.map +1 -0
- package/dist/cli.d.ts +14 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +42 -6
- package/dist/cli.js.map +1 -1
- package/dist/client/browser-dev.d.ts +34 -1
- package/dist/client/browser-dev.d.ts.map +1 -1
- package/dist/client/browser-entry/action-dispatch.d.ts +17 -0
- package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -0
- package/dist/client/browser-entry/hmr.d.ts +21 -0
- package/dist/client/browser-entry/hmr.d.ts.map +1 -0
- package/dist/client/browser-entry/hydrate.d.ts +46 -0
- package/dist/client/browser-entry/hydrate.d.ts.map +1 -0
- package/dist/client/browser-entry/index.d.ts +30 -0
- package/dist/client/browser-entry/index.d.ts.map +1 -0
- package/dist/client/browser-entry/post-hydration.d.ts +26 -0
- package/dist/client/browser-entry/post-hydration.d.ts.map +1 -0
- package/dist/client/browser-entry/router-init.d.ts +23 -0
- package/dist/client/browser-entry/router-init.d.ts.map +1 -0
- package/dist/client/browser-entry/rsc-stream.d.ts +24 -0
- package/dist/client/browser-entry/rsc-stream.d.ts.map +1 -0
- package/dist/client/browser-entry/scroll.d.ts +19 -0
- package/dist/client/browser-entry/scroll.d.ts.map +1 -0
- package/dist/client/error-boundary.d.ts +12 -5
- package/dist/client/error-boundary.d.ts.map +1 -1
- package/dist/client/error-boundary.js +29 -6
- package/dist/client/error-boundary.js.map +1 -1
- package/dist/client/error-reconstituter.d.ts +54 -0
- package/dist/client/error-reconstituter.d.ts.map +1 -0
- package/dist/client/form.d.ts +16 -27
- package/dist/client/form.d.ts.map +1 -1
- package/dist/client/history.d.ts +19 -4
- package/dist/client/history.d.ts.map +1 -1
- package/dist/client/index.d.ts +9 -24
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +172 -1100
- package/dist/client/index.js.map +1 -1
- package/dist/client/internal.d.ts +19 -0
- package/dist/client/internal.d.ts.map +1 -0
- package/dist/client/internal.js +964 -0
- package/dist/client/internal.js.map +1 -0
- package/dist/client/link-pending-store.d.ts +63 -0
- package/dist/client/link-pending-store.d.ts.map +1 -0
- package/dist/client/link.d.ts +62 -55
- package/dist/client/link.d.ts.map +1 -1
- package/dist/client/nav-link-store.d.ts +36 -0
- package/dist/client/nav-link-store.d.ts.map +1 -0
- package/dist/client/navigation-api-types.d.ts +90 -0
- package/dist/client/navigation-api-types.d.ts.map +1 -0
- package/dist/client/navigation-api.d.ts +115 -0
- package/dist/client/navigation-api.d.ts.map +1 -0
- package/dist/client/navigation-context.d.ts +13 -2
- package/dist/client/navigation-context.d.ts.map +1 -1
- package/dist/client/{transition-root.d.ts → navigation-root.d.ts} +42 -8
- package/dist/client/navigation-root.d.ts.map +1 -0
- package/dist/client/nuqs-adapter.d.ts.map +1 -1
- package/dist/client/router-ref.d.ts +1 -1
- package/dist/client/router.d.ts +70 -4
- package/dist/client/router.d.ts.map +1 -1
- package/dist/client/rsc-fetch.d.ts +38 -3
- package/dist/client/rsc-fetch.d.ts.map +1 -1
- package/dist/client/segment-cache.d.ts +1 -1
- package/dist/client/segment-cache.d.ts.map +1 -1
- package/dist/client/segment-outlet.d.ts +63 -0
- package/dist/client/segment-outlet.d.ts.map +1 -0
- package/dist/client/ssr-data.d.ts +13 -4
- package/dist/client/ssr-data.d.ts.map +1 -1
- package/dist/client/stale-reload.d.ts +15 -0
- package/dist/client/stale-reload.d.ts.map +1 -1
- package/dist/client/state.d.ts +1 -1
- package/dist/client/top-loader.d.ts +5 -5
- package/dist/client/top-loader.d.ts.map +1 -1
- package/dist/client/use-cookie.d.ts +12 -0
- package/dist/client/use-cookie.d.ts.map +1 -1
- package/dist/client/use-link-status.d.ts +5 -5
- package/dist/client/use-link-status.d.ts.map +1 -1
- package/dist/client/{use-navigation-pending.d.ts → use-pending-navigation.d.ts} +4 -4
- package/dist/client/use-pending-navigation.d.ts.map +1 -0
- package/dist/client/use-query-states.d.ts +1 -1
- package/dist/client/use-query-states.d.ts.map +1 -1
- package/dist/client/use-router.d.ts +1 -1
- package/dist/client/{use-params.d.ts → use-segment-params.d.ts} +8 -6
- package/dist/client/use-segment-params.d.ts.map +1 -0
- package/dist/codec.d.ts +69 -0
- package/dist/codec.d.ts.map +1 -0
- package/dist/codec.js +75 -0
- package/dist/codec.js.map +1 -0
- package/dist/config-types.d.ts +294 -0
- package/dist/config-types.d.ts.map +1 -0
- package/dist/config-validation.d.ts +51 -0
- package/dist/config-validation.d.ts.map +1 -0
- package/dist/content/index.d.ts +1 -10
- package/dist/content/index.d.ts.map +1 -1
- package/dist/content/index.js +0 -2
- package/dist/cookies/define-cookie.d.ts +58 -25
- package/dist/cookies/define-cookie.d.ts.map +1 -1
- package/dist/cookies/index.d.ts +2 -1
- package/dist/cookies/index.d.ts.map +1 -1
- package/dist/cookies/index.js +251 -36
- package/dist/cookies/index.js.map +1 -1
- package/dist/cookies/json-cookie.d.ts +64 -0
- package/dist/cookies/json-cookie.d.ts.map +1 -0
- package/dist/cookies/validation.d.ts +46 -0
- package/dist/cookies/validation.d.ts.map +1 -0
- package/dist/dev-tools/404-page.d.ts +46 -0
- package/dist/dev-tools/404-page.d.ts.map +1 -0
- package/dist/dev-tools/browser-logs.d.ts +84 -0
- package/dist/dev-tools/browser-logs.d.ts.map +1 -0
- package/dist/dev-tools/error-page.d.ts +58 -0
- package/dist/dev-tools/error-page.d.ts.map +1 -0
- package/dist/dev-tools/holding-server.d.ts +54 -0
- package/dist/dev-tools/holding-server.d.ts.map +1 -0
- package/dist/dev-tools/index.d.ts +31 -0
- package/dist/dev-tools/index.d.ts.map +1 -0
- package/dist/{server/dev-span-processor.d.ts → dev-tools/instrumentation.d.ts} +26 -6
- package/dist/dev-tools/instrumentation.d.ts.map +1 -0
- package/dist/{server/dev-logger.d.ts → dev-tools/logger.d.ts} +1 -1
- package/dist/dev-tools/logger.d.ts.map +1 -0
- package/dist/{plugins/dev-logs.d.ts → dev-tools/logs.d.ts} +2 -2
- package/dist/dev-tools/logs.d.ts.map +1 -0
- package/dist/dev-tools/overlay.d.ts +91 -0
- package/dist/dev-tools/overlay.d.ts.map +1 -0
- package/dist/dev-tools/stack-classifier.d.ts +34 -0
- package/dist/dev-tools/stack-classifier.d.ts.map +1 -0
- package/dist/dev-tools/terminal.d.ts +28 -0
- package/dist/dev-tools/terminal.d.ts.map +1 -0
- package/dist/{server/dev-warnings.d.ts → dev-tools/warnings.d.ts} +2 -22
- package/dist/dev-tools/warnings.d.ts.map +1 -0
- package/dist/fonts/ast.d.ts +98 -6
- package/dist/fonts/ast.d.ts.map +1 -1
- package/dist/fonts/bundle.d.ts +48 -0
- package/dist/fonts/bundle.d.ts.map +1 -0
- package/dist/fonts/dev-middleware.d.ts +22 -0
- package/dist/fonts/dev-middleware.d.ts.map +1 -0
- package/dist/fonts/local.d.ts +1 -1
- package/dist/fonts/pipeline.d.ts +167 -0
- package/dist/fonts/pipeline.d.ts.map +1 -0
- package/dist/fonts/transform.d.ts +78 -0
- package/dist/fonts/transform.d.ts.map +1 -0
- package/dist/fonts/types.d.ts +45 -1
- package/dist/fonts/types.d.ts.map +1 -1
- package/dist/fonts/virtual-modules.d.ts +94 -0
- package/dist/fonts/virtual-modules.d.ts.map +1 -0
- package/dist/index.d.ts +46 -190
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4807 -12729
- package/dist/index.js.map +1 -1
- package/dist/params/codec-registry.d.ts +26 -0
- package/dist/params/codec-registry.d.ts.map +1 -0
- package/dist/params/define-schema.d.ts +81 -0
- package/dist/params/define-schema.d.ts.map +1 -0
- package/dist/params/index.d.ts +5 -0
- package/dist/params/index.d.ts.map +1 -0
- package/dist/params/index.js +34 -0
- package/dist/params/index.js.map +1 -0
- package/dist/params/resolve-schema.d.ts +34 -0
- package/dist/params/resolve-schema.d.ts.map +1 -0
- package/dist/plugin-context.d.ts +107 -0
- package/dist/plugin-context.d.ts.map +1 -0
- package/dist/plugins/adapter-build.d.ts +1 -1
- package/dist/plugins/adapter-build.d.ts.map +1 -1
- package/dist/plugins/build-manifest.d.ts +2 -2
- package/dist/plugins/build-manifest.d.ts.map +1 -1
- package/dist/plugins/build-report.d.ts +9 -7
- package/dist/plugins/build-report.d.ts.map +1 -1
- package/dist/plugins/client-chunks.d.ts +32 -0
- package/dist/plugins/client-chunks.d.ts.map +1 -0
- package/dist/plugins/content.d.ts +1 -1
- package/dist/plugins/content.d.ts.map +1 -1
- package/dist/plugins/dev-server.d.ts +1 -1
- package/dist/plugins/dev-server.d.ts.map +1 -1
- package/dist/plugins/entries.d.ts +1 -1
- package/dist/plugins/entries.d.ts.map +1 -1
- package/dist/plugins/fonts.d.ts +17 -73
- package/dist/plugins/fonts.d.ts.map +1 -1
- package/dist/plugins/mdx.d.ts +1 -1
- package/dist/plugins/mdx.d.ts.map +1 -1
- package/dist/plugins/routing.d.ts +1 -1
- package/dist/plugins/routing.d.ts.map +1 -1
- package/dist/plugins/server-bundle.d.ts.map +1 -1
- package/dist/plugins/shims.d.ts +6 -5
- package/dist/plugins/shims.d.ts.map +1 -1
- package/dist/plugins/static-build.d.ts +5 -26
- package/dist/plugins/static-build.d.ts.map +1 -1
- package/dist/routing/codegen-shared.d.ts +63 -0
- package/dist/routing/codegen-shared.d.ts.map +1 -0
- package/dist/routing/codegen-types.d.ts +60 -0
- package/dist/routing/codegen-types.d.ts.map +1 -0
- package/dist/routing/codegen.d.ts +7 -2
- package/dist/routing/codegen.d.ts.map +1 -1
- package/dist/routing/convention-lint.d.ts +41 -0
- package/dist/routing/convention-lint.d.ts.map +1 -0
- package/dist/routing/index.d.ts +7 -1
- package/dist/routing/index.d.ts.map +1 -1
- package/dist/routing/index.js +4 -2
- package/dist/routing/link-codegen.d.ts +90 -0
- package/dist/routing/link-codegen.d.ts.map +1 -0
- package/dist/routing/scanner.d.ts +1 -10
- package/dist/routing/scanner.d.ts.map +1 -1
- package/dist/routing/schema-validation.d.ts +35 -0
- package/dist/routing/schema-validation.d.ts.map +1 -0
- package/dist/routing/segment-classify.d.ts +75 -0
- package/dist/routing/segment-classify.d.ts.map +1 -0
- package/dist/routing/segment-codegen.d.ts +38 -0
- package/dist/routing/segment-codegen.d.ts.map +1 -0
- package/dist/routing/types.d.ts +77 -25
- package/dist/routing/types.d.ts.map +1 -1
- package/dist/routing/walkers.d.ts +51 -0
- package/dist/routing/walkers.d.ts.map +1 -0
- package/dist/rsc-runtime/rsc.d.ts +1 -1
- package/dist/rsc-runtime/rsc.d.ts.map +1 -1
- package/dist/rsc-runtime/ssr.d.ts +12 -0
- package/dist/rsc-runtime/ssr.d.ts.map +1 -1
- package/dist/schema-bridge.d.ts +76 -0
- package/dist/schema-bridge.d.ts.map +1 -0
- package/dist/search-params/define.d.ts +157 -0
- package/dist/search-params/define.d.ts.map +1 -0
- package/dist/search-params/index.d.ts +4 -7
- package/dist/search-params/index.d.ts.map +1 -1
- package/dist/search-params/index.js +34 -441
- package/dist/search-params/index.js.map +1 -1
- package/dist/search-params/registry.d.ts +2 -2
- package/dist/search-params/registry.d.ts.map +1 -1
- package/dist/search-params/wrappers.d.ts +53 -0
- package/dist/search-params/wrappers.d.ts.map +1 -0
- package/dist/segment-params/define.d.ts +95 -0
- package/dist/segment-params/define.d.ts.map +1 -0
- package/dist/segment-params/index.d.ts +3 -0
- package/dist/segment-params/index.d.ts.map +1 -0
- package/dist/segment-params/index.js +2 -0
- package/dist/server/access-gate.d.ts +8 -3
- package/dist/server/access-gate.d.ts.map +1 -1
- package/dist/server/action-client.d.ts +41 -6
- package/dist/server/action-client.d.ts.map +1 -1
- package/dist/server/action-encryption.d.ts +76 -0
- package/dist/server/action-encryption.d.ts.map +1 -0
- package/dist/server/action-handler.d.ts +35 -1
- package/dist/server/action-handler.d.ts.map +1 -1
- package/dist/server/actions.d.ts +3 -6
- package/dist/server/actions.d.ts.map +1 -1
- package/dist/server/als-registry.d.ts +53 -5
- package/dist/server/als-registry.d.ts.map +1 -1
- package/dist/server/asset-headers.d.ts +1 -15
- package/dist/server/asset-headers.d.ts.map +1 -1
- package/dist/server/build-manifest.d.ts +2 -2
- package/dist/server/build-manifest.d.ts.map +1 -1
- package/dist/server/coalesce-tick.d.ts +40 -0
- package/dist/server/coalesce-tick.d.ts.map +1 -0
- package/dist/server/cookie-context.d.ts +170 -0
- package/dist/server/cookie-context.d.ts.map +1 -0
- package/dist/server/cookie-parsing.d.ts +51 -0
- package/dist/server/cookie-parsing.d.ts.map +1 -0
- package/dist/server/debug.d.ts +1 -1
- package/dist/server/default-logger.d.ts +22 -0
- package/dist/server/default-logger.d.ts.map +1 -0
- package/dist/server/deny-boundary.d.ts +90 -0
- package/dist/server/deny-boundary.d.ts.map +1 -0
- package/dist/server/deny-renderer.d.ts.map +1 -1
- package/dist/server/dev-source-map.d.ts +22 -0
- package/dist/server/dev-source-map.d.ts.map +1 -0
- package/dist/server/early-hints-sender.d.ts.map +1 -1
- package/dist/server/early-hints.d.ts +13 -5
- package/dist/server/early-hints.d.ts.map +1 -1
- package/dist/server/error-boundary-wrapper.d.ts +7 -1
- package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
- package/dist/server/fallback-error.d.ts +12 -7
- package/dist/server/fallback-error.d.ts.map +1 -1
- package/dist/server/flight-injection-state.d.ts +66 -0
- package/dist/server/flight-injection-state.d.ts.map +1 -0
- package/dist/server/flight-scripts.d.ts +42 -0
- package/dist/server/flight-scripts.d.ts.map +1 -0
- package/dist/server/flush.d.ts.map +1 -1
- package/dist/server/form-data.d.ts +29 -0
- package/dist/server/form-data.d.ts.map +1 -1
- package/dist/server/html-injector-core.d.ts +213 -0
- package/dist/server/html-injector-core.d.ts.map +1 -0
- package/dist/server/html-injectors.d.ts +81 -41
- package/dist/server/html-injectors.d.ts.map +1 -1
- package/dist/server/index.d.ts +10 -46
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +155 -2905
- package/dist/server/index.js.map +1 -1
- package/dist/server/internal.d.ts +48 -0
- package/dist/server/internal.d.ts.map +1 -0
- package/dist/server/internal.js +2947 -0
- package/dist/server/internal.js.map +1 -0
- package/dist/server/logger.d.ts +39 -7
- package/dist/server/logger.d.ts.map +1 -1
- package/dist/server/middleware-runner.d.ts +36 -4
- package/dist/server/middleware-runner.d.ts.map +1 -1
- package/dist/server/node-stream-transforms.d.ts +112 -0
- package/dist/server/node-stream-transforms.d.ts.map +1 -0
- package/dist/server/param-coercion.d.ts +54 -0
- package/dist/server/param-coercion.d.ts.map +1 -0
- package/dist/server/pipeline-helpers.d.ts +95 -0
- package/dist/server/pipeline-helpers.d.ts.map +1 -0
- package/dist/server/pipeline-interception.d.ts +1 -1
- package/dist/server/pipeline-interception.d.ts.map +1 -1
- package/dist/server/pipeline-metadata.d.ts +6 -0
- package/dist/server/pipeline-metadata.d.ts.map +1 -1
- package/dist/server/pipeline-outcome.d.ts +49 -0
- package/dist/server/pipeline-outcome.d.ts.map +1 -0
- package/dist/server/pipeline-phases.d.ts +52 -0
- package/dist/server/pipeline-phases.d.ts.map +1 -0
- package/dist/server/pipeline.d.ts +118 -23
- package/dist/server/pipeline.d.ts.map +1 -1
- package/dist/server/port-resolution.d.ts +117 -0
- package/dist/server/port-resolution.d.ts.map +1 -0
- package/dist/server/primitives.d.ts +69 -18
- package/dist/server/primitives.d.ts.map +1 -1
- package/dist/server/render-timeout.d.ts +51 -0
- package/dist/server/render-timeout.d.ts.map +1 -0
- package/dist/server/request-context.d.ts +62 -107
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/route-element-builder.d.ts +27 -1
- package/dist/server/route-element-builder.d.ts.map +1 -1
- package/dist/server/route-handler.d.ts.map +1 -1
- package/dist/server/route-matcher.d.ts +21 -34
- package/dist/server/route-matcher.d.ts.map +1 -1
- package/dist/server/rsc-entry/action-middleware-runner.d.ts +66 -0
- package/dist/server/rsc-entry/action-middleware-runner.d.ts.map +1 -0
- package/dist/server/rsc-entry/api-handler.d.ts +2 -2
- package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
- package/dist/server/rsc-entry/error-renderer.d.ts +26 -13
- package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/helpers.d.ts +49 -6
- package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
- package/dist/server/rsc-entry/index.d.ts +19 -8
- package/dist/server/rsc-entry/index.d.ts.map +1 -1
- package/dist/server/rsc-entry/render-route.d.ts +50 -0
- package/dist/server/rsc-entry/render-route.d.ts.map +1 -0
- package/dist/server/rsc-entry/rsc-payload.d.ts +3 -3
- package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
- package/dist/server/rsc-entry/rsc-stream.d.ts +17 -1
- package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-bridge.d.ts +1 -1
- package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-renderer.d.ts +19 -4
- package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/wrap-action-dispatch.d.ts +119 -0
- package/dist/server/rsc-entry/wrap-action-dispatch.d.ts.map +1 -0
- package/dist/server/safe-load.d.ts +46 -0
- package/dist/server/safe-load.d.ts.map +1 -0
- package/dist/server/sensitive-fields.d.ts +74 -0
- package/dist/server/sensitive-fields.d.ts.map +1 -0
- package/dist/server/sitemap-generator.d.ts +129 -0
- package/dist/server/sitemap-generator.d.ts.map +1 -0
- package/dist/server/sitemap-handler.d.ts +22 -0
- package/dist/server/sitemap-handler.d.ts.map +1 -0
- package/dist/server/slot-resolver.d.ts +1 -1
- package/dist/server/slot-resolver.d.ts.map +1 -1
- package/dist/server/ssr-entry.d.ts +30 -0
- package/dist/server/ssr-entry.d.ts.map +1 -1
- package/dist/server/ssr-render.d.ts +39 -21
- package/dist/server/ssr-render.d.ts.map +1 -1
- package/dist/server/ssr-wrappers.d.ts +50 -0
- package/dist/server/ssr-wrappers.d.ts.map +1 -0
- package/dist/server/state-tree-diff.d.ts.map +1 -1
- package/dist/server/status-code-resolver.d.ts +16 -11
- package/dist/server/status-code-resolver.d.ts.map +1 -1
- package/dist/server/stream-utils.d.ts +36 -0
- package/dist/server/stream-utils.d.ts.map +1 -0
- package/dist/server/tracing.d.ts +5 -5
- package/dist/server/tracing.d.ts.map +1 -1
- package/dist/server/tree-builder.d.ts +62 -30
- package/dist/server/tree-builder.d.ts.map +1 -1
- package/dist/server/tree-match.d.ts +41 -0
- package/dist/server/tree-match.d.ts.map +1 -0
- package/dist/server/types.d.ts +49 -4
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/utils/escape-html.d.ts +14 -0
- package/dist/server/utils/escape-html.d.ts.map +1 -0
- package/dist/server/version-skew.d.ts +61 -0
- package/dist/server/version-skew.d.ts.map +1 -0
- package/dist/shared/merge-search-params.d.ts +22 -0
- package/dist/shared/merge-search-params.d.ts.map +1 -0
- package/dist/shims/font-google.d.ts +1 -1
- package/dist/shims/font-google.d.ts.map +1 -1
- package/dist/shims/font-google.js +42 -0
- package/dist/shims/font-google.js.map +1 -0
- package/dist/shims/font-local.d.ts +26 -0
- package/dist/shims/font-local.d.ts.map +1 -0
- package/dist/shims/font-local.js +20 -0
- package/dist/shims/font-local.js.map +1 -0
- package/dist/shims/headers.d.ts +2 -1
- package/dist/shims/headers.d.ts.map +1 -1
- package/dist/shims/navigation-client.d.ts +3 -1
- package/dist/shims/navigation-client.d.ts.map +1 -1
- package/dist/shims/navigation.d.ts +11 -5
- package/dist/shims/navigation.d.ts.map +1 -1
- package/dist/utils/state-machine.d.ts +80 -0
- package/dist/utils/state-machine.d.ts.map +1 -0
- package/package.json +62 -21
- package/src/adapters/build-output-helper.ts +77 -0
- package/src/adapters/cloudflare-dev.ts +177 -0
- package/src/adapters/cloudflare-kv-cache.ts +142 -0
- package/src/adapters/cloudflare.ts +350 -76
- package/src/adapters/compress-module.ts +24 -4
- package/src/adapters/nitro.ts +142 -59
- package/src/adapters/shared.ts +40 -0
- package/src/adapters/wrangler.d.ts +7 -0
- package/src/cache/cache-api.ts +38 -0
- package/src/cache/handler-store.ts +68 -0
- package/src/cache/index.ts +81 -18
- package/src/cache/singleflight.ts +62 -4
- package/src/cache/sizeof.ts +33 -0
- package/src/cache/timber-cache.ts +25 -20
- package/src/cli-schema-sync.ts +207 -0
- package/src/cli.ts +65 -8
- package/src/client/browser-dev.ts +153 -1
- package/src/client/browser-entry/action-dispatch.ts +126 -0
- package/src/client/browser-entry/hmr.ts +81 -0
- package/src/client/browser-entry/hydrate.ts +145 -0
- package/src/client/browser-entry/index.ts +149 -0
- package/src/client/browser-entry/post-hydration.ts +119 -0
- package/src/client/browser-entry/router-init.ts +193 -0
- package/src/client/browser-entry/rsc-stream.ts +157 -0
- package/src/client/browser-entry/scroll.ts +27 -0
- package/src/client/error-boundary.tsx +99 -22
- package/src/client/error-reconstituter.tsx +65 -0
- package/src/client/form.tsx +31 -32
- package/src/client/history.ts +26 -4
- package/src/client/index.ts +69 -44
- package/src/client/internal.ts +58 -0
- package/src/client/link-pending-store.ts +111 -0
- package/src/client/link.tsx +366 -113
- package/src/client/nav-link-store.ts +47 -0
- package/src/client/navigation-api-types.ts +112 -0
- package/src/client/navigation-api.ts +332 -0
- package/src/client/navigation-context.ts +31 -6
- package/src/client/navigation-root.tsx +342 -0
- package/src/client/nuqs-adapter.tsx +16 -3
- package/src/client/router-ref.ts +1 -1
- package/src/client/router.ts +300 -73
- package/src/client/rsc-fetch.ts +112 -8
- package/src/client/segment-cache.ts +1 -1
- package/src/client/segment-outlet.tsx +86 -0
- package/src/client/ssr-data.ts +13 -5
- package/src/client/stale-reload.ts +72 -3
- package/src/client/state.ts +2 -2
- package/src/client/top-loader.tsx +18 -6
- package/src/client/use-cookie.ts +31 -2
- package/src/client/use-link-status.ts +7 -7
- package/src/client/{use-navigation-pending.ts → use-pending-navigation.ts} +6 -6
- package/src/client/use-query-states.ts +9 -3
- package/src/client/use-router.ts +1 -1
- package/src/client/{use-params.ts → use-segment-params.ts} +8 -6
- package/src/codec.ts +147 -0
- package/src/config-types.ts +292 -0
- package/src/config-validation.ts +303 -0
- package/src/content/index.ts +5 -13
- package/src/cookies/define-cookie.ts +233 -53
- package/src/cookies/index.ts +12 -1
- package/src/cookies/json-cookie.ts +105 -0
- package/src/cookies/validation.ts +134 -0
- package/src/dev-tools/404-page.ts +387 -0
- package/src/dev-tools/browser-logs.ts +291 -0
- package/src/dev-tools/error-page.ts +506 -0
- package/src/dev-tools/holding-server.ts +187 -0
- package/src/dev-tools/index.ts +90 -0
- package/src/dev-tools/instrumentation.ts +176 -0
- package/src/{plugins/dev-logs.ts → dev-tools/logs.ts} +9 -5
- package/src/dev-tools/overlay.ts +469 -0
- package/src/dev-tools/stack-classifier.ts +75 -0
- package/src/dev-tools/terminal.ts +183 -0
- package/src/{server/dev-warnings.ts → dev-tools/warnings.ts} +5 -50
- package/src/fonts/ast.ts +525 -16
- package/src/fonts/bundle.ts +142 -0
- package/src/fonts/dev-middleware.ts +74 -0
- package/src/fonts/local.ts +1 -1
- package/src/fonts/pipeline.ts +314 -0
- package/src/fonts/transform.ts +317 -0
- package/src/fonts/types.ts +50 -1
- package/src/fonts/virtual-modules.ts +233 -0
- package/src/index.ts +409 -357
- package/src/params/codec-registry.ts +34 -0
- package/src/params/define-schema.ts +114 -0
- package/src/params/index.ts +17 -0
- package/src/params/resolve-schema.ts +101 -0
- package/src/plugin-context.ts +240 -0
- package/src/plugins/adapter-build.ts +12 -4
- package/src/plugins/build-manifest.ts +13 -2
- package/src/plugins/build-report.ts +16 -25
- package/src/plugins/client-chunks.ts +65 -0
- package/src/plugins/content.ts +1 -1
- package/src/plugins/dev-server.ts +175 -35
- package/src/plugins/entries.ts +111 -9
- package/src/plugins/fonts.ts +157 -654
- package/src/plugins/mdx.ts +47 -10
- package/src/plugins/routing.ts +371 -45
- package/src/plugins/server-bundle.ts +32 -1
- package/src/plugins/shims.ts +136 -35
- package/src/plugins/static-build.ts +15 -89
- package/src/routing/codegen-shared.ts +109 -0
- package/src/routing/codegen-types.ts +61 -0
- package/src/routing/codegen.ts +316 -177
- package/src/routing/convention-lint.ts +357 -0
- package/src/routing/index.ts +10 -1
- package/src/routing/interception.ts +1 -1
- package/src/routing/link-codegen.ts +308 -0
- package/src/routing/scanner.ts +165 -110
- package/src/routing/schema-validation.ts +149 -0
- package/src/routing/segment-classify.ts +188 -0
- package/src/routing/segment-codegen.ts +98 -0
- package/src/routing/types.ts +78 -25
- package/src/routing/walkers.ts +90 -0
- package/src/rsc-runtime/rsc.ts +2 -0
- package/src/rsc-runtime/ssr.ts +50 -0
- package/src/rsc-runtime/vendor-types.d.ts +7 -0
- package/src/{search-params/codecs.ts → schema-bridge.ts} +57 -20
- package/src/search-params/define.ts +538 -0
- package/src/search-params/index.ts +14 -20
- package/src/search-params/registry.ts +2 -2
- package/src/search-params/wrappers.ts +92 -0
- package/src/segment-params/define.ts +336 -0
- package/src/segment-params/index.ts +9 -0
- package/src/server/access-gate.tsx +76 -34
- package/src/server/action-client.ts +88 -15
- package/src/server/action-encryption.ts +144 -0
- package/src/server/action-handler.ts +112 -14
- package/src/server/actions.ts +10 -9
- package/src/server/als-registry.ts +55 -7
- package/src/server/asset-headers.ts +8 -34
- package/src/server/build-manifest.ts +10 -4
- package/src/server/coalesce-tick.ts +75 -0
- package/src/server/compress.ts +25 -7
- package/src/server/cookie-context.ts +468 -0
- package/src/server/cookie-parsing.ts +135 -0
- package/src/server/debug.ts +1 -1
- package/src/server/default-logger.ts +99 -0
- package/src/server/deny-boundary.ts +218 -0
- package/src/server/deny-renderer.ts +31 -50
- package/src/server/dev-source-map.ts +31 -0
- package/src/server/early-hints-sender.ts +3 -2
- package/src/server/early-hints.ts +36 -15
- package/src/server/error-boundary-wrapper.ts +74 -22
- package/src/server/fallback-error.ts +74 -102
- package/src/server/flight-injection-state.ts +113 -0
- package/src/server/flight-scripts.ts +62 -0
- package/src/server/flush.ts +2 -1
- package/src/server/form-data.ts +76 -0
- package/src/server/html-injector-core.ts +417 -0
- package/src/server/html-injectors.ts +235 -223
- package/src/server/index.ts +29 -183
- package/src/server/internal.ts +176 -0
- package/src/server/logger.ts +67 -36
- package/src/server/middleware-runner.ts +75 -4
- package/src/server/node-stream-transforms.ts +361 -0
- package/src/server/param-coercion.ts +206 -0
- package/src/server/pipeline-helpers.ts +204 -0
- package/src/server/pipeline-interception.ts +17 -16
- package/src/server/pipeline-metadata.ts +13 -0
- package/src/server/pipeline-outcome.ts +176 -0
- package/src/server/pipeline-phases.ts +460 -0
- package/src/server/pipeline.ts +154 -394
- package/src/server/port-resolution.ts +215 -0
- package/src/server/primitives.ts +111 -28
- package/src/server/render-timeout.ts +108 -0
- package/src/server/request-context.ts +168 -333
- package/src/server/route-element-builder.ts +309 -195
- package/src/server/route-handler.ts +24 -4
- package/src/server/route-matcher.ts +50 -231
- package/src/server/rsc-entry/action-middleware-runner.ts +167 -0
- package/src/server/rsc-entry/api-handler.ts +16 -17
- package/src/server/rsc-entry/error-renderer.ts +305 -89
- package/src/server/rsc-entry/helpers.ts +137 -12
- package/src/server/rsc-entry/index.ts +316 -352
- package/src/server/rsc-entry/render-route.ts +307 -0
- package/src/server/rsc-entry/rsc-payload.ts +65 -18
- package/src/server/rsc-entry/rsc-stream.ts +85 -13
- package/src/server/rsc-entry/ssr-bridge.ts +14 -5
- package/src/server/rsc-entry/ssr-renderer.ts +187 -38
- package/src/server/rsc-entry/wrap-action-dispatch.ts +449 -0
- package/src/server/safe-load.ts +60 -0
- package/src/server/sensitive-fields.ts +230 -0
- package/src/server/sitemap-generator.ts +338 -0
- package/src/server/sitemap-handler.ts +126 -0
- package/src/server/slot-resolver.ts +228 -246
- package/src/server/ssr-entry.ts +229 -32
- package/src/server/ssr-render.ts +289 -67
- package/src/server/ssr-wrappers.tsx +139 -0
- package/src/server/state-tree-diff.ts +4 -1
- package/src/server/status-code-resolver.ts +112 -128
- package/src/server/stream-utils.ts +213 -0
- package/src/server/tracing.ts +21 -10
- package/src/server/tree-builder.ts +202 -90
- package/src/server/tree-match.ts +198 -0
- package/src/server/types.ts +55 -6
- package/src/server/utils/escape-html.ts +20 -0
- package/src/server/version-skew.ts +104 -0
- package/src/shared/merge-search-params.ts +55 -0
- package/src/shims/font-google.ts +1 -1
- package/src/shims/font-local.ts +34 -0
- package/src/shims/headers.ts +5 -1
- package/src/shims/navigation-client.ts +4 -3
- package/src/shims/navigation.ts +14 -7
- package/src/utils/state-machine.ts +111 -0
- package/LICENSE +0 -8
- package/dist/_chunks/als-registry-B7DbZ2hS.js +0 -41
- package/dist/_chunks/als-registry-B7DbZ2hS.js.map +0 -1
- package/dist/_chunks/debug-gwlJkDuf.js +0 -108
- package/dist/_chunks/debug-gwlJkDuf.js.map +0 -1
- package/dist/_chunks/format-DviM89f0.js.map +0 -1
- package/dist/_chunks/interception-BOoWmLUA.js +0 -676
- package/dist/_chunks/interception-BOoWmLUA.js.map +0 -1
- package/dist/_chunks/request-context-DIkVh_jG.js +0 -330
- package/dist/_chunks/request-context-DIkVh_jG.js.map +0 -1
- package/dist/_chunks/ssr-data-MjmprTmO.js.map +0 -1
- package/dist/_chunks/tracing-CemImE6h.js +0 -187
- package/dist/_chunks/tracing-CemImE6h.js.map +0 -1
- package/dist/_chunks/use-cookie-DX-l1_5E.js +0 -91
- package/dist/_chunks/use-cookie-DX-l1_5E.js.map +0 -1
- package/dist/_chunks/use-query-states-D5KaffOK.js.map +0 -1
- package/dist/cache/register-cached-function.d.ts +0 -17
- package/dist/cache/register-cached-function.d.ts.map +0 -1
- package/dist/client/browser-entry.d.ts +0 -21
- package/dist/client/browser-entry.d.ts.map +0 -1
- package/dist/client/link-status-provider.d.ts +0 -11
- package/dist/client/link-status-provider.d.ts.map +0 -1
- package/dist/client/transition-root.d.ts.map +0 -1
- package/dist/client/use-navigation-pending.d.ts.map +0 -1
- package/dist/client/use-params.d.ts.map +0 -1
- package/dist/plugins/cache-transform.d.ts +0 -36
- package/dist/plugins/cache-transform.d.ts.map +0 -1
- package/dist/plugins/dev-error-overlay.d.ts +0 -60
- package/dist/plugins/dev-error-overlay.d.ts.map +0 -1
- package/dist/plugins/dev-logs.d.ts.map +0 -1
- package/dist/plugins/dynamic-transform.d.ts +0 -72
- package/dist/plugins/dynamic-transform.d.ts.map +0 -1
- package/dist/plugins/server-action-exports.d.ts +0 -26
- package/dist/plugins/server-action-exports.d.ts.map +0 -1
- package/dist/routing/status-file-lint.d.ts +0 -33
- package/dist/routing/status-file-lint.d.ts.map +0 -1
- package/dist/search-params/analyze.d.ts +0 -54
- package/dist/search-params/analyze.d.ts.map +0 -1
- package/dist/search-params/builtin-codecs.d.ts +0 -105
- package/dist/search-params/builtin-codecs.d.ts.map +0 -1
- package/dist/search-params/codecs.d.ts +0 -53
- package/dist/search-params/codecs.d.ts.map +0 -1
- package/dist/search-params/create.d.ts +0 -106
- package/dist/search-params/create.d.ts.map +0 -1
- package/dist/server/dev-fetch-instrumentation.d.ts +0 -22
- package/dist/server/dev-fetch-instrumentation.d.ts.map +0 -1
- package/dist/server/dev-logger.d.ts.map +0 -1
- package/dist/server/dev-span-processor.d.ts.map +0 -1
- package/dist/server/dev-warnings.d.ts.map +0 -1
- package/dist/server/manifest-status-resolver.d.ts +0 -58
- package/dist/server/manifest-status-resolver.d.ts.map +0 -1
- package/dist/server/prerender.d.ts +0 -77
- package/dist/server/prerender.d.ts.map +0 -1
- package/dist/server/response-cache.d.ts +0 -54
- package/dist/server/response-cache.d.ts.map +0 -1
- package/dist/utils/directive-parser.d.ts +0 -70
- package/dist/utils/directive-parser.d.ts.map +0 -1
- package/src/cache/register-cached-function.ts +0 -103
- package/src/client/browser-entry.ts +0 -678
- package/src/client/link-status-provider.tsx +0 -30
- package/src/client/transition-root.tsx +0 -166
- package/src/plugins/cache-transform.ts +0 -199
- package/src/plugins/dev-error-overlay.ts +0 -230
- package/src/plugins/dynamic-transform.ts +0 -161
- package/src/plugins/server-action-exports.ts +0 -220
- package/src/routing/status-file-lint.ts +0 -112
- package/src/search-params/analyze.ts +0 -192
- package/src/search-params/builtin-codecs.ts +0 -228
- package/src/search-params/create.ts +0 -321
- package/src/server/dev-fetch-instrumentation.ts +0 -96
- package/src/server/dev-span-processor.ts +0 -78
- package/src/server/manifest-status-resolver.ts +0 -215
- package/src/server/prerender.ts +0 -139
- package/src/server/response-cache.ts +0 -410
- package/src/utils/directive-parser.ts +0 -529
- /package/src/{server/dev-logger.ts → dev-tools/logger.ts} +0 -0
|
@@ -7,17 +7,18 @@
|
|
|
7
7
|
*
|
|
8
8
|
* This module handles:
|
|
9
9
|
* 1. Loading page/layout components from the segment chain
|
|
10
|
-
* 2.
|
|
10
|
+
* 2. Collecting access.ts checks (executed inside render by AccessPreRunner)
|
|
11
11
|
* 3. Resolving metadata (static object or async function, both exported as `metadata`)
|
|
12
12
|
* 4. Building the React element tree (page → error boundaries → access gates → layouts)
|
|
13
13
|
* 5. Resolving parallel slots
|
|
14
|
+
* 6. Wrapping the tree with AccessPreRunner for React.cache-scoped access checks
|
|
14
15
|
*
|
|
15
16
|
* See design/02-rendering-pipeline.md, design/04-authorization.md
|
|
16
17
|
*/
|
|
17
18
|
|
|
18
19
|
import { createElement } from 'react';
|
|
19
20
|
|
|
20
|
-
import { withSpan
|
|
21
|
+
import { withSpan } from './tracing.js';
|
|
21
22
|
import type { RouteMatch } from './pipeline.js';
|
|
22
23
|
import type { ManifestSegmentNode } from './route-matcher.js';
|
|
23
24
|
import { resolveMetadata, renderMetadataToElements } from './metadata.js';
|
|
@@ -26,13 +27,61 @@ import type { Metadata } from './types.js';
|
|
|
26
27
|
import { METADATA_ROUTE_CONVENTIONS, getMetadataRouteAutoLink } from './metadata-routes.js';
|
|
27
28
|
import { DenySignal, RedirectSignal } from './primitives.js';
|
|
28
29
|
import { AccessGate } from './access-gate.js';
|
|
30
|
+
import {
|
|
31
|
+
PageDenyBoundary,
|
|
32
|
+
buildDenyPageChain,
|
|
33
|
+
renderMatchingDenyPage,
|
|
34
|
+
setDenyStatus,
|
|
35
|
+
} from './deny-boundary.js';
|
|
36
|
+
import type { DenyPageEntry } from './deny-boundary.js';
|
|
29
37
|
import { resolveSlotElement } from './slot-resolver.js';
|
|
30
|
-
import { SegmentProvider } from '
|
|
31
|
-
|
|
32
|
-
import type { SearchParamsDefinition } from '#/search-params/create.js';
|
|
38
|
+
import { SegmentProvider } from '../client/segment-context.js';
|
|
39
|
+
|
|
33
40
|
import { wrapSegmentWithErrorBoundaries } from './error-boundary-wrapper.js';
|
|
34
41
|
import type { InterceptionContext } from './pipeline.js';
|
|
35
42
|
import { shouldSkipSegment } from './state-tree-diff.js';
|
|
43
|
+
import { loadModule } from './safe-load.js';
|
|
44
|
+
|
|
45
|
+
// ─── Client Reference Detection ──────────────────────────────────────────
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Symbol used by React Flight to mark client references.
|
|
49
|
+
* Client references are proxy objects created by @vitejs/plugin-rsc for
|
|
50
|
+
* 'use client' modules in the RSC environment. They must be passed to
|
|
51
|
+
* createElement() — calling them as functions throws:
|
|
52
|
+
* "Unexpectedly client reference export 'default' is called on server"
|
|
53
|
+
*/
|
|
54
|
+
const CLIENT_REFERENCE_TAG = Symbol.for('react.client.reference');
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Detect whether a component is a React client reference.
|
|
58
|
+
* Client references have $$typeof set to Symbol.for('react.client.reference')
|
|
59
|
+
* by registerClientReference() in the React Flight server runtime.
|
|
60
|
+
*
|
|
61
|
+
* Used to skip OTEL tracing wrappers that would call the component as a
|
|
62
|
+
* function. Client components must go through createElement only — they are
|
|
63
|
+
* serialized as references in the RSC Flight stream, not executed on the server.
|
|
64
|
+
*/
|
|
65
|
+
export function isClientReference(component: unknown): boolean {
|
|
66
|
+
return (
|
|
67
|
+
component != null &&
|
|
68
|
+
typeof component === 'function' &&
|
|
69
|
+
(component as unknown as Record<string, unknown>).$$typeof === CLIENT_REFERENCE_TAG
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ─── Param Coercion Error ─────────────────────────────────────────────────
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Thrown when a defineSegmentParams codec's parse() fails.
|
|
77
|
+
* The pipeline catches this and responds with 404.
|
|
78
|
+
*/
|
|
79
|
+
export class ParamCoercionError extends Error {
|
|
80
|
+
constructor(message: string) {
|
|
81
|
+
super(message);
|
|
82
|
+
this.name = 'ParamCoercionError';
|
|
83
|
+
}
|
|
84
|
+
}
|
|
36
85
|
|
|
37
86
|
// ─── Types ────────────────────────────────────────────────────────────────
|
|
38
87
|
|
|
@@ -73,6 +122,10 @@ export interface RouteElementResult {
|
|
|
73
122
|
/**
|
|
74
123
|
* Wraps a DenySignal or RedirectSignal with the layout components loaded
|
|
75
124
|
* so far, enabling the caller to render deny pages inside the layout shell.
|
|
125
|
+
*
|
|
126
|
+
* @deprecated No longer thrown by buildRouteElement since TIM-662. Access
|
|
127
|
+
* checks now run inside AccessPreRunner during renderToReadableStream, and
|
|
128
|
+
* signals are caught by onError. Kept for backward compat with external code.
|
|
76
129
|
*/
|
|
77
130
|
export class RouteSignalWithContext extends Error {
|
|
78
131
|
constructor(
|
|
@@ -84,6 +137,64 @@ export class RouteSignalWithContext extends Error {
|
|
|
84
137
|
}
|
|
85
138
|
}
|
|
86
139
|
|
|
140
|
+
// ─── Module Processing Helpers ─────────────────────────────────────────────
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Reject the legacy `generateMetadata` export with a helpful migration message.
|
|
144
|
+
* Throws if the module exports `generateMetadata` instead of `metadata`.
|
|
145
|
+
*/
|
|
146
|
+
function rejectLegacyGenerateMetadata(mod: Record<string, unknown>, filePath: string): void {
|
|
147
|
+
if ('generateMetadata' in mod) {
|
|
148
|
+
throw new Error(
|
|
149
|
+
`${filePath}: "generateMetadata" is not a valid export. ` +
|
|
150
|
+
`Export an async function named "metadata" instead.\n\n` +
|
|
151
|
+
` // Before\n` +
|
|
152
|
+
` export async function generateMetadata({ params }) { ... }\n\n` +
|
|
153
|
+
` // After\n` +
|
|
154
|
+
` export async function metadata() { ... }`
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Extract and resolve metadata from a module (layout or page).
|
|
161
|
+
* Handles both static metadata objects and async metadata functions.
|
|
162
|
+
* Returns the resolved Metadata, or null if none exported.
|
|
163
|
+
*
|
|
164
|
+
* Metadata functions no longer receive { params } — they access params
|
|
165
|
+
* via getSegmentParams() from ALS, same as page/layout components.
|
|
166
|
+
*/
|
|
167
|
+
async function extractMetadata(
|
|
168
|
+
mod: Record<string, unknown>,
|
|
169
|
+
segment: ManifestSegmentNode
|
|
170
|
+
): Promise<Metadata | null> {
|
|
171
|
+
if (typeof mod.metadata === 'function') {
|
|
172
|
+
type MetadataFn = () => Promise<Metadata>;
|
|
173
|
+
return (
|
|
174
|
+
(await withSpan(
|
|
175
|
+
'timber.metadata',
|
|
176
|
+
{ 'timber.segment': segment.segmentName ?? segment.urlPath },
|
|
177
|
+
() => (mod.metadata as MetadataFn)()
|
|
178
|
+
)) ?? null
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
if (mod.metadata) {
|
|
182
|
+
return mod.metadata as Metadata;
|
|
183
|
+
}
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Extract `deferSuspenseFor` from a module and return the maximum
|
|
189
|
+
* of the current value and the module's value.
|
|
190
|
+
*/
|
|
191
|
+
function extractDeferSuspenseFor(mod: Record<string, unknown>, current: number): number {
|
|
192
|
+
if (typeof mod.deferSuspenseFor === 'number' && mod.deferSuspenseFor > current) {
|
|
193
|
+
return mod.deferSuspenseFor;
|
|
194
|
+
}
|
|
195
|
+
return current;
|
|
196
|
+
}
|
|
197
|
+
|
|
87
198
|
// ─── Builder ──────────────────────────────────────────────────────────────
|
|
88
199
|
|
|
89
200
|
/**
|
|
@@ -95,6 +206,10 @@ export class RouteSignalWithContext extends Error {
|
|
|
95
206
|
*
|
|
96
207
|
* Does NOT serialize to RSC Flight — the caller decides whether to render
|
|
97
208
|
* to a stream or use the element directly (e.g., for action revalidation).
|
|
209
|
+
*
|
|
210
|
+
* Access checks are collected but NOT executed here. They run inside
|
|
211
|
+
* AccessPreRunner during renderToReadableStream so that access.ts and
|
|
212
|
+
* render components share the same React.cache scope (TIM-662).
|
|
98
213
|
*/
|
|
99
214
|
export async function buildRouteElement(
|
|
100
215
|
req: Request,
|
|
@@ -102,10 +217,7 @@ export async function buildRouteElement(
|
|
|
102
217
|
interception?: InterceptionContext,
|
|
103
218
|
clientStateTree?: Set<string> | null
|
|
104
219
|
): Promise<RouteElementResult> {
|
|
105
|
-
const segments = match.segments
|
|
106
|
-
|
|
107
|
-
// Params are passed as a Promise to match Next.js 15+ convention.
|
|
108
|
-
const paramsPromise = Promise.resolve(match.params);
|
|
220
|
+
const segments = match.segments;
|
|
109
221
|
|
|
110
222
|
// Load all modules along the segment chain
|
|
111
223
|
const metadataEntries: Array<{ metadata: Metadata; isPage: boolean }> = [];
|
|
@@ -119,149 +231,77 @@ export async function buildRouteElement(
|
|
|
119
231
|
|
|
120
232
|
// Load layout
|
|
121
233
|
if (segment.layout) {
|
|
122
|
-
const mod =
|
|
234
|
+
const mod = await loadModule(segment.layout);
|
|
123
235
|
if (mod.default) {
|
|
124
236
|
layoutComponents.push({
|
|
125
237
|
component: mod.default as (...args: unknown[]) => unknown,
|
|
126
238
|
segment,
|
|
127
239
|
});
|
|
128
240
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
` // After\n` +
|
|
138
|
-
` export async function metadata({ params }) { ... }`
|
|
139
|
-
);
|
|
140
|
-
}
|
|
141
|
-
// Unified metadata export: static object or async function
|
|
142
|
-
if (typeof mod.metadata === 'function') {
|
|
143
|
-
type MetadataFn = (props: Record<string, unknown>) => Promise<Metadata>;
|
|
144
|
-
const generated = await withSpan(
|
|
145
|
-
'timber.metadata',
|
|
146
|
-
{ 'timber.segment': segment.segmentName ?? segment.urlPath },
|
|
147
|
-
() => (mod.metadata as MetadataFn)({ params: paramsPromise })
|
|
148
|
-
);
|
|
149
|
-
if (generated) {
|
|
150
|
-
metadataEntries.push({ metadata: generated, isPage: false });
|
|
151
|
-
}
|
|
152
|
-
} else if (mod.metadata) {
|
|
153
|
-
metadataEntries.push({ metadata: mod.metadata as Metadata, isPage: false });
|
|
154
|
-
}
|
|
155
|
-
// deferSuspenseFor hold window — max across all segments
|
|
156
|
-
if (typeof mod.deferSuspenseFor === 'number' && mod.deferSuspenseFor > deferSuspenseFor) {
|
|
157
|
-
deferSuspenseFor = mod.deferSuspenseFor;
|
|
241
|
+
|
|
242
|
+
// Param coercion is handled in the pipeline (Stage 2c) before
|
|
243
|
+
// middleware and rendering. See coerceSegmentParams() in pipeline.ts.
|
|
244
|
+
|
|
245
|
+
rejectLegacyGenerateMetadata(mod, segment.layout.filePath ?? segment.urlPath);
|
|
246
|
+
const layoutMetadata = await extractMetadata(mod, segment);
|
|
247
|
+
if (layoutMetadata) {
|
|
248
|
+
metadataEntries.push({ metadata: layoutMetadata, isPage: false });
|
|
158
249
|
}
|
|
250
|
+
deferSuspenseFor = extractDeferSuspenseFor(mod, deferSuspenseFor);
|
|
159
251
|
}
|
|
160
252
|
|
|
161
253
|
// Load page (leaf segment only)
|
|
162
254
|
if (isLeaf && segment.page) {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
default?: SearchParamsDefinition<Record<string, unknown>>;
|
|
168
|
-
};
|
|
169
|
-
if (spMod.default) {
|
|
170
|
-
const rawSearchParams = new URL(req.url).searchParams;
|
|
171
|
-
const parsed = spMod.default.parse(rawSearchParams);
|
|
172
|
-
setParsedSearchParams(parsed);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
255
|
+
const mod = await loadModule(segment.page);
|
|
256
|
+
|
|
257
|
+
// Param coercion is handled in the pipeline (Stage 2c) before
|
|
258
|
+
// middleware and rendering. See coerceSegmentParams() in pipeline.ts.
|
|
175
259
|
|
|
176
|
-
const mod = (await segment.page.load()) as Record<string, unknown>;
|
|
177
260
|
if (mod.default) {
|
|
178
261
|
PageComponent = mod.default as (...args: unknown[]) => unknown;
|
|
179
262
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
`${filePath}: "generateMetadata" is not a valid export. ` +
|
|
185
|
-
`Export an async function named "metadata" instead.\n\n` +
|
|
186
|
-
` // Before\n` +
|
|
187
|
-
` export async function generateMetadata({ params }) { ... }\n\n` +
|
|
188
|
-
` // After\n` +
|
|
189
|
-
` export async function metadata({ params }) { ... }`
|
|
190
|
-
);
|
|
191
|
-
}
|
|
192
|
-
// Unified metadata export: static object or async function
|
|
193
|
-
if (typeof mod.metadata === 'function') {
|
|
194
|
-
type MetadataFn = (props: Record<string, unknown>) => Promise<Metadata>;
|
|
195
|
-
const generated = await withSpan(
|
|
196
|
-
'timber.metadata',
|
|
197
|
-
{ 'timber.segment': segment.segmentName ?? segment.urlPath },
|
|
198
|
-
() => (mod.metadata as MetadataFn)({ params: paramsPromise })
|
|
199
|
-
);
|
|
200
|
-
if (generated) {
|
|
201
|
-
metadataEntries.push({ metadata: generated, isPage: true });
|
|
202
|
-
}
|
|
203
|
-
} else if (mod.metadata) {
|
|
204
|
-
metadataEntries.push({ metadata: mod.metadata as Metadata, isPage: true });
|
|
205
|
-
}
|
|
206
|
-
// deferSuspenseFor hold window — max across all segments
|
|
207
|
-
if (typeof mod.deferSuspenseFor === 'number' && mod.deferSuspenseFor > deferSuspenseFor) {
|
|
208
|
-
deferSuspenseFor = mod.deferSuspenseFor;
|
|
263
|
+
rejectLegacyGenerateMetadata(mod, segment.page.filePath ?? segment.urlPath);
|
|
264
|
+
const pageMetadata = await extractMetadata(mod, segment);
|
|
265
|
+
if (pageMetadata) {
|
|
266
|
+
metadataEntries.push({ metadata: pageMetadata, isPage: true });
|
|
209
267
|
}
|
|
268
|
+
deferSuspenseFor = extractDeferSuspenseFor(mod, deferSuspenseFor);
|
|
210
269
|
}
|
|
211
270
|
}
|
|
212
271
|
|
|
213
272
|
if (!PageComponent) {
|
|
214
|
-
|
|
273
|
+
const segmentInfo = segments
|
|
274
|
+
.map(
|
|
275
|
+
(s, i) =>
|
|
276
|
+
` [${i}] ${s.segmentName} (page: ${s.page ? 'yes' : 'no'}, layout: ${s.layout ? 'yes' : 'no'}, children: ${s.children?.length ?? 0})${i === segments.length - 1 ? ' ← leaf' : ''}`
|
|
277
|
+
)
|
|
278
|
+
.join('\n');
|
|
279
|
+
throw new Error(
|
|
280
|
+
`No page component found for route: ${new URL(req.url).pathname}\nMatched segments:\n${segmentInfo}`
|
|
281
|
+
);
|
|
215
282
|
}
|
|
216
283
|
|
|
217
|
-
//
|
|
218
|
-
//
|
|
219
|
-
//
|
|
220
|
-
//
|
|
221
|
-
//
|
|
222
|
-
//
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
try {
|
|
239
|
-
await accessFn({ params: match.params, searchParams: {} });
|
|
240
|
-
await setSpanAttribute('timber.result', 'pass');
|
|
241
|
-
accessVerdicts.set(si, 'pass');
|
|
242
|
-
} catch (error) {
|
|
243
|
-
if (error instanceof DenySignal) {
|
|
244
|
-
await setSpanAttribute('timber.result', 'deny');
|
|
245
|
-
await setSpanAttribute('timber.deny_status', error.status);
|
|
246
|
-
if (error.sourceFile) {
|
|
247
|
-
await setSpanAttribute('timber.deny_file', error.sourceFile);
|
|
248
|
-
}
|
|
249
|
-
accessVerdicts.set(si, error);
|
|
250
|
-
} else if (error instanceof RedirectSignal) {
|
|
251
|
-
await setSpanAttribute('timber.result', 'redirect');
|
|
252
|
-
accessVerdicts.set(si, error);
|
|
253
|
-
}
|
|
254
|
-
throw error;
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
);
|
|
258
|
-
} catch (error) {
|
|
259
|
-
if (error instanceof DenySignal || error instanceof RedirectSignal) {
|
|
260
|
-
throw new RouteSignalWithContext(error, layoutComponents, segments);
|
|
261
|
-
}
|
|
262
|
-
throw error;
|
|
263
|
-
}
|
|
264
|
-
}
|
|
284
|
+
// Access checks are NOT run here. AccessGate components in the element
|
|
285
|
+
// tree call accessFn directly during renderToReadableStream, sharing the
|
|
286
|
+
// same React.cache scope as layout/page components. A requireUser() call
|
|
287
|
+
// in access.ts populates React.cache; the same call in a layout is a hit.
|
|
288
|
+
//
|
|
289
|
+
// Previously (before TIM-662), access checks ran eagerly in a pre-render
|
|
290
|
+
// loop OUTSIDE renderToReadableStream, breaking React.cache dedup.
|
|
291
|
+
//
|
|
292
|
+
// See design/04-authorization.md §"Pre-Render Pass and Verdict Replay"
|
|
293
|
+
|
|
294
|
+
// Build deny page fallback chains for each segment position.
|
|
295
|
+
// When AccessGate or PageDenyBoundary catches a DenySignal, they render
|
|
296
|
+
// the matching deny page in-tree instead of throwing into React Flight.
|
|
297
|
+
// The chain walks from the current segment outward to root, collecting
|
|
298
|
+
// status-code files (403.tsx → 4xx.tsx → error.tsx) in fallback order.
|
|
299
|
+
// See TIM-666.
|
|
300
|
+
const denyPageChains = new Map<number, DenyPageEntry[]>();
|
|
301
|
+
for (let i = 0; i < segments.length; i++) {
|
|
302
|
+
const chain = await buildDenyPageChain(segments, i);
|
|
303
|
+
if (chain.length > 0) {
|
|
304
|
+
denyPageChains.set(i, chain);
|
|
265
305
|
}
|
|
266
306
|
}
|
|
267
307
|
|
|
@@ -293,19 +333,43 @@ export async function buildRouteElement(
|
|
|
293
333
|
// Build element tree: page wrapped in layouts (innermost to outermost)
|
|
294
334
|
const h = createElement as (...args: unknown[]) => React.ReactElement;
|
|
295
335
|
|
|
296
|
-
//
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
336
|
+
// Build the page element.
|
|
337
|
+
// Client references ('use client' pages) must NOT be called as functions —
|
|
338
|
+
// they are proxy objects that throw when invoked. They must go through
|
|
339
|
+
// createElement only, which serializes them as client references in the
|
|
340
|
+
// RSC Flight stream. OTEL tracing is skipped for client components.
|
|
341
|
+
// See TIM-627 for the original bug.
|
|
342
|
+
// Build the page element.
|
|
343
|
+
// Server component pages are wrapped in PageDenyBoundary which calls
|
|
344
|
+
// them as async functions and catches DenySignal — rendering the deny
|
|
345
|
+
// page in-tree instead of throwing into React Flight. This eliminates
|
|
346
|
+
// the second render pass for deny pages. See TIM-666.
|
|
347
|
+
//
|
|
348
|
+
// Client reference pages ('use client') can't call deny() (server-only),
|
|
349
|
+
// so they go through createElement normally — no wrapper needed.
|
|
350
|
+
const leafIndex = segments.length - 1;
|
|
351
|
+
const leafDenyPages = denyPageChains.get(leafIndex);
|
|
352
|
+
let element: React.ReactElement;
|
|
353
|
+
if (isClientReference(PageComponent)) {
|
|
354
|
+
element = h(PageComponent, {});
|
|
355
|
+
} else if (leafDenyPages && leafDenyPages.length > 0) {
|
|
356
|
+
// Server component page WITH deny page chain — wrap in PageDenyBoundary
|
|
357
|
+
element = h(PageDenyBoundary, {
|
|
358
|
+
Page: PageComponent,
|
|
359
|
+
route: match.segments[leafIndex]?.urlPath ?? '/',
|
|
360
|
+
denyPages: leafDenyPages,
|
|
361
|
+
});
|
|
362
|
+
} else {
|
|
363
|
+
// Server component page WITHOUT deny page chain — trace only
|
|
364
|
+
const TracedPage = async (props: Record<string, unknown>) => {
|
|
365
|
+
return withSpan(
|
|
366
|
+
'timber.page',
|
|
367
|
+
{ 'timber.route': match.segments[leafIndex]?.urlPath ?? '/' },
|
|
368
|
+
() => (PageComponent as (props: Record<string, unknown>) => unknown)(props)
|
|
369
|
+
);
|
|
370
|
+
};
|
|
371
|
+
element = h(TracedPage, {});
|
|
372
|
+
}
|
|
309
373
|
|
|
310
374
|
// Build a lookup of layout components by segment for O(1) access.
|
|
311
375
|
const layoutBySegment = new Map(
|
|
@@ -357,11 +421,28 @@ export async function buildRouteElement(
|
|
|
357
421
|
segment.segmentType !== 'group';
|
|
358
422
|
|
|
359
423
|
if (skip) {
|
|
360
|
-
// Skip this segment
|
|
361
|
-
// Access.ts already ran in the pre-render loop (security guarantee).
|
|
424
|
+
// Skip this segment's layout/error boundaries — the client uses its cached version.
|
|
362
425
|
// Metadata was already resolved above (head elements are correct).
|
|
363
426
|
// Record for X-Timber-Skipped-Segments header (outermost first, so prepend).
|
|
364
427
|
skippedSegments.unshift(segment.urlPath);
|
|
428
|
+
|
|
429
|
+
// SECURITY: Even though the layout is skipped, AccessGate MUST still
|
|
430
|
+
// wrap the element tree. access.ts runs on every navigation regardless
|
|
431
|
+
// of cached layouts or state tree content.
|
|
432
|
+
// See design/13-security.md §"Auth always runs" (test #11).
|
|
433
|
+
if (segment.access) {
|
|
434
|
+
const accessMod = await loadModule(segment.access);
|
|
435
|
+
const accessFn = accessMod.default as (() => unknown) | undefined;
|
|
436
|
+
if (accessFn) {
|
|
437
|
+
element = h(AccessGate, {
|
|
438
|
+
accessFn,
|
|
439
|
+
segmentName: segment.segmentName,
|
|
440
|
+
denyPages: denyPageChains.get(i),
|
|
441
|
+
children: element,
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
365
446
|
continue;
|
|
366
447
|
}
|
|
367
448
|
|
|
@@ -372,83 +453,116 @@ export async function buildRouteElement(
|
|
|
372
453
|
}
|
|
373
454
|
|
|
374
455
|
// Wrap with error boundaries from this segment (inside layout).
|
|
456
|
+
// Keep ALL error boundaries (including 4xx) — they're the safety net for
|
|
457
|
+
// DenySignal from nested server components that escape AccessGate/PageDenyBoundary
|
|
458
|
+
// try/catch. Status-code files must be 'use client' TSX or MDX to serialize
|
|
459
|
+
// as error boundary fallbacks. See TIM-666.
|
|
375
460
|
element = await wrapSegmentWithErrorBoundaries(segment, element, h);
|
|
376
461
|
|
|
377
|
-
// Wrap
|
|
378
|
-
//
|
|
379
|
-
//
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
const accessFn = accessMod.default as
|
|
383
|
-
| ((ctx: { params: Record<string, string | string[]>; searchParams: unknown }) => unknown)
|
|
384
|
-
| undefined;
|
|
385
|
-
if (accessFn) {
|
|
386
|
-
element = h(AccessGate, {
|
|
387
|
-
accessFn,
|
|
388
|
-
params: match.params,
|
|
389
|
-
searchParams: {},
|
|
390
|
-
segmentName: segment.segmentName,
|
|
391
|
-
verdict: accessVerdicts.get(i),
|
|
392
|
-
children: element,
|
|
393
|
-
});
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
// Wrap with layout if this segment has one — traced with OTEL span
|
|
462
|
+
// Wrap with layout BEFORE AccessGate — AccessGate is OUTSIDE the layout.
|
|
463
|
+
// When AccessGate denies, the layout never renders. The deny page appears
|
|
464
|
+
// at the AccessGate level, wrapped by PARENT layouts only.
|
|
465
|
+
// This prevents leaking layout UI (sidebars, nav) on denied pages.
|
|
466
|
+
// See design/04-authorization.md §"Access Failure".
|
|
398
467
|
if (layoutComponent) {
|
|
399
|
-
// Resolve parallel slots for this layout
|
|
468
|
+
// Resolve parallel slots for this layout.
|
|
469
|
+
// Compute the parent tree path so slots can build their full
|
|
470
|
+
// segment path for per-slot param storage in ALS.
|
|
471
|
+
const parentTreePath =
|
|
472
|
+
'/' +
|
|
473
|
+
segments
|
|
474
|
+
.slice(0, i + 1)
|
|
475
|
+
.map((s) => s.segmentName)
|
|
476
|
+
.filter(Boolean)
|
|
477
|
+
.join('/');
|
|
400
478
|
const slotProps: Record<string, unknown> = {};
|
|
401
479
|
const slotEntries = Object.entries(segment.slots ?? {});
|
|
402
480
|
for (const [slotName, slotNode] of slotEntries) {
|
|
403
481
|
slotProps[slotName] = await resolveSlotElement(
|
|
404
482
|
slotNode as ManifestSegmentNode,
|
|
405
483
|
match,
|
|
406
|
-
paramsPromise,
|
|
407
484
|
h,
|
|
408
|
-
interception
|
|
485
|
+
interception,
|
|
486
|
+
parentTreePath
|
|
409
487
|
);
|
|
410
488
|
}
|
|
411
489
|
|
|
412
490
|
const segmentPath = segment.urlPath.split('/');
|
|
413
491
|
const parallelRouteKeys = Object.keys(segment.slots ?? {});
|
|
414
492
|
|
|
415
|
-
//
|
|
416
|
-
//
|
|
417
|
-
//
|
|
418
|
-
// from the root "layout /".
|
|
419
|
-
const segmentForSpan = segment;
|
|
420
|
-
const layoutComponentForSpan = layoutComponent;
|
|
421
|
-
const segmentLabel =
|
|
422
|
-
segmentForSpan.segmentType === 'group'
|
|
423
|
-
? `${segmentForSpan.urlPath === '/' ? '' : segmentForSpan.urlPath}/${segmentForSpan.segmentName}`
|
|
424
|
-
: segmentForSpan.urlPath;
|
|
425
|
-
const TracedLayout = async (props: Record<string, unknown>) => {
|
|
426
|
-
return withSpan('timber.layout', { 'timber.segment': segmentLabel }, () =>
|
|
427
|
-
(layoutComponentForSpan as (props: Record<string, unknown>) => unknown)(props)
|
|
428
|
-
);
|
|
429
|
-
};
|
|
430
|
-
|
|
431
|
-
// segmentId uniquely identifies this segment for client-side element
|
|
432
|
-
// caching. For route groups, urlPath is shared with the parent (both "/"),
|
|
433
|
-
// so we include the group name to distinguish them. Without this, the
|
|
434
|
-
// segment merger's element cache would conflate root and group elements.
|
|
493
|
+
// For route groups, urlPath is shared with the parent (both "/"),
|
|
494
|
+
// so include the group name to distinguish them. Used for both OTEL
|
|
495
|
+
// span labels and client-side element caching (segmentId).
|
|
435
496
|
const segmentId =
|
|
436
497
|
segment.segmentType === 'group'
|
|
437
498
|
? `${segment.urlPath === '/' ? '' : segment.urlPath}/${segment.segmentName}`
|
|
438
499
|
: segment.urlPath;
|
|
439
500
|
|
|
501
|
+
// Build the layout element.
|
|
502
|
+
// Same client reference guard as pages — client layouts must not be
|
|
503
|
+
// called as functions. OTEL tracing is skipped for client components.
|
|
504
|
+
let layoutElement: React.ReactElement;
|
|
505
|
+
if (isClientReference(layoutComponent)) {
|
|
506
|
+
layoutElement = h(layoutComponent, {
|
|
507
|
+
...slotProps,
|
|
508
|
+
children: element,
|
|
509
|
+
});
|
|
510
|
+
} else {
|
|
511
|
+
// Server component layout — wrap with OTEL tracing AND DenySignal
|
|
512
|
+
// catching. If the layout calls deny(), the signal is caught here
|
|
513
|
+
// and the matching deny page renders in-tree (same pattern as
|
|
514
|
+
// AccessGate and PageDenyBoundary). Without this, DenySignal
|
|
515
|
+
// escapes to React Flight onError and triggers the re-render
|
|
516
|
+
// fallback path. See TIM-668, design/04-authorization.md.
|
|
517
|
+
const layoutComponentRef = layoutComponent;
|
|
518
|
+
const layoutDenyPages = denyPageChains.get(i);
|
|
519
|
+
const TracedLayout = async (props: Record<string, unknown>) => {
|
|
520
|
+
try {
|
|
521
|
+
return await withSpan('timber.layout', { 'timber.segment': segmentId }, () =>
|
|
522
|
+
(layoutComponentRef as (props: Record<string, unknown>) => unknown)(props)
|
|
523
|
+
);
|
|
524
|
+
} catch (error: unknown) {
|
|
525
|
+
if (error instanceof DenySignal && layoutDenyPages) {
|
|
526
|
+
const denyElement = renderMatchingDenyPage(layoutDenyPages, error.status, error.data);
|
|
527
|
+
if (denyElement) {
|
|
528
|
+
setDenyStatus(error.status);
|
|
529
|
+
return denyElement;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
// Non-deny errors (RedirectSignal, runtime errors) propagate normally.
|
|
533
|
+
throw error;
|
|
534
|
+
}
|
|
535
|
+
};
|
|
536
|
+
layoutElement = h(TracedLayout, {
|
|
537
|
+
...slotProps,
|
|
538
|
+
children: element,
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
|
|
440
542
|
element = h(SegmentProvider, {
|
|
441
543
|
segments: segmentPath,
|
|
442
544
|
segmentId,
|
|
443
545
|
parallelRouteKeys,
|
|
444
|
-
children:
|
|
445
|
-
...slotProps,
|
|
446
|
-
params: paramsPromise,
|
|
447
|
-
searchParams: {},
|
|
448
|
-
children: element,
|
|
449
|
-
}),
|
|
546
|
+
children: layoutElement,
|
|
450
547
|
});
|
|
451
548
|
}
|
|
549
|
+
|
|
550
|
+
// Wrap in AccessGate OUTSIDE the layout.
|
|
551
|
+
// If access denies, the deny page renders here — the layout above
|
|
552
|
+
// never executes. Parent layouts (from outer iterations) form the shell.
|
|
553
|
+
// See TIM-662, TIM-666, design/04-authorization.md §"Access Failure".
|
|
554
|
+
if (segment.access) {
|
|
555
|
+
const accessMod = await loadModule(segment.access);
|
|
556
|
+
const accessFn = accessMod.default as (() => unknown) | undefined;
|
|
557
|
+
if (accessFn) {
|
|
558
|
+
element = h(AccessGate, {
|
|
559
|
+
accessFn,
|
|
560
|
+
segmentName: segment.segmentName,
|
|
561
|
+
denyPages: denyPageChains.get(i),
|
|
562
|
+
children: element,
|
|
563
|
+
});
|
|
564
|
+
}
|
|
565
|
+
}
|
|
452
566
|
}
|
|
453
567
|
|
|
454
568
|
return {
|