@timber-js/app 0.2.0-alpha.6 → 0.2.0-alpha.61
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/LICENSE +8 -0
- package/dist/_chunks/{als-registry-B7DbZ2hS.js → als-registry-Ba7URUIn.js} +1 -1
- package/dist/_chunks/als-registry-Ba7URUIn.js.map +1 -0
- package/dist/_chunks/chunk-DYhsFzuS.js +33 -0
- package/dist/_chunks/{debug-gwlJkDuf.js → debug-ECi_61pb.js} +2 -2
- package/dist/_chunks/debug-ECi_61pb.js.map +1 -0
- package/dist/_chunks/define-CT98cU9c.js +121 -0
- package/dist/_chunks/define-CT98cU9c.js.map +1 -0
- package/dist/_chunks/define-TK8C1M3x.js +279 -0
- package/dist/_chunks/define-TK8C1M3x.js.map +1 -0
- package/dist/_chunks/define-cookie-BWr_52kY.js +93 -0
- package/dist/_chunks/define-cookie-BWr_52kY.js.map +1 -0
- package/dist/_chunks/error-boundary-DpZJBCqh.js +211 -0
- package/dist/_chunks/error-boundary-DpZJBCqh.js.map +1 -0
- package/dist/_chunks/{format-DviM89f0.js → format-cX7wzEp2.js} +2 -2
- package/dist/_chunks/{format-DviM89f0.js.map → format-cX7wzEp2.js.map} +1 -1
- package/dist/_chunks/{interception-BOoWmLUA.js → interception-Cey5DCGr.js} +129 -77
- package/dist/_chunks/interception-Cey5DCGr.js.map +1 -0
- package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js → metadata-routes-BU684ls2.js} +1 -1
- package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js.map → metadata-routes-BU684ls2.js.map} +1 -1
- package/dist/_chunks/{request-context-DIkVh_jG.js → request-context-rju2rbga.js} +97 -69
- package/dist/_chunks/request-context-rju2rbga.js.map +1 -0
- package/dist/_chunks/segment-context-CyaM1mrD.js +72 -0
- package/dist/_chunks/segment-context-CyaM1mrD.js.map +1 -0
- package/dist/_chunks/stale-reload-BSSym1MJ.js +64 -0
- package/dist/_chunks/stale-reload-BSSym1MJ.js.map +1 -0
- package/dist/_chunks/{tracing-Cwn7697K.js → tracing-VYETCQsg.js} +17 -3
- package/dist/_chunks/{tracing-Cwn7697K.js.map → tracing-VYETCQsg.js.map} +1 -1
- package/dist/_chunks/{use-query-states-D5KaffOK.js → use-query-states-wEXY2JQB.js} +1 -1
- package/dist/_chunks/use-query-states-wEXY2JQB.js.map +1 -0
- package/dist/_chunks/wrappers-BaG1bnM3.js +63 -0
- package/dist/_chunks/wrappers-BaG1bnM3.js.map +1 -0
- 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 +56 -13
- package/dist/adapters/nitro.js.map +1 -1
- package/dist/cache/fast-hash.d.ts +22 -0
- package/dist/cache/fast-hash.d.ts.map +1 -0
- package/dist/cache/index.d.ts +5 -2
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +90 -20
- package/dist/cache/index.js.map +1 -1
- package/dist/cache/register-cached-function.d.ts.map +1 -1
- package/dist/cache/singleflight.d.ts +18 -1
- package/dist/cache/singleflight.d.ts.map +1 -1
- package/dist/cache/timber-cache.d.ts +1 -1
- package/dist/cache/timber-cache.d.ts.map +1 -1
- package/dist/client/error-boundary.d.ts +10 -1
- package/dist/client/error-boundary.d.ts.map +1 -1
- package/dist/client/error-boundary.js +1 -125
- 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 +2 -2
- package/dist/client/form.d.ts.map +1 -1
- package/dist/client/index.d.ts +3 -2
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +433 -252
- package/dist/client/index.js.map +1 -1
- package/dist/client/link-pending-store.d.ts +78 -0
- package/dist/client/link-pending-store.d.ts.map +1 -0
- package/dist/client/link.d.ts +23 -9
- package/dist/client/link.d.ts.map +1 -1
- package/dist/client/navigation-context.d.ts +2 -2
- package/dist/client/navigation-context.d.ts.map +1 -1
- package/dist/client/router.d.ts +25 -3
- package/dist/client/router.d.ts.map +1 -1
- package/dist/client/rsc-fetch.d.ts +36 -2
- 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-context.d.ts +1 -1
- package/dist/client/segment-context.d.ts.map +1 -1
- package/dist/client/segment-merger.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/stale-reload.d.ts +15 -0
- package/dist/client/stale-reload.d.ts.map +1 -1
- package/dist/client/top-loader.d.ts +1 -1
- package/dist/client/top-loader.d.ts.map +1 -1
- package/dist/client/transition-root.d.ts +1 -1
- package/dist/client/transition-root.d.ts.map +1 -1
- package/dist/client/use-params.d.ts +3 -3
- package/dist/client/use-params.d.ts.map +1 -1
- package/dist/client/use-query-states.d.ts +1 -1
- package/dist/client/use-query-states.d.ts.map +1 -1
- package/dist/codec.d.ts +21 -0
- package/dist/codec.d.ts.map +1 -0
- package/dist/cookies/define-cookie.d.ts +34 -13
- package/dist/cookies/define-cookie.d.ts.map +1 -1
- package/dist/cookies/index.js +1 -83
- package/dist/fonts/css.d.ts +1 -0
- package/dist/fonts/css.d.ts.map +1 -1
- package/dist/index.d.ts +127 -35
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +665 -242
- package/dist/index.js.map +1 -1
- package/dist/params/define.d.ts +100 -0
- package/dist/params/define.d.ts.map +1 -0
- package/dist/params/index.d.ts +8 -0
- package/dist/params/index.d.ts.map +1 -0
- package/dist/params/index.js +4 -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 +3 -3
- 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-browser-logs.d.ts +84 -0
- package/dist/plugins/dev-browser-logs.d.ts.map +1 -0
- package/dist/plugins/dev-error-overlay.d.ts +26 -1
- package/dist/plugins/dev-error-overlay.d.ts.map +1 -1
- package/dist/plugins/dev-logs.d.ts +1 -1
- package/dist/plugins/dev-logs.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 +9 -2
- 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 +1 -1
- package/dist/plugins/static-build.d.ts.map +1 -1
- package/dist/routing/codegen.d.ts +2 -2
- package/dist/routing/codegen.d.ts.map +1 -1
- package/dist/routing/index.js +1 -1
- package/dist/routing/scanner.d.ts.map +1 -1
- package/dist/routing/status-file-lint.d.ts +2 -1
- package/dist/routing/status-file-lint.d.ts.map +1 -1
- package/dist/routing/types.d.ts +16 -4
- package/dist/routing/types.d.ts.map +1 -1
- 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/search-params/codecs.d.ts +1 -1
- package/dist/search-params/define.d.ts +159 -0
- package/dist/search-params/define.d.ts.map +1 -0
- package/dist/search-params/index.d.ts +4 -5
- package/dist/search-params/index.d.ts.map +1 -1
- package/dist/search-params/index.js +4 -474
- package/dist/search-params/registry.d.ts +1 -1
- package/dist/search-params/wrappers.d.ts +53 -0
- package/dist/search-params/wrappers.d.ts.map +1 -0
- package/dist/server/access-gate.d.ts +4 -0
- package/dist/server/access-gate.d.ts.map +1 -1
- 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.map +1 -1
- package/dist/server/actions.d.ts +1 -1
- package/dist/server/actions.d.ts.map +1 -1
- package/dist/server/als-registry.d.ts +25 -4
- package/dist/server/als-registry.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/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-renderer.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 +4 -0
- package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
- package/dist/server/fallback-error.d.ts +4 -3
- 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-injectors.d.ts +51 -11
- package/dist/server/html-injectors.d.ts.map +1 -1
- package/dist/server/index.d.ts +4 -2
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1977 -1648
- package/dist/server/index.js.map +1 -1
- package/dist/server/logger.d.ts +25 -7
- package/dist/server/logger.d.ts.map +1 -1
- package/dist/server/node-stream-transforms.d.ts +113 -0
- package/dist/server/node-stream-transforms.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.d.ts +20 -6
- package/dist/server/pipeline.d.ts.map +1 -1
- package/dist/server/primitives.d.ts +30 -3
- 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 +65 -38
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/route-element-builder.d.ts +7 -0
- 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 +9 -2
- package/dist/server/route-matcher.d.ts.map +1 -1
- 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 +48 -5
- package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
- package/dist/server/rsc-entry/index.d.ts +8 -3
- package/dist/server/rsc-entry/index.d.ts.map +1 -1
- 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 +10 -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/slot-resolver.d.ts +1 -1
- package/dist/server/slot-resolver.d.ts.map +1 -1
- package/dist/server/ssr-entry.d.ts +22 -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/status-code-resolver.d.ts +1 -1
- 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 +10 -0
- package/dist/server/tracing.d.ts.map +1 -1
- package/dist/server/tree-builder.d.ts +20 -13
- package/dist/server/tree-builder.d.ts.map +1 -1
- package/dist/server/types.d.ts +1 -3
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/version-skew.d.ts +61 -0
- package/dist/server/version-skew.d.ts.map +1 -0
- package/dist/server/waituntil-bridge.d.ts.map +1 -1
- 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/navigation-client.d.ts +1 -1
- package/dist/shims/navigation-client.d.ts.map +1 -1
- package/dist/shims/navigation.d.ts +1 -1
- 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 +17 -17
- package/src/adapters/compress-module.ts +24 -4
- package/src/adapters/nitro.ts +58 -9
- package/src/cache/fast-hash.ts +34 -0
- package/src/cache/index.ts +5 -2
- package/src/cache/register-cached-function.ts +7 -3
- package/src/cache/singleflight.ts +62 -4
- package/src/cache/timber-cache.ts +40 -29
- package/src/cli.ts +0 -0
- package/src/client/browser-entry.ts +151 -99
- package/src/client/error-boundary.tsx +18 -1
- package/src/client/error-reconstituter.tsx +65 -0
- package/src/client/form.tsx +2 -2
- package/src/client/index.ts +10 -1
- package/src/client/link-pending-store.ts +136 -0
- package/src/client/link.tsx +137 -22
- package/src/client/navigation-context.ts +6 -5
- package/src/client/router.ts +117 -60
- package/src/client/rsc-fetch.ts +90 -2
- package/src/client/segment-cache.ts +1 -1
- package/src/client/segment-context.ts +6 -1
- package/src/client/segment-merger.ts +2 -8
- package/src/client/segment-outlet.tsx +86 -0
- package/src/client/stale-reload.ts +73 -6
- package/src/client/top-loader.tsx +10 -9
- package/src/client/transition-root.tsx +20 -2
- package/src/client/use-params.ts +4 -4
- package/src/client/use-query-states.ts +2 -2
- package/src/codec.ts +21 -0
- package/src/cookies/define-cookie.ts +71 -20
- package/src/fonts/css.ts +2 -1
- package/src/index.ts +297 -85
- package/src/params/define.ts +327 -0
- package/src/params/index.ts +28 -0
- package/src/plugins/adapter-build.ts +8 -2
- package/src/plugins/build-manifest.ts +13 -2
- package/src/plugins/build-report.ts +3 -3
- package/src/plugins/cache-transform.ts +1 -1
- package/src/plugins/client-chunks.ts +65 -0
- package/src/plugins/content.ts +1 -1
- package/src/plugins/dev-browser-logs.ts +284 -0
- package/src/plugins/dev-error-overlay.ts +70 -1
- package/src/plugins/dev-logs.ts +1 -1
- package/src/plugins/dev-server.ts +41 -7
- package/src/plugins/entries.ts +6 -8
- package/src/plugins/fonts.ts +102 -55
- package/src/plugins/mdx.ts +1 -1
- package/src/plugins/routing.ts +57 -17
- package/src/plugins/server-action-exports.ts +1 -1
- package/src/plugins/server-bundle.ts +32 -1
- package/src/plugins/shims.ts +69 -31
- package/src/plugins/static-build.ts +10 -6
- package/src/routing/codegen.ts +109 -88
- package/src/routing/scanner.ts +86 -7
- package/src/routing/status-file-lint.ts +3 -2
- package/src/routing/types.ts +17 -4
- 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 +1 -1
- package/src/search-params/define.ts +518 -0
- package/src/search-params/index.ts +12 -18
- package/src/search-params/registry.ts +1 -1
- package/src/search-params/wrappers.ts +85 -0
- package/src/server/access-gate.tsx +40 -9
- package/src/server/action-client.ts +8 -2
- package/src/server/action-encryption.ts +144 -0
- package/src/server/action-handler.ts +20 -3
- package/src/server/actions.ts +1 -1
- package/src/server/als-registry.ts +25 -4
- package/src/server/build-manifest.ts +10 -4
- package/src/server/compress.ts +25 -7
- package/src/server/debug.ts +1 -1
- package/src/server/default-logger.ts +99 -0
- package/src/server/deny-renderer.ts +5 -3
- package/src/server/early-hints.ts +36 -15
- package/src/server/error-boundary-wrapper.ts +58 -15
- package/src/server/fallback-error.ts +29 -14
- 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-injectors.ts +277 -117
- package/src/server/index.ts +9 -4
- package/src/server/logger.ts +44 -36
- package/src/server/node-stream-transforms.ts +509 -0
- package/src/server/pipeline-interception.ts +1 -1
- package/src/server/pipeline.ts +148 -41
- package/src/server/primitives.ts +47 -5
- package/src/server/render-timeout.ts +108 -0
- package/src/server/request-context.ts +125 -119
- package/src/server/route-element-builder.ts +107 -115
- package/src/server/route-handler.ts +2 -1
- package/src/server/route-matcher.ts +9 -2
- package/src/server/rsc-entry/api-handler.ts +8 -8
- package/src/server/rsc-entry/error-renderer.ts +286 -81
- package/src/server/rsc-entry/helpers.ts +134 -5
- package/src/server/rsc-entry/index.ts +177 -76
- package/src/server/rsc-entry/rsc-payload.ts +91 -18
- package/src/server/rsc-entry/rsc-stream.ts +74 -18
- package/src/server/rsc-entry/ssr-bridge.ts +2 -2
- package/src/server/rsc-entry/ssr-renderer.ts +152 -34
- package/src/server/slot-resolver.ts +231 -220
- package/src/server/ssr-entry.ts +211 -32
- package/src/server/ssr-render.ts +289 -67
- package/src/server/ssr-wrappers.tsx +139 -0
- package/src/server/status-code-resolver.ts +1 -1
- package/src/server/stream-utils.ts +213 -0
- package/src/server/tracing.ts +23 -0
- package/src/server/tree-builder.ts +92 -58
- package/src/server/types.ts +1 -3
- package/src/server/version-skew.ts +104 -0
- package/src/server/waituntil-bridge.ts +4 -1
- package/src/shared/merge-search-params.ts +55 -0
- package/src/shims/font-google.ts +1 -1
- package/src/shims/navigation-client.ts +1 -1
- package/src/shims/navigation.ts +2 -1
- package/src/utils/state-machine.ts +111 -0
- package/dist/_chunks/als-registry-B7DbZ2hS.js.map +0 -1
- package/dist/_chunks/debug-gwlJkDuf.js.map +0 -1
- package/dist/_chunks/interception-BOoWmLUA.js.map +0 -1
- package/dist/_chunks/request-context-DIkVh_jG.js.map +0 -1
- package/dist/_chunks/ssr-data-MjmprTmO.js +0 -88
- package/dist/_chunks/ssr-data-MjmprTmO.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/client/error-boundary.js.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/cookies/index.js.map +0 -1
- package/dist/plugins/dynamic-transform.d.ts +0 -72
- package/dist/plugins/dynamic-transform.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/create.d.ts +0 -106
- package/dist/search-params/create.d.ts.map +0 -1
- package/dist/search-params/index.js.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 -53
- package/dist/server/response-cache.d.ts.map +0 -1
- package/src/client/link-status-provider.tsx +0 -30
- package/src/plugins/dynamic-transform.ts +0 -161
- 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/prerender.ts +0 -139
- package/src/server/response-cache.ts +0 -277
|
@@ -10,30 +10,46 @@
|
|
|
10
10
|
* 13-security.md §"Errors don't leak"
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import { renderToReadableStream } from '
|
|
13
|
+
import { renderToReadableStream } from '../../rsc-runtime/rsc.js';
|
|
14
14
|
|
|
15
|
-
import {
|
|
16
|
-
import { DenySignal, RedirectSignal, RenderError } from '#/server/primitives.js';
|
|
17
|
-
import { checkAndWarnRscPropError } from '#/server/rsc-prop-warnings.js';
|
|
15
|
+
import { randomUUID } from 'node:crypto';
|
|
18
16
|
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
17
|
+
import { logRenderError } from '../logger.js';
|
|
18
|
+
import { DenySignal, RedirectSignal, RenderError } from '../primitives.js';
|
|
19
|
+
import { checkAndWarnRscPropError } from '../rsc-prop-warnings.js';
|
|
20
|
+
|
|
21
|
+
import {
|
|
22
|
+
createDebugChannelSink,
|
|
23
|
+
createDebugChannelCollector,
|
|
24
|
+
isAbortError,
|
|
25
|
+
type DebugComponentEntry,
|
|
26
|
+
} from './helpers.js';
|
|
27
|
+
import { isDebug } from '../debug.js';
|
|
28
|
+
import { isDevMode } from '../debug.js';
|
|
21
29
|
|
|
22
30
|
/**
|
|
23
31
|
* Mutable signal state captured during RSC rendering.
|
|
24
32
|
*
|
|
25
33
|
* Signals fire asynchronously via `onError` during stream consumption.
|
|
26
34
|
* The first signal of each type wins — subsequent signals are ignored.
|
|
35
|
+
*
|
|
36
|
+
* `onSignal` is an optional callback fired when a DenySignal or
|
|
37
|
+
* RedirectSignal is captured. Consumers use it with Promise.race to
|
|
38
|
+
* react immediately instead of polling with setTimeout/queueMicrotask.
|
|
27
39
|
*/
|
|
28
40
|
export interface RenderSignals {
|
|
29
41
|
denySignal: DenySignal | null;
|
|
30
42
|
redirectSignal: RedirectSignal | null;
|
|
31
43
|
renderError: { error: unknown; status: number } | null;
|
|
44
|
+
/** Callback fired when a redirect or deny signal is captured in onError. */
|
|
45
|
+
onSignal?: () => void;
|
|
32
46
|
}
|
|
33
47
|
|
|
34
48
|
export interface RscStreamResult {
|
|
35
49
|
rscStream: ReadableStream<Uint8Array> | undefined;
|
|
36
50
|
signals: RenderSignals;
|
|
51
|
+
/** Dev-only: server component debug info from the Flight debug channel. */
|
|
52
|
+
getDebugComponents?: () => DebugComponentEntry[];
|
|
37
53
|
}
|
|
38
54
|
|
|
39
55
|
/**
|
|
@@ -56,6 +72,10 @@ export function renderRscStream(element: React.ReactElement, req: Request): RscS
|
|
|
56
72
|
|
|
57
73
|
let rscStream: ReadableStream<Uint8Array> | undefined;
|
|
58
74
|
|
|
75
|
+
// In dev mode, collect debug channel data for the error overlay.
|
|
76
|
+
// In production, use the discard sink (no overhead).
|
|
77
|
+
const debugChannel = isDevMode() ? createDebugChannelCollector() : createDebugChannelSink();
|
|
78
|
+
|
|
59
79
|
try {
|
|
60
80
|
rscStream = renderToReadableStream(
|
|
61
81
|
element,
|
|
@@ -67,11 +87,13 @@ export function renderRscStream(element: React.ReactElement, req: Request): RscS
|
|
|
67
87
|
if (isAbortError(error) || req.signal?.aborted) return;
|
|
68
88
|
if (error instanceof DenySignal) {
|
|
69
89
|
signals.denySignal = error;
|
|
90
|
+
signals.onSignal?.();
|
|
70
91
|
// Return structured digest for client-side error boundaries
|
|
71
92
|
return JSON.stringify({ type: 'deny', status: error.status, data: error.data });
|
|
72
93
|
}
|
|
73
94
|
if (error instanceof RedirectSignal) {
|
|
74
95
|
signals.redirectSignal = error;
|
|
96
|
+
signals.onSignal?.();
|
|
75
97
|
return JSON.stringify({
|
|
76
98
|
type: 'redirect',
|
|
77
99
|
location: error.location,
|
|
@@ -98,11 +120,7 @@ export function renderRscStream(element: React.ReactElement, req: Request): RscS
|
|
|
98
120
|
// directive isn't at the very top of the file, or the component is
|
|
99
121
|
// re-exported through a barrel file without 'use client'.
|
|
100
122
|
// See LOCAL-297.
|
|
101
|
-
if (
|
|
102
|
-
isDebug() &&
|
|
103
|
-
error instanceof Error &&
|
|
104
|
-
error.message.includes('Invalid hook call')
|
|
105
|
-
) {
|
|
123
|
+
if (isDebug() && error instanceof Error && error.message.includes('Invalid hook call')) {
|
|
106
124
|
console.error(
|
|
107
125
|
'[timber] A React hook was called during RSC rendering. This usually means a ' +
|
|
108
126
|
"'use client' component is being executed as a server component instead of " +
|
|
@@ -122,13 +140,42 @@ export function renderRscStream(element: React.ReactElement, req: Request): RscS
|
|
|
122
140
|
checkAndWarnRscPropError(error, new URL(req.url).pathname);
|
|
123
141
|
}
|
|
124
142
|
|
|
125
|
-
//
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
143
|
+
// Log the error but do NOT track it as a page-level render error.
|
|
144
|
+
// If this error is inside a <Suspense> boundary, React will emit
|
|
145
|
+
// an error row in the Flight stream and the Suspense fallback will
|
|
146
|
+
// render on the client. Tracking it as signals.renderError would
|
|
147
|
+
// cause the pipeline to treat the entire page as a 500, even though
|
|
148
|
+
// the shell rendered successfully. See TIM-524.
|
|
149
|
+
//
|
|
150
|
+
// Only track as renderError if no Suspense boundary contains it —
|
|
151
|
+
// React will call onShellError for truly unrecoverable errors.
|
|
152
|
+
|
|
153
|
+
// Return a digest so React emits a per-row error in the Flight
|
|
154
|
+
// stream instead of leaving the lazy reference unresolved.
|
|
155
|
+
//
|
|
156
|
+
// SECURITY: Never include error.message in the digest — it may
|
|
157
|
+
// contain SQL queries, filesystem paths, secret fragments, or
|
|
158
|
+
// internal IDs. Use a generic message with a correlation ID so
|
|
159
|
+
// the error can be matched to server logs.
|
|
160
|
+
// See design/13-security.md §"Errors don't leak".
|
|
161
|
+
const errorId = randomUUID();
|
|
162
|
+
logRenderError({
|
|
163
|
+
method: req.method,
|
|
164
|
+
path: new URL(req.url).pathname,
|
|
165
|
+
error,
|
|
166
|
+
errorId,
|
|
167
|
+
});
|
|
168
|
+
return JSON.stringify({
|
|
169
|
+
type: 'error',
|
|
170
|
+
message: isDevMode()
|
|
171
|
+
? error instanceof Error
|
|
172
|
+
? error.message
|
|
173
|
+
: String(error)
|
|
174
|
+
: 'An unexpected error occurred.',
|
|
175
|
+
errorId,
|
|
176
|
+
});
|
|
130
177
|
},
|
|
131
|
-
debugChannel
|
|
178
|
+
debugChannel,
|
|
132
179
|
},
|
|
133
180
|
{
|
|
134
181
|
onClientReference(info: { id: string; name: string; deps: unknown }) {
|
|
@@ -156,5 +203,14 @@ export function renderRscStream(element: React.ReactElement, req: Request): RscS
|
|
|
156
203
|
}
|
|
157
204
|
}
|
|
158
205
|
|
|
159
|
-
return {
|
|
206
|
+
return {
|
|
207
|
+
rscStream,
|
|
208
|
+
signals,
|
|
209
|
+
// Expose the debug channel collector's getComponents in dev mode.
|
|
210
|
+
// The caller can retrieve component tree info when handling errors.
|
|
211
|
+
getDebugComponents:
|
|
212
|
+
'getComponents' in debugChannel
|
|
213
|
+
? (debugChannel as { getComponents: () => DebugComponentEntry[] }).getComponents
|
|
214
|
+
: undefined,
|
|
215
|
+
};
|
|
160
216
|
}
|
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
/// <reference types="@vitejs/plugin-rsc/types" />
|
|
6
6
|
|
|
7
|
-
import type { NavContext } from '
|
|
7
|
+
import type { NavContext } from '../ssr-entry.js';
|
|
8
8
|
|
|
9
9
|
export async function callSsr(
|
|
10
10
|
rscStream: ReadableStream<Uint8Array>,
|
|
11
11
|
navContext: NavContext
|
|
12
12
|
): Promise<Response> {
|
|
13
|
-
const ssrEntry = await import.meta.viteRsc.import<typeof import('
|
|
13
|
+
const ssrEntry = await import.meta.viteRsc.import<typeof import('../ssr-entry.js')>(
|
|
14
14
|
'../ssr-entry.js',
|
|
15
15
|
{ environment: 'ssr' }
|
|
16
16
|
);
|
|
@@ -12,25 +12,48 @@
|
|
|
12
12
|
* 05-streaming.md §"deferSuspenseFor and the Hold Window"
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import type { ClientBootstrapConfig } from '
|
|
16
|
-
import
|
|
17
|
-
import {
|
|
18
|
-
import
|
|
19
|
-
import {
|
|
20
|
-
import
|
|
21
|
-
import type {
|
|
22
|
-
import type {
|
|
15
|
+
import type { ClientBootstrapConfig } from '../html-injectors.js';
|
|
16
|
+
import { flightInitScript } from '../flight-scripts.js';
|
|
17
|
+
import type { LayoutEntry } from '../deny-renderer.js';
|
|
18
|
+
import { renderDenyPage } from '../deny-renderer.js';
|
|
19
|
+
import type { RouteMatch } from '../pipeline.js';
|
|
20
|
+
import { SsrStreamError } from '../primitives.js';
|
|
21
|
+
import type { LayoutComponentEntry } from '../route-element-builder.js';
|
|
22
|
+
import type { ManifestSegmentNode } from '../route-matcher.js';
|
|
23
|
+
import type { NavContext } from '../ssr-entry.js';
|
|
23
24
|
|
|
24
25
|
import {
|
|
25
26
|
buildRedirectResponse,
|
|
26
27
|
buildSegmentInfo,
|
|
27
28
|
createDebugChannelSink,
|
|
28
29
|
isAbortError,
|
|
29
|
-
parseCookiesFromHeader,
|
|
30
30
|
} from './helpers.js';
|
|
31
|
-
import {
|
|
31
|
+
import { getCookiesForSsr } from '../request-context.js';
|
|
32
|
+
import { renderErrorPage, type GlobalErrorFile } from './error-renderer.js';
|
|
32
33
|
import { callSsr } from './ssr-bridge.js';
|
|
33
34
|
import type { RenderSignals } from './rsc-stream.js';
|
|
35
|
+
import { recordTiming } from '../server-timing.js';
|
|
36
|
+
import { teeWithErrorPropagation } from '../stream-utils.js';
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Maximum number of queueMicrotask yields during signal promotion.
|
|
40
|
+
* The known rejection chain depth for a withSpan-wrapped component is 3+
|
|
41
|
+
* microtasks. We use 5 to tolerate additional async wrappers or React
|
|
42
|
+
* Flight internals adding extra microtask hops. Do not increase beyond 8 —
|
|
43
|
+
* a deeper chain indicates a structural problem.
|
|
44
|
+
*/
|
|
45
|
+
const SIGNAL_PROMOTION_MAX_YIELDS = 5;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Test-only observable: records how many microtask yields were consumed
|
|
49
|
+
* during the last signal promotion check. Import this in tests to assert
|
|
50
|
+
* the actual rejection chain depth and detect regressions if wrappers
|
|
51
|
+
* add more async hops.
|
|
52
|
+
*
|
|
53
|
+
* Only populated when the object is imported and exists — production
|
|
54
|
+
* bundles that don't import it pay zero cost (the typeof check is free).
|
|
55
|
+
*/
|
|
56
|
+
export const __test_only_signalPromotionDepth: { value: number } = { value: 0 };
|
|
34
57
|
|
|
35
58
|
interface SsrRenderOptions {
|
|
36
59
|
req: Request;
|
|
@@ -44,6 +67,8 @@ interface SsrRenderOptions {
|
|
|
44
67
|
clientJsDisabled: boolean;
|
|
45
68
|
headHtml: string;
|
|
46
69
|
deferSuspenseFor: number;
|
|
70
|
+
/** Tier 2 global-error.tsx file, if present in app/. */
|
|
71
|
+
globalError?: GlobalErrorFile;
|
|
47
72
|
}
|
|
48
73
|
|
|
49
74
|
/**
|
|
@@ -77,11 +102,26 @@ export async function renderSsrResponse(opts: SsrRenderOptions): Promise<Respons
|
|
|
77
102
|
clientJsDisabled,
|
|
78
103
|
headHtml,
|
|
79
104
|
deferSuspenseFor,
|
|
105
|
+
globalError,
|
|
80
106
|
} = opts;
|
|
81
107
|
|
|
82
108
|
// Tee the RSC stream — one copy goes to SSR for HTML rendering,
|
|
83
109
|
// the other is inlined in the HTML for client-side hydration.
|
|
84
|
-
|
|
110
|
+
// Uses teeWithErrorPropagation to ensure errors on either branch
|
|
111
|
+
// cancel the other (preventing hung responses) and to monitor
|
|
112
|
+
// buffer divergence between SSR and inline consumers.
|
|
113
|
+
//
|
|
114
|
+
// When client JS is disabled, skip the tee — the inline stream would
|
|
115
|
+
// never be consumed, causing monotonic buffer divergence that eventually
|
|
116
|
+
// triggers the 5MB guard and cancels the SSR stream.
|
|
117
|
+
let ssrStream: ReadableStream<Uint8Array>;
|
|
118
|
+
let inlineStream: ReadableStream<Uint8Array> | undefined;
|
|
119
|
+
if (clientJsDisabled) {
|
|
120
|
+
ssrStream = rscStream;
|
|
121
|
+
inlineStream = undefined;
|
|
122
|
+
} else {
|
|
123
|
+
[ssrStream, inlineStream] = teeWithErrorPropagation(rscStream);
|
|
124
|
+
}
|
|
85
125
|
|
|
86
126
|
// Embed segment metadata in HTML for initial hydration.
|
|
87
127
|
// The client reads this to populate its segment cache before the
|
|
@@ -91,8 +131,8 @@ export async function renderSsrResponse(opts: SsrRenderOptions): Promise<Respons
|
|
|
91
131
|
? ''
|
|
92
132
|
: `<script>self.__timber_segments=${JSON.stringify(buildSegmentInfo(segments, layoutComponents))}</script>`;
|
|
93
133
|
|
|
94
|
-
// Embed route params in HTML so
|
|
95
|
-
// Without this,
|
|
134
|
+
// Embed route params in HTML so useSegmentParams() works on initial hydration.
|
|
135
|
+
// Without this, useSegmentParams() returns {} until the first client navigation.
|
|
96
136
|
const paramsScript =
|
|
97
137
|
clientJsDisabled || Object.keys(match.params).length === 0
|
|
98
138
|
? ''
|
|
@@ -104,13 +144,20 @@ export async function renderSsrResponse(opts: SsrRenderOptions): Promise<Respons
|
|
|
104
144
|
searchParams: Object.fromEntries(new URL(req.url).searchParams),
|
|
105
145
|
statusCode: 200,
|
|
106
146
|
responseHeaders,
|
|
107
|
-
headHtml:
|
|
147
|
+
headHtml:
|
|
148
|
+
headHtml +
|
|
149
|
+
clientBootstrap.preloadLinks +
|
|
150
|
+
segmentScript +
|
|
151
|
+
paramsScript +
|
|
152
|
+
// Initialize __timber_f in <head> so it exists before any streaming
|
|
153
|
+
// chunk scripts arrive in <body>. See flight-scripts.ts, LOCAL-415.
|
|
154
|
+
(clientJsDisabled ? '' : flightInitScript()),
|
|
108
155
|
bootstrapScriptContent: clientBootstrap.bootstrapScriptContent,
|
|
109
156
|
// Skip RSC inline stream when client JS is disabled — no client to hydrate.
|
|
110
157
|
rscStream: clientJsDisabled ? undefined : inlineStream,
|
|
111
158
|
deferSuspenseFor: deferSuspenseFor > 0 ? deferSuspenseFor : undefined,
|
|
112
159
|
signal: req.signal,
|
|
113
|
-
cookies:
|
|
160
|
+
cookies: getCookiesForSsr(),
|
|
114
161
|
};
|
|
115
162
|
|
|
116
163
|
// Helper: check if render-phase signals were captured and return the
|
|
@@ -147,7 +194,8 @@ export async function renderSsrResponse(opts: SsrRenderOptions): Promise<Respons
|
|
|
147
194
|
req,
|
|
148
195
|
match,
|
|
149
196
|
responseHeaders,
|
|
150
|
-
clientBootstrap
|
|
197
|
+
clientBootstrap,
|
|
198
|
+
globalError
|
|
151
199
|
);
|
|
152
200
|
}
|
|
153
201
|
return null;
|
|
@@ -156,16 +204,52 @@ export async function renderSsrResponse(opts: SsrRenderOptions): Promise<Respons
|
|
|
156
204
|
try {
|
|
157
205
|
const ssrResponse = await callSsr(ssrStream, navContext);
|
|
158
206
|
|
|
159
|
-
//
|
|
160
|
-
//
|
|
161
|
-
//
|
|
162
|
-
|
|
207
|
+
// Record SSR sub-phase timings for Server-Timing header (detailed mode).
|
|
208
|
+
// These are populated by handleSsr() in the SSR environment and passed
|
|
209
|
+
// back via navContext._ssrTimings across the RSC→SSR boundary.
|
|
210
|
+
if (navContext._ssrTimings) {
|
|
211
|
+
const t = navContext._ssrTimings;
|
|
212
|
+
recordTiming({ name: 'ssr-decode', dur: t.decodeMs, desc: 'RSC Flight decode' });
|
|
213
|
+
recordTiming({ name: 'ssr-shell', dur: t.shellMs, desc: 'Fizz onShellReady' });
|
|
214
|
+
recordTiming({ name: 'ssr-pipeline', dur: t.pipelineMs, desc: 'stream transforms' });
|
|
215
|
+
recordTiming({
|
|
216
|
+
name: 'ssr-total',
|
|
217
|
+
dur: t.totalMs,
|
|
218
|
+
desc: t.nodeStreams ? 'SSR (Node streams)' : 'SSR (Web Streams)',
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Signal promotion: check if any signals were captured during rendering
|
|
223
|
+
// inside Suspense boundaries. If no signals are present yet, yield
|
|
224
|
+
// multiple microtasks so async component rejections propagate through
|
|
225
|
+
// the full rejection chain to the RSC onError callback before we
|
|
226
|
+
// commit the response.
|
|
227
|
+
//
|
|
228
|
+
// The known rejection chain depth for a withSpan-wrapped page:
|
|
229
|
+
// 1. PageComponent throws DenySignal/RedirectSignal
|
|
230
|
+
// 2. withSpan catches and re-throws (microtask 1)
|
|
231
|
+
// 3. TracedPage promise rejects (microtask 2)
|
|
232
|
+
// 4. React Flight rejection handler → onError (microtask 3+)
|
|
233
|
+
//
|
|
234
|
+
// A single queueMicrotask only advances the queue by one step, which
|
|
235
|
+
// is insufficient for chains deeper than 1. We retry up to
|
|
236
|
+
// SIGNAL_PROMOTION_MAX_YIELDS (5) times, exiting early as soon as a
|
|
237
|
+
// signal is detected. This tolerates future wrappers adding depth
|
|
238
|
+
// without requiring code changes.
|
|
163
239
|
//
|
|
164
|
-
//
|
|
165
|
-
//
|
|
166
|
-
//
|
|
240
|
+
// When signals are already captured (onSignal already fired), skip the
|
|
241
|
+
// yield entirely — react immediately. Uses queueMicrotask instead of
|
|
242
|
+
// setTimeout(0) to avoid yielding to the full event loop (timers phase).
|
|
167
243
|
// See design/05-streaming.md §"deferSuspenseFor and the Hold Window"
|
|
168
|
-
|
|
244
|
+
if (!signals.redirectSignal && !signals.denySignal && !signals.renderError) {
|
|
245
|
+
let yieldsConsumed = 0;
|
|
246
|
+
for (let i = 0; i < SIGNAL_PROMOTION_MAX_YIELDS; i++) {
|
|
247
|
+
await new Promise<void>((r) => queueMicrotask(r));
|
|
248
|
+
yieldsConsumed++;
|
|
249
|
+
if (signals.redirectSignal || signals.denySignal || signals.renderError) break;
|
|
250
|
+
}
|
|
251
|
+
__test_only_signalPromotionDepth.value = yieldsConsumed;
|
|
252
|
+
}
|
|
169
253
|
|
|
170
254
|
const promoted = checkCapturedSignals(/* skipHandledDeny */ true);
|
|
171
255
|
if (promoted) {
|
|
@@ -182,19 +266,38 @@ export async function renderSsrResponse(opts: SsrRenderOptions): Promise<Respons
|
|
|
182
266
|
|
|
183
267
|
// SsrStreamError: SSR's renderToReadableStream failed because the RSC
|
|
184
268
|
// stream contained an uncontained error (e.g., slot without error boundary).
|
|
185
|
-
//
|
|
186
|
-
//
|
|
187
|
-
//
|
|
188
|
-
|
|
269
|
+
//
|
|
270
|
+
// Error pages now use SSR-only rendering (Fizz directly, no RSC Flight),
|
|
271
|
+
// which imports layouts in the SSR environment where ALS is active. This
|
|
272
|
+
// means we CAN include layouts — they'll call headers()/cookies() correctly.
|
|
273
|
+
//
|
|
274
|
+
// Deny pages still go through RSC → SSR (plain props), so they pass empty
|
|
275
|
+
// layouts to avoid re-executing server components in the RSC environment's
|
|
276
|
+
// stale ALS scope. See LOCAL-293.
|
|
277
|
+
// Name-based check: SsrStreamError is thrown in the SSR environment
|
|
278
|
+
// but caught in the RSC environment. Since RSC and SSR are separate
|
|
279
|
+
// Vite module graphs, `instanceof` fails (different class identities).
|
|
280
|
+
// Use error.name instead. See design/18-build-system.md §"Virtual Module
|
|
281
|
+
// Resolution Quirks".
|
|
282
|
+
const isSsrStreamError =
|
|
283
|
+
ssrError instanceof SsrStreamError ||
|
|
284
|
+
(ssrError instanceof Error && ssrError.name === 'SsrStreamError');
|
|
285
|
+
if (isSsrStreamError) {
|
|
189
286
|
if (signals.redirectSignal) {
|
|
190
287
|
return buildRedirectResponse(req, signals.redirectSignal, responseHeaders);
|
|
191
288
|
}
|
|
192
289
|
if (signals.denySignal) {
|
|
193
|
-
//
|
|
290
|
+
// Deny pages go through RSC → SSR with the full layout chain.
|
|
291
|
+
// We re-execute layout server components in a fresh RSC render,
|
|
292
|
+
// which is necessary so the deny page gets the HTML shell
|
|
293
|
+
// (<html>, <head>, <body>) and CSS from the root layout.
|
|
294
|
+
// Without layouts, deny pages render unstyled (no doctype, no
|
|
295
|
+
// stylesheets). ALS is still active for this request, so
|
|
296
|
+
// layouts calling headers()/cookies() work correctly.
|
|
194
297
|
return renderDenyPage(
|
|
195
298
|
signals.denySignal,
|
|
196
299
|
segments,
|
|
197
|
-
|
|
300
|
+
layoutComponents as LayoutEntry[],
|
|
198
301
|
req,
|
|
199
302
|
match,
|
|
200
303
|
responseHeaders,
|
|
@@ -204,19 +307,34 @@ export async function renderSsrResponse(opts: SsrRenderOptions): Promise<Respons
|
|
|
204
307
|
);
|
|
205
308
|
}
|
|
206
309
|
if (signals.renderError) {
|
|
310
|
+
// RenderError: TSX error pages use SSR-only path (layouts OK),
|
|
311
|
+
// MDX error pages use RSC path (plain props, no Error object).
|
|
207
312
|
return renderErrorPage(
|
|
208
313
|
signals.renderError.error,
|
|
209
314
|
signals.renderError.status,
|
|
210
315
|
segments,
|
|
211
|
-
|
|
316
|
+
layoutComponents as LayoutEntry[],
|
|
212
317
|
req,
|
|
213
318
|
match,
|
|
214
319
|
responseHeaders,
|
|
215
|
-
clientBootstrap
|
|
320
|
+
clientBootstrap,
|
|
321
|
+
globalError
|
|
216
322
|
);
|
|
217
323
|
}
|
|
218
|
-
// No captured signal —
|
|
219
|
-
|
|
324
|
+
// No captured signal — unhandled error in the RSC stream.
|
|
325
|
+
// Render the error page using the original error (cause).
|
|
326
|
+
const cause = (ssrError as { cause?: unknown }).cause ?? ssrError;
|
|
327
|
+
return renderErrorPage(
|
|
328
|
+
cause,
|
|
329
|
+
500,
|
|
330
|
+
segments,
|
|
331
|
+
layoutComponents as LayoutEntry[],
|
|
332
|
+
req,
|
|
333
|
+
match,
|
|
334
|
+
responseHeaders,
|
|
335
|
+
clientBootstrap,
|
|
336
|
+
globalError
|
|
337
|
+
);
|
|
220
338
|
}
|
|
221
339
|
|
|
222
340
|
// SSR shell rendering failed — the error was outside Suspense.
|