@timber-js/app 0.2.0-alpha.97 → 0.2.0-alpha.99
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-CQ8Z8VGL.js +1061 -0
- package/dist/_chunks/actions-CQ8Z8VGL.js.map +1 -0
- package/dist/_chunks/build-output-helper-DXnW0qjz.js +61 -0
- package/dist/_chunks/build-output-helper-DXnW0qjz.js.map +1 -0
- package/dist/_chunks/{define-Itxvcd7F.js → define-B-Q_UMOD.js} +19 -23
- package/dist/_chunks/define-B-Q_UMOD.js.map +1 -0
- package/dist/_chunks/{define-C77ScO0m.js → define-CfBPoJb0.js} +24 -7
- package/dist/_chunks/define-CfBPoJb0.js.map +1 -0
- package/dist/_chunks/define-cookie-BjpIt4UC.js +194 -0
- package/dist/_chunks/define-cookie-BjpIt4UC.js.map +1 -0
- package/dist/_chunks/{format-CYBGxKtc.js → format-Bcn-Iv1x.js} +1 -1
- package/dist/_chunks/{format-CYBGxKtc.js.map → format-Bcn-Iv1x.js.map} +1 -1
- package/dist/_chunks/handler-store-B-lqaGyh.js +54 -0
- package/dist/_chunks/handler-store-B-lqaGyh.js.map +1 -0
- package/dist/_chunks/logger-0m8MsKdc.js +291 -0
- package/dist/_chunks/logger-0m8MsKdc.js.map +1 -0
- package/dist/_chunks/merge-search-params-BphMdht_.js +122 -0
- package/dist/_chunks/merge-search-params-BphMdht_.js.map +1 -0
- package/dist/_chunks/{metadata-routes-DS3eKNmf.js → metadata-routes-BU684ls2.js} +1 -1
- package/dist/_chunks/{metadata-routes-DS3eKNmf.js.map → metadata-routes-BU684ls2.js.map} +1 -1
- package/dist/_chunks/navigation-root-BCYczjml.js +96 -0
- package/dist/_chunks/navigation-root-BCYczjml.js.map +1 -0
- package/dist/_chunks/registry-I2ss-lvy.js +20 -0
- package/dist/_chunks/registry-I2ss-lvy.js.map +1 -0
- package/dist/_chunks/router-ref-h3-UaCQv.js +28 -0
- package/dist/_chunks/router-ref-h3-UaCQv.js.map +1 -0
- package/dist/_chunks/{schema-bridge-C3xl_vfb.js → schema-bridge-Cxu4l-7p.js} +1 -1
- package/dist/_chunks/{schema-bridge-C3xl_vfb.js.map → schema-bridge-Cxu4l-7p.js.map} +1 -1
- package/dist/_chunks/segment-classify-BjfuctV2.js +137 -0
- package/dist/_chunks/segment-classify-BjfuctV2.js.map +1 -0
- package/dist/_chunks/{segment-context-fHFLF1PE.js → segment-context-Dx_OizxD.js} +1 -1
- package/dist/_chunks/{segment-context-fHFLF1PE.js.map → segment-context-Dx_OizxD.js.map} +1 -1
- package/dist/_chunks/{router-ref-C8OCm7g7.js → ssr-data-B4CdH7rE.js} +2 -26
- package/dist/_chunks/ssr-data-B4CdH7rE.js.map +1 -0
- package/dist/_chunks/{stale-reload-BX5gL1r-.js → stale-reload-Bab885FO.js} +1 -1
- package/dist/_chunks/{stale-reload-BX5gL1r-.js.map → stale-reload-Bab885FO.js.map} +1 -1
- package/dist/_chunks/tracing-C8V-YGsP.js +329 -0
- package/dist/_chunks/tracing-C8V-YGsP.js.map +1 -0
- package/dist/_chunks/{use-query-states-BiV5GJgm.js → use-query-states-B2XTqxDR.js} +3 -19
- package/dist/_chunks/use-query-states-B2XTqxDR.js.map +1 -0
- package/dist/_chunks/{use-params-IOPu7E8t.js → use-segment-params-BkpKAQ7D.js} +9 -95
- package/dist/_chunks/use-segment-params-BkpKAQ7D.js.map +1 -0
- package/dist/_chunks/{interception-BbqMCVXa.js → walkers-Tg0Alwcg.js} +66 -87
- package/dist/_chunks/walkers-Tg0Alwcg.js.map +1 -0
- package/dist/_chunks/{dev-warnings-DpGRGoDi.js → warnings-Cg47l5sk.js} +3 -3
- package/dist/_chunks/warnings-Cg47l5sk.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.d.ts.map +1 -1
- package/dist/adapters/cloudflare.js +8 -28
- package/dist/adapters/cloudflare.js.map +1 -1
- package/dist/adapters/nitro.d.ts.map +1 -1
- package/dist/adapters/nitro.js +63 -31
- 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/index.js +9 -2
- package/dist/cache/index.js.map +1 -1
- package/dist/cache/timber-cache.d.ts.map +1 -1
- package/dist/client/error-boundary.js +2 -1
- package/dist/client/error-boundary.js.map +1 -1
- package/dist/client/form.d.ts +10 -24
- package/dist/client/form.d.ts.map +1 -1
- package/dist/client/index.d.ts +1 -5
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +41 -91
- package/dist/client/index.js.map +1 -1
- package/dist/client/internal.d.ts +2 -1
- package/dist/client/internal.d.ts.map +1 -1
- package/dist/client/internal.js +81 -7
- package/dist/client/internal.js.map +1 -1
- package/dist/client/rsc-fetch.d.ts.map +1 -1
- package/dist/client/state.d.ts +1 -1
- package/dist/client/use-cookie.d.ts +8 -0
- package/dist/client/use-cookie.d.ts.map +1 -1
- package/dist/client/{use-params.d.ts → use-segment-params.d.ts} +1 -1
- package/dist/client/use-segment-params.d.ts.map +1 -0
- package/dist/codec.d.ts +1 -1
- package/dist/codec.d.ts.map +1 -1
- package/dist/codec.js +2 -2
- package/dist/config-types.d.ts +28 -0
- package/dist/config-types.d.ts.map +1 -1
- package/dist/cookies/define-cookie.d.ts +87 -35
- 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 +48 -2
- package/dist/cookies/index.js.map +1 -0
- 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/{plugins/dev-404-page.d.ts → dev-tools/404-page.d.ts} +9 -19
- package/dist/dev-tools/404-page.d.ts.map +1 -0
- package/dist/{plugins/dev-browser-logs.d.ts → dev-tools/browser-logs.d.ts} +1 -1
- package/dist/dev-tools/browser-logs.d.ts.map +1 -0
- package/dist/{plugins/dev-error-page.d.ts → dev-tools/error-page.d.ts} +2 -2
- package/dist/dev-tools/error-page.d.ts.map +1 -0
- package/dist/{server/dev-holding-server.d.ts → dev-tools/holding-server.d.ts} +5 -3
- 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} +1 -1
- package/dist/dev-tools/logs.d.ts.map +1 -0
- package/dist/{plugins/dev-error-overlay.d.ts → dev-tools/overlay.d.ts} +3 -12
- 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/{plugins/dev-terminal-error.d.ts → dev-tools/terminal.d.ts} +2 -2
- package/dist/dev-tools/terminal.d.ts.map +1 -0
- package/dist/{server/dev-warnings.d.ts → dev-tools/warnings.d.ts} +1 -1
- package/dist/dev-tools/warnings.d.ts.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +285 -133
- package/dist/index.js.map +1 -1
- package/dist/plugin-context.d.ts +1 -1
- package/dist/plugin-context.d.ts.map +1 -1
- package/dist/plugins/adapter-build.d.ts.map +1 -1
- package/dist/plugins/build-report.d.ts +6 -4
- package/dist/plugins/build-report.d.ts.map +1 -1
- package/dist/routing/convention-lint.d.ts.map +1 -1
- package/dist/routing/index.d.ts +5 -3
- package/dist/routing/index.d.ts.map +1 -1
- package/dist/routing/index.js +3 -3
- package/dist/routing/scanner.d.ts +1 -10
- package/dist/routing/scanner.d.ts.map +1 -1
- package/dist/routing/segment-classify.d.ts +37 -8
- package/dist/routing/segment-classify.d.ts.map +1 -1
- package/dist/routing/status-file-lint.d.ts.map +1 -1
- package/dist/routing/types.d.ts +63 -23
- 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/search-params/define.d.ts +25 -7
- package/dist/search-params/define.d.ts.map +1 -1
- package/dist/search-params/index.js +5 -3
- package/dist/search-params/index.js.map +1 -1
- package/dist/search-params/wrappers.d.ts +2 -2
- package/dist/search-params/wrappers.d.ts.map +1 -1
- package/dist/segment-params/define.d.ts +23 -6
- package/dist/segment-params/define.d.ts.map +1 -1
- package/dist/segment-params/index.js +1 -1
- package/dist/server/access-gate.d.ts +4 -3
- package/dist/server/access-gate.d.ts.map +1 -1
- package/dist/server/action-handler.d.ts +15 -6
- package/dist/server/action-handler.d.ts.map +1 -1
- package/dist/server/als-registry.d.ts +5 -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/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/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/early-hints-sender.d.ts.map +1 -1
- package/dist/server/html-injector-core.d.ts +212 -0
- package/dist/server/html-injector-core.d.ts.map +1 -0
- package/dist/server/html-injectors.d.ts +59 -59
- package/dist/server/html-injectors.d.ts.map +1 -1
- package/dist/server/index.d.ts +5 -4
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +4 -149
- package/dist/server/index.js.map +1 -1
- package/dist/server/internal.d.ts +6 -4
- package/dist/server/internal.d.ts.map +1 -1
- package/dist/server/internal.js +852 -852
- package/dist/server/internal.js.map +1 -1
- package/dist/server/logger.d.ts +14 -0
- package/dist/server/logger.d.ts.map +1 -1
- package/dist/server/middleware-runner.d.ts +17 -0
- package/dist/server/middleware-runner.d.ts.map +1 -1
- package/dist/server/node-stream-transforms.d.ts +46 -49
- package/dist/server/node-stream-transforms.d.ts.map +1 -1
- package/dist/server/param-coercion.d.ts +26 -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-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 +51 -32
- 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/request-context.d.ts +22 -159
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/route-element-builder.d.ts.map +1 -1
- package/dist/server/route-matcher.d.ts +20 -47
- 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/helpers.d.ts +1 -1
- package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
- 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/wrap-action-dispatch.d.ts +119 -0
- package/dist/server/rsc-entry/wrap-action-dispatch.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/tracing.d.ts +1 -1
- package/dist/server/tracing.d.ts.map +1 -1
- package/dist/server/tree-builder.d.ts +45 -16
- package/dist/server/tree-builder.d.ts.map +1 -1
- package/dist/server/types.d.ts +48 -0
- 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/shims/headers.d.ts +2 -2
- 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 +9 -4
- package/dist/shims/navigation.d.ts.map +1 -1
- package/dist/utils/directive-parser.d.ts +0 -45
- package/dist/utils/directive-parser.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/adapters/build-output-helper.ts +77 -0
- package/src/adapters/cloudflare.ts +10 -50
- package/src/adapters/nitro.ts +66 -50
- package/src/adapters/shared.ts +40 -0
- package/src/cache/timber-cache.ts +3 -2
- package/src/client/form.tsx +17 -25
- package/src/client/index.ts +16 -9
- package/src/client/internal.ts +3 -2
- package/src/client/router.ts +1 -1
- package/src/client/rsc-fetch.ts +15 -0
- package/src/client/state.ts +2 -2
- package/src/client/use-cookie.ts +29 -0
- package/src/codec.ts +3 -7
- package/src/config-types.ts +28 -0
- package/src/cookies/define-cookie.ts +271 -78
- package/src/cookies/index.ts +11 -8
- package/src/cookies/json-cookie.ts +105 -0
- package/src/cookies/validation.ts +134 -0
- package/src/{plugins/dev-404-page.ts → dev-tools/404-page.ts} +17 -48
- package/src/{plugins/dev-error-page.ts → dev-tools/error-page.ts} +5 -32
- package/src/{server/dev-holding-server.ts → dev-tools/holding-server.ts} +4 -2
- 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} +2 -2
- package/src/{plugins/dev-error-overlay.ts → dev-tools/overlay.ts} +5 -23
- package/src/dev-tools/stack-classifier.ts +75 -0
- package/src/{plugins/dev-terminal-error.ts → dev-tools/terminal.ts} +4 -38
- package/src/{server/dev-warnings.ts → dev-tools/warnings.ts} +1 -1
- package/src/index.ts +95 -34
- package/src/plugin-context.ts +1 -1
- package/src/plugins/adapter-build.ts +3 -1
- package/src/plugins/build-report.ts +13 -22
- package/src/plugins/dev-server.ts +3 -3
- package/src/plugins/routing.ts +14 -12
- package/src/plugins/shims.ts +1 -1
- package/src/plugins/static-build.ts +1 -1
- package/src/routing/codegen.ts +1 -1
- package/src/routing/convention-lint.ts +9 -8
- package/src/routing/index.ts +5 -3
- package/src/routing/interception.ts +1 -1
- package/src/routing/scanner.ts +22 -95
- package/src/routing/segment-classify.ts +107 -8
- package/src/routing/status-file-lint.ts +7 -5
- package/src/routing/types.ts +63 -23
- package/src/routing/walkers.ts +90 -0
- package/src/search-params/define.ts +71 -15
- package/src/search-params/wrappers.ts +9 -2
- package/src/segment-params/define.ts +66 -13
- package/src/server/access-gate.tsx +9 -8
- package/src/server/action-handler.ts +34 -38
- package/src/server/als-registry.ts +5 -5
- package/src/server/asset-headers.ts +8 -34
- package/src/server/cookie-context.ts +468 -0
- package/src/server/cookie-parsing.ts +135 -0
- package/src/server/{deny-page-resolver.ts → deny-boundary.ts} +78 -14
- package/src/server/deny-renderer.ts +7 -12
- package/src/server/early-hints-sender.ts +3 -2
- package/src/server/fallback-error.ts +2 -2
- package/src/server/html-injector-core.ts +403 -0
- package/src/server/html-injectors.ts +158 -297
- package/src/server/index.ts +13 -14
- package/src/server/internal.ts +10 -3
- package/src/server/logger.ts +23 -0
- package/src/server/middleware-runner.ts +44 -0
- package/src/server/node-stream-transforms.ts +108 -248
- package/src/server/param-coercion.ts +76 -0
- package/src/server/pipeline-helpers.ts +204 -0
- package/src/server/pipeline-outcome.ts +167 -0
- package/src/server/pipeline-phases.ts +409 -0
- package/src/server/pipeline.ts +70 -540
- package/src/server/port-resolution.ts +215 -0
- package/src/server/request-context.ts +46 -451
- package/src/server/route-element-builder.ts +8 -4
- package/src/server/route-matcher.ts +28 -60
- package/src/server/rsc-entry/action-middleware-runner.ts +167 -0
- package/src/server/rsc-entry/api-handler.ts +2 -2
- package/src/server/rsc-entry/error-renderer.ts +2 -2
- package/src/server/rsc-entry/helpers.ts +2 -7
- package/src/server/rsc-entry/index.ts +81 -366
- package/src/server/rsc-entry/render-route.ts +304 -0
- package/src/server/rsc-entry/rsc-payload.ts +1 -1
- package/src/server/rsc-entry/ssr-renderer.ts +2 -2
- package/src/server/rsc-entry/wrap-action-dispatch.ts +449 -0
- package/src/server/sitemap-generator.ts +1 -1
- package/src/server/slot-resolver.ts +1 -1
- package/src/server/ssr-entry.ts +1 -1
- package/src/server/state-tree-diff.ts +4 -1
- package/src/server/status-code-resolver.ts +112 -128
- package/src/server/tracing.ts +3 -3
- package/src/server/tree-builder.ts +134 -56
- package/src/server/types.ts +52 -0
- package/src/server/utils/escape-html.ts +20 -0
- package/src/shims/headers.ts +3 -3
- package/src/shims/navigation-client.ts +4 -3
- package/src/shims/navigation.ts +9 -7
- package/src/utils/directive-parser.ts +0 -392
- package/dist/_chunks/actions-DLnUaR65.js +0 -421
- package/dist/_chunks/actions-DLnUaR65.js.map +0 -1
- package/dist/_chunks/als-registry-HS0LGUl2.js +0 -41
- package/dist/_chunks/als-registry-HS0LGUl2.js.map +0 -1
- package/dist/_chunks/debug-ECi_61pb.js +0 -108
- package/dist/_chunks/debug-ECi_61pb.js.map +0 -1
- package/dist/_chunks/define-C77ScO0m.js.map +0 -1
- package/dist/_chunks/define-Itxvcd7F.js.map +0 -1
- package/dist/_chunks/define-cookie-BowvzoP0.js +0 -94
- package/dist/_chunks/define-cookie-BowvzoP0.js.map +0 -1
- package/dist/_chunks/dev-warnings-DpGRGoDi.js.map +0 -1
- package/dist/_chunks/interception-BbqMCVXa.js.map +0 -1
- package/dist/_chunks/merge-search-params-Cm_KIWDX.js +0 -41
- package/dist/_chunks/merge-search-params-Cm_KIWDX.js.map +0 -1
- package/dist/_chunks/request-context-CK5tZqIP.js +0 -478
- package/dist/_chunks/request-context-CK5tZqIP.js.map +0 -1
- package/dist/_chunks/router-ref-C8OCm7g7.js.map +0 -1
- package/dist/_chunks/segment-classify-BDNn6EzD.js +0 -65
- package/dist/_chunks/segment-classify-BDNn6EzD.js.map +0 -1
- package/dist/_chunks/tracing-CCYbKn5n.js +0 -238
- package/dist/_chunks/tracing-CCYbKn5n.js.map +0 -1
- package/dist/_chunks/use-params-IOPu7E8t.js.map +0 -1
- package/dist/_chunks/use-query-states-BiV5GJgm.js.map +0 -1
- package/dist/client/use-params.d.ts.map +0 -1
- package/dist/plugins/dev-404-page.d.ts.map +0 -1
- package/dist/plugins/dev-browser-logs.d.ts.map +0 -1
- package/dist/plugins/dev-error-overlay.d.ts.map +0 -1
- package/dist/plugins/dev-error-page.d.ts.map +0 -1
- package/dist/plugins/dev-logs.d.ts.map +0 -1
- package/dist/plugins/dev-terminal-error.d.ts.map +0 -1
- package/dist/server/deny-page-resolver.d.ts +0 -52
- package/dist/server/deny-page-resolver.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-holding-server.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/page-deny-boundary.d.ts +0 -31
- package/dist/server/page-deny-boundary.d.ts.map +0 -1
- 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/page-deny-boundary.tsx +0 -56
- /package/src/client/{use-params.ts → use-segment-params.ts} +0 -0
- /package/src/{plugins/dev-browser-logs.ts → dev-tools/browser-logs.ts} +0 -0
- /package/src/{server/dev-logger.ts → dev-tools/logger.ts} +0 -0
|
@@ -31,28 +31,20 @@ import loadUserInstrumentation from 'virtual:timber-instrumentation';
|
|
|
31
31
|
// @ts-expect-error — virtual module provided by timber-entries plugin
|
|
32
32
|
import loadCacheHandler from 'virtual:timber-cache-handler';
|
|
33
33
|
|
|
34
|
-
import
|
|
35
|
-
import { handleActionRequest, isActionRequest } from '../action-handler.js';
|
|
34
|
+
import { wrapPipelineWithActionDispatch } from './wrap-action-dispatch.js';
|
|
36
35
|
import type { BodyLimitsConfig } from '../body-limits.js';
|
|
37
36
|
import type { BuildManifest } from '../build-manifest.js';
|
|
38
|
-
import {
|
|
39
|
-
buildFontPreloadTags,
|
|
40
|
-
buildModulepreloadTags,
|
|
41
|
-
collectRouteFonts,
|
|
42
|
-
collectRouteModulepreloads,
|
|
43
|
-
} from '../build-manifest.js';
|
|
44
37
|
import type { LayoutEntry } from '../deny-renderer.js';
|
|
45
38
|
import { renderDenyPage, renderDenyPageAsRsc } from '../deny-renderer.js';
|
|
46
|
-
import { resolveLogMode } from '
|
|
39
|
+
import { resolveLogMode } from '../../dev-tools/logger.js';
|
|
47
40
|
import { sendEarlyHints103 } from '../early-hints-sender.js';
|
|
48
41
|
import { collectEarlyHintHeaders } from '../early-hints.js';
|
|
49
|
-
import { runWithFormFlash } from '../form-flash.js';
|
|
50
|
-
import type { ClientBootstrapConfig } from '../html-injectors.js';
|
|
51
42
|
import { buildClientScripts } from '../html-injectors.js';
|
|
52
43
|
import type { InterceptionContext, PipelineConfig, RouteMatch } from '../pipeline.js';
|
|
53
|
-
import { createPipeline
|
|
44
|
+
import { createPipeline } from '../pipeline.js';
|
|
45
|
+
import { coerceSegmentParams } from '../param-coercion.js';
|
|
54
46
|
import { setSegmentParams } from '../request-context.js';
|
|
55
|
-
import { buildRouteElement
|
|
47
|
+
import { buildRouteElement } from '../route-element-builder.js';
|
|
56
48
|
import type { ManifestSegmentNode } from '../route-matcher.js';
|
|
57
49
|
import { createMetadataRouteMatcher, createRouteMatcher } from '../route-matcher.js';
|
|
58
50
|
import { initDevTracing } from '../tracing.js';
|
|
@@ -61,23 +53,16 @@ import { renderFallbackError as renderFallback } from '../fallback-error.js';
|
|
|
61
53
|
import { loadInstrumentation } from '../instrumentation.js';
|
|
62
54
|
import { loadModule } from '../safe-load.js';
|
|
63
55
|
import { logRenderError } from '../logger.js';
|
|
64
|
-
import {
|
|
65
|
-
import { renderErrorPage, renderNoMatchPage } from './error-renderer.js';
|
|
56
|
+
import { renderNoMatchPage } from './error-renderer.js';
|
|
66
57
|
import {
|
|
67
|
-
buildRedirectResponse,
|
|
68
58
|
createDebugChannelSink,
|
|
69
|
-
escapeHtml,
|
|
70
59
|
isRscPayloadRequest,
|
|
71
60
|
type DebugComponentEntry,
|
|
72
61
|
} from './helpers.js';
|
|
73
|
-
import {
|
|
74
|
-
import { buildRscPayloadResponse } from './rsc-payload.js';
|
|
75
|
-
import { renderRscStream } from './rsc-stream.js';
|
|
76
|
-
import { renderSsrResponse } from './ssr-renderer.js';
|
|
62
|
+
import { renderRoute } from './render-route.js';
|
|
77
63
|
import { callSsr } from './ssr-bridge.js';
|
|
78
64
|
import { isDebug, isDevMode, setDebugFromConfig } from '../debug.js';
|
|
79
65
|
import { setSourceMapCallback } from '../dev-source-map.js';
|
|
80
|
-
import { recordTiming } from '../server-timing.js';
|
|
81
66
|
import { requestContextAls } from '../als-registry.js';
|
|
82
67
|
import { createAutoSitemapHandler } from '../sitemap-handler.js';
|
|
83
68
|
|
|
@@ -232,15 +217,22 @@ async function createRequestHandler(manifest: typeof routeManifest, runtimeConfi
|
|
|
232
217
|
await initDevTracing({ mode: devLogMode, slowPhaseMs });
|
|
233
218
|
// Patch globalThis.fetch to create OTEL spans for fetch calls.
|
|
234
219
|
// Spans appear as children of the active component span in the dev log tree.
|
|
235
|
-
const { instrumentDevFetch } = await import('
|
|
220
|
+
const { instrumentDevFetch } = await import('../../dev-tools/instrumentation.js');
|
|
236
221
|
instrumentDevFetch();
|
|
237
222
|
}
|
|
238
223
|
}
|
|
239
224
|
|
|
240
225
|
const typedBuildManifest = buildManifest as BuildManifest;
|
|
241
226
|
|
|
227
|
+
// The routing plugin emits `manifest.proxy = { load, filePath }` only when
|
|
228
|
+
// the app has an `app/proxy.ts`. Convert that to the pipeline's lazy variant
|
|
229
|
+
// so HMR re-imports per request; leave it undefined when there's no proxy.
|
|
230
|
+
const proxyConfig: PipelineConfig['proxy'] = manifest.proxy?.load
|
|
231
|
+
? { kind: 'lazy', loader: manifest.proxy.load }
|
|
232
|
+
: undefined;
|
|
233
|
+
|
|
242
234
|
const pipelineConfig: PipelineConfig = {
|
|
243
|
-
|
|
235
|
+
proxy: proxyConfig,
|
|
244
236
|
matchRoute,
|
|
245
237
|
matchMetadataRoute,
|
|
246
238
|
// 103 Early Hints — fires after route match, before middleware.
|
|
@@ -248,11 +240,7 @@ async function createRequestHandler(manifest: typeof routeManifest, runtimeConfi
|
|
|
248
240
|
// so the browser starts fetching critical resources while the server renders.
|
|
249
241
|
// In dev mode the manifest is empty — no hints are sent.
|
|
250
242
|
earlyHints: (match: RouteMatch, _req: Request, responseHeaders: Headers) => {
|
|
251
|
-
const
|
|
252
|
-
layout?: { filePath: string };
|
|
253
|
-
page?: { filePath: string };
|
|
254
|
-
}>;
|
|
255
|
-
const headers = collectEarlyHintHeaders(segments, typedBuildManifest, {
|
|
243
|
+
const headers = collectEarlyHintHeaders(match.segments, typedBuildManifest, {
|
|
256
244
|
skipJs: clientJsDisabled,
|
|
257
245
|
});
|
|
258
246
|
for (const h of headers) {
|
|
@@ -273,11 +261,14 @@ async function createRequestHandler(manifest: typeof routeManifest, runtimeConfi
|
|
|
273
261
|
req,
|
|
274
262
|
match,
|
|
275
263
|
responseHeaders,
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
264
|
+
{
|
|
265
|
+
clientBootstrap,
|
|
266
|
+
clientJsDisabled,
|
|
267
|
+
rootSegment: manifest.root,
|
|
268
|
+
buildManifest: typedBuildManifest,
|
|
269
|
+
globalError: manifest.globalError,
|
|
270
|
+
},
|
|
271
|
+
interception
|
|
281
272
|
);
|
|
282
273
|
},
|
|
283
274
|
renderNoMatch: async (req: Request, responseHeaders: Headers) => {
|
|
@@ -295,7 +286,7 @@ async function createRequestHandler(manifest: typeof routeManifest, runtimeConfi
|
|
|
295
286
|
// should receive the bare 404 without an HTML body (TIM-793).
|
|
296
287
|
const acceptsHtml = (req.headers.get('accept') ?? '').includes('text/html');
|
|
297
288
|
if (isDev && !response.body && req.method === 'GET' && acceptsHtml) {
|
|
298
|
-
const { generateDev404Page, collectRoutes } = await import('../../
|
|
289
|
+
const { generateDev404Page, collectRoutes } = await import('../../dev-tools/404-page.js');
|
|
299
290
|
const routes = collectRoutes(manifest.root);
|
|
300
291
|
const pathname = new URL(req.url).pathname;
|
|
301
292
|
const html = generateDev404Page(pathname, routes);
|
|
@@ -358,10 +349,7 @@ async function createRequestHandler(manifest: typeof routeManifest, runtimeConfi
|
|
|
358
349
|
// route's `401.json` are picked up. Fall back to the root chain when no
|
|
359
350
|
// match is available (e.g. proxy-stage deny before route matching).
|
|
360
351
|
// See TIM-822, design/04-authorization.md, design/10-error-handling.md.
|
|
361
|
-
|
|
362
|
-
const chain = matchedRoute
|
|
363
|
-
? (matchedRoute.segments as unknown as SegNode[])
|
|
364
|
-
: ([manifest.root] as unknown as SegNode[]);
|
|
352
|
+
const chain: ManifestSegmentNode[] = matchedRoute ? matchedRoute.segments : [manifest.root];
|
|
365
353
|
const layoutComponents: LayoutEntry[] = [];
|
|
366
354
|
try {
|
|
367
355
|
for (const segment of chain) {
|
|
@@ -382,8 +370,8 @@ async function createRequestHandler(manifest: typeof routeManifest, runtimeConfi
|
|
|
382
370
|
// Reuse the matched route's params/middleware metadata when present so
|
|
383
371
|
// downstream rendering sees the real route shape. Otherwise synthesise
|
|
384
372
|
// a root-only stub (no params, no middleware).
|
|
385
|
-
const match = matchedRoute ?? {
|
|
386
|
-
segments: chain
|
|
373
|
+
const match: RouteMatch = matchedRoute ?? {
|
|
374
|
+
segments: chain,
|
|
387
375
|
segmentParams: {},
|
|
388
376
|
middlewareChain: [],
|
|
389
377
|
};
|
|
@@ -421,9 +409,15 @@ async function createRequestHandler(manifest: typeof routeManifest, runtimeConfi
|
|
|
421
409
|
|
|
422
410
|
const pipeline = createPipeline(pipelineConfig);
|
|
423
411
|
|
|
424
|
-
// Wrap the pipeline to
|
|
425
|
-
//
|
|
426
|
-
//
|
|
412
|
+
// Wrap the pipeline to enforce CSRF at the request boundary and intercept
|
|
413
|
+
// server action requests. By default, the wrapper also runs the matched
|
|
414
|
+
// route's `middleware.ts` chain on action POSTs, so authentication, rate
|
|
415
|
+
// limiting, tenant isolation, and request-header injection apply to
|
|
416
|
+
// actions just like they do to page renders. See TIM-871 and
|
|
417
|
+
// design/08-forms-and-actions.md §"Middleware for Server Actions".
|
|
418
|
+
//
|
|
419
|
+
// CSRF validation lives in the wrapper (not inside the action handler) so
|
|
420
|
+
// it covers route.ts API handlers as well as server actions. See LOCAL-773.
|
|
427
421
|
const csrfConfig = {
|
|
428
422
|
csrf: runtimeConfig.csrf,
|
|
429
423
|
allowedOrigins: (runtimeConfig as Record<string, unknown>).allowedOrigins as
|
|
@@ -431,330 +425,51 @@ async function createRequestHandler(manifest: typeof routeManifest, runtimeConfi
|
|
|
431
425
|
| undefined,
|
|
432
426
|
};
|
|
433
427
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
// the revalidation render (AccessGate reads params via ALS).
|
|
461
|
-
// Without this, AccessGate → getSegmentParams() throws because
|
|
462
|
-
// segmentParamsPromise is never set. See TIM-667.
|
|
463
|
-
setSegmentParams(revalidateMatch.segmentParams);
|
|
464
|
-
const routeResult = await buildRouteElement(revalidateReq, revalidateMatch);
|
|
465
|
-
return {
|
|
466
|
-
element: routeResult.element,
|
|
467
|
-
headElements: routeResult.headElements,
|
|
468
|
-
};
|
|
469
|
-
},
|
|
428
|
+
const actionsConfig = (runtimeConfig as Record<string, unknown>).actions as
|
|
429
|
+
| { runMiddleware?: boolean }
|
|
430
|
+
| undefined;
|
|
431
|
+
|
|
432
|
+
return wrapPipelineWithActionDispatch(pipeline, {
|
|
433
|
+
csrfConfig,
|
|
434
|
+
bodyLimits: (runtimeConfig as Record<string, unknown>).limits as BodyLimitsConfig['limits'],
|
|
435
|
+
sensitiveFields: formsConfig?.stripSensitiveFields,
|
|
436
|
+
matchRoute,
|
|
437
|
+
coerceSegmentParams,
|
|
438
|
+
renderDenyFallback: pipelineConfig.renderDenyFallback,
|
|
439
|
+
runMiddleware: actionsConfig?.runMiddleware,
|
|
440
|
+
// Thread the pipeline's `stripTrailingSlash` setting into the wrapper
|
|
441
|
+
// so its canonicalization step (applied before `matchRoute` for
|
|
442
|
+
// action POSTs) matches the page pipeline exactly. Defaults to `true`
|
|
443
|
+
// both here and inside the wrapper.
|
|
444
|
+
stripTrailingSlash: pipelineConfig.stripTrailingSlash,
|
|
445
|
+
buildRevalidateRenderer: (req) => async (path: string) => {
|
|
446
|
+
// Build the React element tree for the route at `path`.
|
|
447
|
+
// Returns the element tree (not serialized) so the action handler can
|
|
448
|
+
// combine it with the action result in a single renderToReadableStream call.
|
|
449
|
+
// Forward original request headers (cookies, session IDs, etc.).
|
|
450
|
+
const revalidateHeaders = new Headers(req.headers);
|
|
451
|
+
revalidateHeaders.set('Accept', 'text/x-component');
|
|
452
|
+
const revalidateReq = new Request(new URL(path, req.url), {
|
|
453
|
+
headers: revalidateHeaders,
|
|
470
454
|
});
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
const formRerender = actionResponse as FormRerender;
|
|
475
|
-
// Re-render the page with the action result as flash data.
|
|
476
|
-
// Server components read it via getFormFlash() and pass it to
|
|
477
|
-
// client form components as the initial useActionState value.
|
|
478
|
-
//
|
|
479
|
-
// Build a synthetic GET request for the rerender pipeline:
|
|
480
|
-
// - Same URL (so route matching lands on the same page)
|
|
481
|
-
// - Cookie header replaced with the post-action RYW snapshot
|
|
482
|
-
// so server components see the action's writes (TIM-837)
|
|
483
|
-
// - Method GET because the rerender is conceptually a page
|
|
484
|
-
// render, not a re-POST. The pipeline doesn't branch on
|
|
485
|
-
// method for page rendering, and constructing a POST without
|
|
486
|
-
// a body is awkward across Request implementations.
|
|
487
|
-
const rerenderHeaders = new Headers(req.headers);
|
|
488
|
-
if (formRerender.cookieHeader) {
|
|
489
|
-
rerenderHeaders.set('cookie', formRerender.cookieHeader);
|
|
490
|
-
} else {
|
|
491
|
-
rerenderHeaders.delete('cookie');
|
|
492
|
-
}
|
|
493
|
-
const rerenderReq = new Request(req.url, {
|
|
494
|
-
method: 'GET',
|
|
495
|
-
headers: rerenderHeaders,
|
|
496
|
-
});
|
|
497
|
-
const response = await runWithFormFlash(formRerender.rerender, () =>
|
|
498
|
-
pipeline(rerenderReq)
|
|
499
|
-
);
|
|
500
|
-
// Apply Set-Cookie headers snapshotted from the action's ALS scope.
|
|
501
|
-
// The pipeline above runs in its own request context with a fresh
|
|
502
|
-
// cookie jar, so cookies set inside the action would otherwise be
|
|
503
|
-
// silently dropped on the no-JS rerender path. See TIM-836
|
|
504
|
-
// (LOCAL-740).
|
|
505
|
-
for (const value of formRerender.setCookieHeaders) {
|
|
506
|
-
response.headers.append('Set-Cookie', value);
|
|
507
|
-
}
|
|
508
|
-
return response;
|
|
509
|
-
}
|
|
510
|
-
return actionResponse;
|
|
455
|
+
const revalidateMatch = matchRoute(new URL(revalidateReq.url).pathname);
|
|
456
|
+
if (!revalidateMatch) {
|
|
457
|
+
throw new Error(`revalidatePath('${path}') — no matching route`);
|
|
511
458
|
}
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
*/
|
|
527
|
-
async function renderRoute(
|
|
528
|
-
_req: Request,
|
|
529
|
-
match: RouteMatch,
|
|
530
|
-
responseHeaders: Headers,
|
|
531
|
-
clientBootstrap: ClientBootstrapConfig,
|
|
532
|
-
clientJsDisabled: boolean,
|
|
533
|
-
interception?: InterceptionContext,
|
|
534
|
-
rootSegment?: ManifestSegmentNode,
|
|
535
|
-
globalError?: { load: () => Promise<unknown>; filePath: string }
|
|
536
|
-
): Promise<Response> {
|
|
537
|
-
const segments = match.segments as unknown as ManifestSegmentNode[];
|
|
538
|
-
const leaf = segments[segments.length - 1];
|
|
539
|
-
|
|
540
|
-
// API routes (route.ts) — run access.ts standalone then dispatch to handler.
|
|
541
|
-
// No React render pass — AccessGate is not used, React.cache is not active.
|
|
542
|
-
// See design/04-authorization.md §"Auth in API Routes".
|
|
543
|
-
if (leaf.route && !leaf.page) {
|
|
544
|
-
return handleApiRoute(_req, match, segments, responseHeaders);
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
// Parse X-Timber-State-Tree for RSC payload requests (client navigation).
|
|
548
|
-
// The state tree lists sync segments the client has cached — the server
|
|
549
|
-
// skips re-rendering those layouts for a smaller, faster RSC payload.
|
|
550
|
-
// Only used for RSC requests — HTML requests always get a full render.
|
|
551
|
-
// See design/19-client-navigation.md §"X-Timber-State-Tree Header"
|
|
552
|
-
const clientStateTree = isRscPayloadRequest(_req) ? parseClientStateTree(_req) : null;
|
|
553
|
-
|
|
554
|
-
// Build the React element tree — loads modules, collects access checks,
|
|
555
|
-
// resolves metadata. Access checks are NOT run here — they run inside
|
|
556
|
-
// AccessPreRunner during renderToReadableStream so that access.ts and
|
|
557
|
-
// render components share the same React.cache scope (TIM-662).
|
|
558
|
-
//
|
|
559
|
-
// DenySignal/RedirectSignal from access checks are caught by onError
|
|
560
|
-
// during stream consumption and handled by renderSsrResponse /
|
|
561
|
-
// buildRscPayloadResponse.
|
|
562
|
-
let routeResult;
|
|
563
|
-
const _buildStart = performance.now();
|
|
564
|
-
try {
|
|
565
|
-
routeResult = await buildRouteElement(_req, match, interception, clientStateTree);
|
|
566
|
-
} catch (error) {
|
|
567
|
-
// Param coercion failed — render the custom 404 page (status files / not-found).
|
|
568
|
-
// Previously returned a bare Response(null, { status: 404 }) which bypassed
|
|
569
|
-
// custom not-found pages. Now routes through renderNoMatchPage so apps with
|
|
570
|
-
// 404.tsx / not-found status files render their custom page.
|
|
571
|
-
if (error instanceof ParamCoercionError) {
|
|
572
|
-
return renderNoMatchPage(_req, rootSegment!, responseHeaders, clientBootstrap);
|
|
573
|
-
}
|
|
574
|
-
// No PageComponent found — same treatment as param coercion: render custom 404.
|
|
575
|
-
if (error instanceof Error && error.message.startsWith('No page component')) {
|
|
576
|
-
return renderNoMatchPage(_req, rootSegment!, responseHeaders, clientBootstrap);
|
|
577
|
-
}
|
|
578
|
-
throw error;
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
const _buildEnd = performance.now();
|
|
582
|
-
recordTiming({
|
|
583
|
-
name: 'build',
|
|
584
|
-
dur: Math.round(_buildEnd - _buildStart),
|
|
585
|
-
desc: 'build element tree',
|
|
586
|
-
});
|
|
587
|
-
|
|
588
|
-
const { element, headElements, layoutComponents, deferSuspenseFor, skippedSegments } =
|
|
589
|
-
routeResult;
|
|
590
|
-
|
|
591
|
-
// Build head HTML for injection into the SSR output.
|
|
592
|
-
// Collects CSS, fonts, and modulepreload from the build manifest for matched segments.
|
|
593
|
-
// In dev mode the manifest is empty — Vite HMR handles CSS/JS.
|
|
594
|
-
//
|
|
595
|
-
// Link headers (for 103 Early Hints) are emitted by the earlyHints pipeline
|
|
596
|
-
// stage before middleware runs. Here we only emit the <head> HTML fallback tags
|
|
597
|
-
// — these ensure resources load even on platforms without Early Hints support.
|
|
598
|
-
const typedManifest = buildManifest as BuildManifest;
|
|
599
|
-
let headHtml = '';
|
|
600
|
-
|
|
601
|
-
// CSS is handled by the RSC plugin via ReactDOM.preinit() with
|
|
602
|
-
// data-precedence attributes. This injects <link rel="stylesheet">
|
|
603
|
-
// tags during the RSC render phase — before our headHtml injection.
|
|
604
|
-
// We do NOT emit additional <link rel="stylesheet"> tags here because:
|
|
605
|
-
// 1. React's Float system deduplicates them, making ours redundant
|
|
606
|
-
// 2. The duplicate reference confuses React's client-side preload
|
|
607
|
-
// deduplication, causing "preload ignored" browser warnings
|
|
608
|
-
//
|
|
609
|
-
// CSS URLs are still collected for Early Hints (Link headers) in
|
|
610
|
-
// buildEarlyHintsHeaders() — those are HTTP headers, not DOM elements,
|
|
611
|
-
// so they don't conflict with Float.
|
|
612
|
-
|
|
613
|
-
// Font CSS is NOT inlined here anymore (TIM-828). The transform hook
|
|
614
|
-
// injects a side-effect `import 'virtual:timber-font-css/<hash>.css'`
|
|
615
|
-
// into each file that calls a font function. @vitejs/plugin-rsc's
|
|
616
|
-
// `collectCss` walks the RSC module graph, finds the virtual CSS
|
|
617
|
-
// module, and React Float `preinit()`s it as
|
|
618
|
-
// `<link rel="stylesheet" data-rsc-css-href=...>` — the same path
|
|
619
|
-
// component CSS rides on. Dev and production share a single path,
|
|
620
|
-
// with no `globalThis` channel and no dev/prod skew.
|
|
621
|
-
//
|
|
622
|
-
// Font preload hints (distinct from the @font-face CSS) still flow
|
|
623
|
-
// through `BuildManifest.fonts[importer]` and are emitted below plus
|
|
624
|
-
// as 103 Early Hints via `buildEarlyHintsHeaders()`.
|
|
625
|
-
const fontEntries = collectRouteFonts(segments, typedManifest);
|
|
626
|
-
if (fontEntries.length > 0) {
|
|
627
|
-
headHtml += buildFontPreloadTags(fontEntries);
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
// Skip modulepreload tags when client JavaScript is disabled — no JS to preload.
|
|
631
|
-
if (!clientJsDisabled) {
|
|
632
|
-
const preloadUrls = collectRouteModulepreloads(segments, typedManifest);
|
|
633
|
-
if (preloadUrls.length > 0) {
|
|
634
|
-
headHtml += buildModulepreloadTags(preloadUrls);
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
for (const el of headElements) {
|
|
639
|
-
if (el.tag === 'title' && el.content) {
|
|
640
|
-
headHtml += `<title>${escapeHtml(el.content)}</title>`;
|
|
641
|
-
} else if (el.attrs) {
|
|
642
|
-
const attrs = Object.entries(el.attrs)
|
|
643
|
-
.filter(([, v]) => v != null)
|
|
644
|
-
.map(([k, v]) => `${k}="${escapeHtml(v as string)}"`)
|
|
645
|
-
.join(' ');
|
|
646
|
-
headHtml += `<${el.tag} ${attrs}>`;
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
// In dev mode, inject the browser log forwarding script so console
|
|
651
|
-
// errors/warnings from the browser appear in the server terminal.
|
|
652
|
-
// Set by timber-dev-browser-logs plugin via globalThis (TIM-575).
|
|
653
|
-
if (isDevMode()) {
|
|
654
|
-
const devLogScript = (globalThis as Record<string, unknown>).__timber_dev_browser_log_script as
|
|
655
|
-
| string
|
|
656
|
-
| undefined;
|
|
657
|
-
if (devLogScript) {
|
|
658
|
-
headHtml += devLogScript;
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
// Render to RSC Flight stream with signal tracking.
|
|
663
|
-
const _rscStart = performance.now();
|
|
664
|
-
const { rscStream, signals, getDebugComponents } = renderRscStream(element, _req);
|
|
665
|
-
|
|
666
|
-
// Store the debug components getter in ALS so onPipelineError can
|
|
667
|
-
// include component tree context for render-phase errors (dev mode only).
|
|
668
|
-
// Per-request via ALS — no cross-request race. See TIM-557.
|
|
669
|
-
const alsStore = requestContextAls.getStore();
|
|
670
|
-
if (alsStore) {
|
|
671
|
-
alsStore.debugComponentsGetter = getDebugComponents;
|
|
672
|
-
}
|
|
673
|
-
recordTiming({
|
|
674
|
-
name: 'rsc-init',
|
|
675
|
-
dur: Math.round(performance.now() - _rscStart),
|
|
676
|
-
desc: 'RSC stream init',
|
|
677
|
-
});
|
|
678
|
-
|
|
679
|
-
// Synchronous redirect — redirect() in access.ts or a non-async component
|
|
680
|
-
// throws during renderToReadableStream creation. Return HTTP redirect.
|
|
681
|
-
if (signals.redirectSignal) {
|
|
682
|
-
return buildRedirectResponse(_req, signals.redirectSignal, responseHeaders);
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
// Synchronous deny — deny() in a non-async component throws during
|
|
686
|
-
// renderToReadableStream creation, caught in the try/catch above.
|
|
687
|
-
if (signals.denySignal) {
|
|
688
|
-
if (isRscPayloadRequest(_req)) {
|
|
689
|
-
return renderDenyPageAsRsc(
|
|
690
|
-
signals.denySignal,
|
|
691
|
-
segments,
|
|
692
|
-
layoutComponents as LayoutEntry[],
|
|
693
|
-
responseHeaders,
|
|
694
|
-
createDebugChannelSink
|
|
695
|
-
);
|
|
696
|
-
}
|
|
697
|
-
return renderDenyPage(
|
|
698
|
-
signals.denySignal,
|
|
699
|
-
segments,
|
|
700
|
-
layoutComponents as LayoutEntry[],
|
|
701
|
-
_req,
|
|
702
|
-
match,
|
|
703
|
-
responseHeaders,
|
|
704
|
-
clientBootstrap,
|
|
705
|
-
createDebugChannelSink,
|
|
706
|
-
callSsr
|
|
707
|
-
);
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
// Synchronous render error — renderToReadableStream threw before
|
|
711
|
-
// creating the stream. Render the error page with correct 5xx status.
|
|
712
|
-
// (Async render errors are tracked in onError and handled after SSR.)
|
|
713
|
-
if (signals.renderError && !rscStream) {
|
|
714
|
-
return renderErrorPage(
|
|
715
|
-
signals.renderError.error,
|
|
716
|
-
signals.renderError.status,
|
|
717
|
-
segments,
|
|
718
|
-
layoutComponents as LayoutEntry[],
|
|
719
|
-
_req,
|
|
720
|
-
match,
|
|
721
|
-
responseHeaders,
|
|
722
|
-
clientBootstrap,
|
|
723
|
-
globalError
|
|
724
|
-
);
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
// For RSC payload requests (client navigation), return the RSC Flight
|
|
728
|
-
// stream directly — skip SSR HTML rendering entirely.
|
|
729
|
-
// See design/19-client-navigation.md §"RSC Payload Handling"
|
|
730
|
-
if (isRscPayloadRequest(_req)) {
|
|
731
|
-
return buildRscPayloadResponse(
|
|
732
|
-
_req,
|
|
733
|
-
rscStream!,
|
|
734
|
-
signals,
|
|
735
|
-
segments,
|
|
736
|
-
layoutComponents,
|
|
737
|
-
headElements,
|
|
738
|
-
match,
|
|
739
|
-
responseHeaders,
|
|
740
|
-
skippedSegments
|
|
741
|
-
);
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
// Pipe through SSR for HTML rendering with streaming Suspense support.
|
|
745
|
-
return renderSsrResponse({
|
|
746
|
-
req: _req,
|
|
747
|
-
rscStream: rscStream!,
|
|
748
|
-
signals,
|
|
749
|
-
segments,
|
|
750
|
-
layoutComponents,
|
|
751
|
-
match,
|
|
752
|
-
responseHeaders,
|
|
753
|
-
clientBootstrap,
|
|
754
|
-
clientJsDisabled,
|
|
755
|
-
headHtml,
|
|
756
|
-
deferSuspenseFor,
|
|
757
|
-
globalError,
|
|
459
|
+
// Coerce segment params (params.ts) before building the element tree.
|
|
460
|
+
// Without this, components receive raw strings instead of typed values.
|
|
461
|
+
await coerceSegmentParams(revalidateMatch);
|
|
462
|
+
// Set coerced params in ALS so getSegmentParams() works during the
|
|
463
|
+
// revalidation render (AccessGate reads params via ALS). Without this,
|
|
464
|
+
// AccessGate → getSegmentParams() throws because segmentParams
|
|
465
|
+
// is never set. See TIM-667.
|
|
466
|
+
setSegmentParams(revalidateMatch.segmentParams);
|
|
467
|
+
const routeResult = await buildRouteElement(revalidateReq, revalidateMatch);
|
|
468
|
+
return {
|
|
469
|
+
element: routeResult.element,
|
|
470
|
+
headElements: routeResult.headElements,
|
|
471
|
+
};
|
|
472
|
+
},
|
|
758
473
|
});
|
|
759
474
|
}
|
|
760
475
|
|