@timber-js/app 0.2.0-alpha.208 → 0.2.0-alpha.209
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/{primitives-DLAnvsrk.js → actions-BerlqoXA.js} +640 -410
- package/dist/_chunks/actions-BerlqoXA.js.map +1 -0
- package/dist/_chunks/{als-registry-C6kcfprT.js → als-registry-DaxkVjt5.js} +6 -2
- package/dist/_chunks/als-registry-DaxkVjt5.js.map +1 -0
- package/dist/_chunks/{build-manifest-DTmSGLRz.js → build-manifest-DWppEdLB.js} +2 -51
- package/dist/_chunks/build-manifest-DWppEdLB.js.map +1 -0
- package/dist/_chunks/{build-output-helper-9dqCv1pZ.js → build-output-helper-RV_BRcF1.js} +50 -53
- package/dist/_chunks/build-output-helper-RV_BRcF1.js.map +1 -0
- package/dist/_chunks/{cache-api-CUD9Ezaq.js → cache-api-CR23J_NC.js} +64 -32
- package/dist/_chunks/cache-api-CR23J_NC.js.map +1 -0
- package/dist/_chunks/{chains-B4bgOl2g.js → chains-CpFg56UB.js} +2 -2
- package/dist/_chunks/{chains-B4bgOl2g.js.map → chains-CpFg56UB.js.map} +1 -1
- package/dist/_chunks/{cli-check-G8o30ldg.js → cli-check-C6Ev6wBO.js} +11 -52
- package/dist/_chunks/cli-check-C6Ev6wBO.js.map +1 -0
- package/dist/_chunks/cli-context-By7k2xVo.js +70 -0
- package/dist/_chunks/cli-context-By7k2xVo.js.map +1 -0
- package/dist/_chunks/{cli-schema-sync--LZKs8Zn.js → cli-schema-sync-CbT2AUUI.js} +3 -3
- package/dist/_chunks/{cli-schema-sync--LZKs8Zn.js.map → cli-schema-sync-CbT2AUUI.js.map} +1 -1
- package/dist/_chunks/{cloudflare-BFb__LYG.js → cloudflare-Byxl8FWP.js} +96 -53
- package/dist/_chunks/{cloudflare-BFb__LYG.js.map → cloudflare-Byxl8FWP.js.map} +1 -1
- package/dist/_chunks/{convention-lint-5KzoMg_A.js → convention-lint-jKTwKwPe.js} +21 -6
- package/dist/_chunks/convention-lint-jKTwKwPe.js.map +1 -0
- package/dist/_chunks/{dev-server-BzBxgYAV.js → dev-server-C4WZdB7L.js} +15 -167
- package/dist/_chunks/dev-server-C4WZdB7L.js.map +1 -0
- package/dist/_chunks/{error-boundary-BrHmG-2X.js → error-boundary-tA7kVfs4.js} +84 -104
- package/dist/_chunks/error-boundary-tA7kVfs4.js.map +1 -0
- package/dist/_chunks/{fs-identity-D7vb6GdI.js → fs-identity-BRKuL215.js} +3 -4
- package/dist/_chunks/fs-identity-BRKuL215.js.map +1 -0
- package/dist/_chunks/{graph-cache-CP4GEmf9.js → graph-cache-CYiUS2aS.js} +4 -5
- package/dist/_chunks/graph-cache-CYiUS2aS.js.map +1 -0
- package/dist/_chunks/{json-lossy-check-ClNvBM_3.js → json-lossy-check-ip0Qi0MT.js} +6 -3
- package/dist/_chunks/json-lossy-check-ip0Qi0MT.js.map +1 -0
- package/dist/_chunks/{live-graph-Bm5WTvcr.js → live-graph-Dv-JJCZw.js} +3 -3
- package/dist/_chunks/{live-graph-Bm5WTvcr.js.map → live-graph-Dv-JJCZw.js.map} +1 -1
- package/dist/_chunks/{logger-k2DQ4EUf.js → logger-DiDt5ppH.js} +192 -51
- package/dist/_chunks/logger-DiDt5ppH.js.map +1 -0
- package/dist/_chunks/{navigation-root-mHSK9psY.js → navigation-root-BQfo1-kG.js} +2 -2
- package/dist/_chunks/{navigation-root-mHSK9psY.js.map → navigation-root-BQfo1-kG.js.map} +1 -1
- package/dist/_chunks/{plugin-context-8idfR3UZ.js → plugin-context-BPBPc3lL.js} +28 -4
- package/dist/_chunks/plugin-context-BPBPc3lL.js.map +1 -0
- package/dist/_chunks/{poison-scan-DG5eI2_z.js → poison-scan-CpeT6_OJ.js} +2 -2
- package/dist/_chunks/{poison-scan-DG5eI2_z.js.map → poison-scan-CpeT6_OJ.js.map} +1 -1
- package/dist/_chunks/render-timeout-DOf_BBcO.js +46 -0
- package/dist/_chunks/render-timeout-DOf_BBcO.js.map +1 -0
- package/dist/_chunks/{rsc-payload-path-B_LBodc2.js → rsc-payload-path-dffcs4jp.js} +9 -3
- package/dist/_chunks/{rsc-payload-path-B_LBodc2.js.map → rsc-payload-path-dffcs4jp.js.map} +1 -1
- package/dist/_chunks/{scanner-BQ5sPIJ7.js → scanner-Bw0oq1HB.js} +2 -2
- package/dist/_chunks/{scanner-BQ5sPIJ7.js.map → scanner-Bw0oq1HB.js.map} +1 -1
- package/dist/_chunks/{navigation-context-D0TU0Jog.js → segment-context-xtPUGfdq.js} +36 -34
- package/dist/_chunks/segment-context-xtPUGfdq.js.map +1 -0
- package/dist/_chunks/{singleflight-2lUWfcAk.js → singleflight-BeVMMKi0.js} +4 -3
- package/dist/_chunks/{singleflight-2lUWfcAk.js.map → singleflight-BeVMMKi0.js.map} +1 -1
- package/dist/_chunks/{sizeof-lXffQ1Vr.js → sizeof-UwzwB1uM.js} +3 -2
- package/dist/_chunks/sizeof-UwzwB1uM.js.map +1 -0
- package/dist/_chunks/ssr-data-nA3I70_n.js +49 -0
- package/dist/_chunks/ssr-data-nA3I70_n.js.map +1 -0
- package/dist/_chunks/{state-FippDgxN.js → state-BhNGPsdi.js} +6 -8
- package/dist/_chunks/state-BhNGPsdi.js.map +1 -0
- package/dist/_chunks/{status-page-marker-CNbpUOPB.js → status-page-marker-gaihi0KZ.js} +53 -20
- package/dist/_chunks/status-page-marker-gaihi0KZ.js.map +1 -0
- package/dist/_chunks/{walkers-CN2N_bA-.js → walkers-BXExhzzk.js} +2 -2
- package/dist/_chunks/{walkers-CN2N_bA-.js.map → walkers-BXExhzzk.js.map} +1 -1
- package/dist/_chunks/write-file-atomic-D1qWqHb4.js +32 -0
- package/dist/_chunks/write-file-atomic-D1qWqHb4.js.map +1 -0
- package/dist/adapters/build-output-helper.d.ts +7 -7
- package/dist/adapters/build-output-helper.d.ts.map +1 -1
- package/dist/adapters/canonicalize-module.d.ts +8 -0
- package/dist/adapters/canonicalize-module.d.ts.map +1 -0
- package/dist/adapters/cloudflare-dev.js +1 -1
- package/dist/adapters/cloudflare-kv-cache.js +2 -2
- package/dist/adapters/cloudflare.d.ts +30 -8
- package/dist/adapters/cloudflare.d.ts.map +1 -1
- package/dist/adapters/cloudflare.js +2 -2
- package/dist/adapters/compress-module.d.ts +8 -0
- package/dist/adapters/compress-module.d.ts.map +1 -1
- package/dist/adapters/fs-identity.d.ts +2 -3
- package/dist/adapters/fs-identity.d.ts.map +1 -1
- package/dist/adapters/nitro-presets.d.ts +0 -6
- package/dist/adapters/nitro-presets.d.ts.map +1 -1
- package/dist/adapters/nitro-preview.d.ts +43 -11
- package/dist/adapters/nitro-preview.d.ts.map +1 -1
- package/dist/adapters/nitro.d.ts +1 -13
- package/dist/adapters/nitro.d.ts.map +1 -1
- package/dist/adapters/nitro.js +291 -176
- package/dist/adapters/nitro.js.map +1 -1
- package/dist/adapters/shared.d.ts +7 -2
- package/dist/adapters/shared.d.ts.map +1 -1
- package/dist/adapters/types.d.ts +105 -21
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/adapters/types.js +0 -0
- package/dist/analyze/crawl-entry.js +3 -3
- package/dist/analyze/graph-cache.d.ts.map +1 -1
- package/dist/analyze/graph-command.js +4 -4
- package/dist/cache/index.js +2 -2
- package/dist/cache/json-lossy-check.d.ts.map +1 -1
- package/dist/cache/singleflight.d.ts.map +1 -1
- package/dist/cache/sizeof.d.ts.map +1 -1
- package/dist/cache/stores/memory.js +1 -1
- package/dist/cache/tag-aware-handler.d.ts.map +1 -1
- package/dist/cdn/workers-cache-purge.js +1 -1
- package/dist/cli-check.d.ts +7 -37
- package/dist/cli-check.d.ts.map +1 -1
- package/dist/cli-context.d.ts +54 -0
- package/dist/cli-context.d.ts.map +1 -0
- package/dist/cli.d.ts +9 -9
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +20 -24
- package/dist/cli.js.map +1 -1
- package/dist/client/browser-dev.d.ts +1 -1
- package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -1
- package/dist/client/browser-entry/hydrate.d.ts +19 -29
- package/dist/client/browser-entry/hydrate.d.ts.map +1 -1
- package/dist/client/browser-entry/index.d.ts +7 -7
- package/dist/client/browser-entry/post-hydration.d.ts +6 -9
- package/dist/client/browser-entry/post-hydration.d.ts.map +1 -1
- package/dist/client/browser-entry/router-init.d.ts +6 -11
- package/dist/client/browser-entry/router-init.d.ts.map +1 -1
- package/dist/client/error-boundary.d.ts +4 -3
- package/dist/client/error-boundary.d.ts.map +1 -1
- package/dist/client/error-boundary.js +1 -1
- package/dist/client/error-reconstituter.d.ts +3 -9
- package/dist/client/error-reconstituter.d.ts.map +1 -1
- package/dist/client/history.d.ts +12 -11
- package/dist/client/history.d.ts.map +1 -1
- package/dist/client/index.d.ts +0 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +5 -6
- package/dist/client/index.js.map +1 -1
- package/dist/client/internal.d.ts +3 -3
- package/dist/client/internal.d.ts.map +1 -1
- package/dist/client/internal.js +68 -104
- package/dist/client/internal.js.map +1 -1
- package/dist/client/navigation-commit.d.ts +16 -7
- package/dist/client/navigation-commit.d.ts.map +1 -1
- package/dist/client/navigation-context.d.ts +3 -5
- package/dist/client/navigation-context.d.ts.map +1 -1
- package/dist/client/react-root.d.ts +3 -2
- package/dist/client/react-root.d.ts.map +1 -1
- package/dist/client/router-pipeline.d.ts +1 -6
- package/dist/client/router-pipeline.d.ts.map +1 -1
- package/dist/client/router-types.d.ts +45 -39
- package/dist/client/router-types.d.ts.map +1 -1
- package/dist/client/router-url.d.ts +24 -0
- package/dist/client/router-url.d.ts.map +1 -0
- package/dist/client/router.d.ts.map +1 -1
- package/dist/client/rsc-fetch.d.ts +8 -4
- package/dist/client/rsc-fetch.d.ts.map +1 -1
- package/dist/client/ssr-data.d.ts +18 -64
- package/dist/client/ssr-data.d.ts.map +1 -1
- package/dist/client/state.d.ts +2 -5
- package/dist/client/state.d.ts.map +1 -1
- package/dist/client/use-pathname.d.ts +1 -1
- package/dist/config-types.d.ts +2 -1
- package/dist/config-types.d.ts.map +1 -1
- package/dist/config-validation.d.ts.map +1 -1
- package/dist/cookies/index.js +1 -1
- package/dist/dev-tools/dev-page-shell.d.ts +17 -0
- package/dist/dev-tools/dev-page-shell.d.ts.map +1 -1
- package/dist/dev-tools/index.d.ts +1 -1
- package/dist/dev-tools/index.d.ts.map +1 -1
- package/dist/dev-tools/instrumentation.d.ts +17 -2
- package/dist/dev-tools/instrumentation.d.ts.map +1 -1
- package/dist/dev-tools/overlay.d.ts +6 -27
- package/dist/dev-tools/overlay.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +531 -373
- package/dist/index.js.map +1 -1
- package/dist/plugin-context.d.ts +26 -40
- package/dist/plugin-context.d.ts.map +1 -1
- package/dist/plugins/build-manifest.d.ts.map +1 -1
- package/dist/plugins/build-report.d.ts +15 -2
- package/dist/plugins/build-report.d.ts.map +1 -1
- package/dist/plugins/dev-server.d.ts.map +1 -1
- package/dist/plugins/entries.d.ts.map +1 -1
- package/dist/plugins/fonts.d.ts +19 -1
- package/dist/plugins/fonts.d.ts.map +1 -1
- package/dist/plugins/post-build.d.ts +110 -0
- package/dist/plugins/post-build.d.ts.map +1 -0
- package/dist/plugins/prebuilt-capture.d.ts +11 -4
- package/dist/plugins/prebuilt-capture.d.ts.map +1 -1
- package/dist/plugins/prebuilt.d.ts +17 -1
- package/dist/plugins/prebuilt.d.ts.map +1 -1
- package/dist/plugins/prerender-sugar.d.ts.map +1 -1
- package/dist/plugins/rsc-assets-manifest.d.ts +33 -0
- package/dist/plugins/rsc-assets-manifest.d.ts.map +1 -0
- package/dist/plugins/shims.d.ts.map +1 -1
- package/dist/plugins/static-build.d.ts +32 -9
- package/dist/plugins/static-build.d.ts.map +1 -1
- package/dist/routing/codegen-write.d.ts +0 -9
- package/dist/routing/codegen-write.d.ts.map +1 -1
- package/dist/routing/index.js +2 -2
- package/dist/routing/segment-codegen.d.ts.map +1 -1
- package/dist/server/access-gate.d.ts.map +1 -1
- package/dist/server/action-handler.d.ts +5 -4
- package/dist/server/action-handler.d.ts.map +1 -1
- package/dist/server/actions.d.ts +46 -7
- package/dist/server/actions.d.ts.map +1 -1
- package/dist/server/als-registry.d.ts +58 -5
- package/dist/server/als-registry.d.ts.map +1 -1
- package/dist/server/children-interception.d.ts.map +1 -1
- package/dist/server/cookie-context.d.ts +2 -23
- package/dist/server/cookie-context.d.ts.map +1 -1
- package/dist/server/csp-nonce.d.ts +0 -9
- package/dist/server/csp-nonce.d.ts.map +1 -1
- package/dist/server/csrf.d.ts +27 -4
- package/dist/server/csrf.d.ts.map +1 -1
- package/dist/server/debug.d.ts +0 -1
- package/dist/server/debug.d.ts.map +1 -1
- package/dist/server/default-logger.d.ts +2 -1
- package/dist/server/default-logger.d.ts.map +1 -1
- package/dist/server/deny-boundary.d.ts +12 -6
- package/dist/server/deny-boundary.d.ts.map +1 -1
- package/dist/server/deny-renderer.d.ts +2 -2
- package/dist/server/deny-renderer.d.ts.map +1 -1
- package/dist/server/error-boundary-wrapper.d.ts +7 -3
- package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
- package/dist/server/fallback-error.d.ts +9 -2
- package/dist/server/fallback-error.d.ts.map +1 -1
- package/dist/server/head-response.d.ts +4 -4
- package/dist/server/html-injectors.d.ts.map +1 -1
- package/dist/server/index.d.ts +0 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +3 -4
- package/dist/server/index.js.map +1 -1
- package/dist/server/instrumentation.d.ts +10 -3
- package/dist/server/instrumentation.d.ts.map +1 -1
- package/dist/server/internal.d.ts +1 -4
- package/dist/server/internal.d.ts.map +1 -1
- package/dist/server/internal.js +961 -581
- package/dist/server/internal.js.map +1 -1
- package/dist/server/json-status-response.d.ts +34 -0
- package/dist/server/json-status-response.d.ts.map +1 -0
- package/dist/server/logger.d.ts +26 -0
- package/dist/server/logger.d.ts.map +1 -1
- package/dist/server/param-coercion.d.ts +11 -6
- package/dist/server/param-coercion.d.ts.map +1 -1
- package/dist/server/pipeline-helpers.d.ts +95 -7
- package/dist/server/pipeline-helpers.d.ts.map +1 -1
- package/dist/server/pipeline-interception.d.ts +11 -0
- package/dist/server/pipeline-interception.d.ts.map +1 -1
- package/dist/server/pipeline-outcome.d.ts +11 -1
- package/dist/server/pipeline-outcome.d.ts.map +1 -1
- package/dist/server/pipeline-phases.d.ts +2 -2
- package/dist/server/pipeline-phases.d.ts.map +1 -1
- package/dist/server/pipeline.d.ts +23 -35
- package/dist/server/pipeline.d.ts.map +1 -1
- package/dist/server/prebuilt/capture-render.d.ts +25 -0
- package/dist/server/prebuilt/capture-render.d.ts.map +1 -0
- package/dist/server/prebuilt/capture-routes.d.ts +37 -0
- package/dist/server/prebuilt/capture-routes.d.ts.map +1 -0
- package/dist/server/prebuilt/capture-state.d.ts +79 -35
- package/dist/server/prebuilt/capture-state.d.ts.map +1 -1
- package/dist/server/prebuilt/lifetime.d.ts +38 -0
- package/dist/server/prebuilt/lifetime.d.ts.map +1 -0
- package/dist/server/prebuilt/slots.d.ts +7 -0
- package/dist/server/prebuilt/slots.d.ts.map +1 -1
- package/dist/server/prebuilt/synthetic-store.d.ts.map +1 -1
- package/dist/server/prebuilt-builder.d.ts.map +1 -1
- package/dist/server/prebuilt-runtime.d.ts.map +1 -1
- package/dist/server/primitives.d.ts +6 -81
- package/dist/server/primitives.d.ts.map +1 -1
- package/dist/server/react-cache-bridge.d.ts +59 -0
- package/dist/server/react-cache-bridge.d.ts.map +1 -0
- package/dist/server/react-cache-scope.d.ts +49 -0
- package/dist/server/react-cache-scope.d.ts.map +1 -0
- package/dist/server/render-timeout.d.ts +15 -0
- package/dist/server/render-timeout.d.ts.map +1 -1
- package/dist/server/render-utils.d.ts +9 -0
- package/dist/server/render-utils.d.ts.map +1 -1
- package/dist/server/request-context.d.ts +26 -5
- 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-handler.d.ts.map +1 -1
- package/dist/server/route-matcher.d.ts +7 -0
- package/dist/server/route-matcher.d.ts.map +1 -1
- package/dist/server/rsc-entry/action-middleware-runner.d.ts +22 -22
- package/dist/server/rsc-entry/action-middleware-runner.d.ts.map +1 -1
- package/dist/server/rsc-entry/api-handler.d.ts +7 -0
- package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
- package/dist/server/rsc-entry/deny-fallback.d.ts +32 -6
- package/dist/server/rsc-entry/deny-fallback.d.ts.map +1 -1
- package/dist/server/rsc-entry/error-renderer.d.ts +11 -18
- package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/helpers.d.ts +0 -1
- package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
- package/dist/server/rsc-entry/index.d.ts +5 -15
- package/dist/server/rsc-entry/index.d.ts.map +1 -1
- package/dist/server/rsc-entry/render-route.d.ts +5 -6
- package/dist/server/rsc-entry/render-route.d.ts.map +1 -1
- package/dist/server/rsc-entry/render-signals.d.ts +65 -0
- package/dist/server/rsc-entry/render-signals.d.ts.map +1 -0
- package/dist/server/rsc-entry/revalidate-renderer.d.ts +6 -16
- package/dist/server/rsc-entry/revalidate-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/rsc-payload.d.ts +7 -3
- package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
- package/dist/server/rsc-entry/rsc-stream.d.ts +8 -53
- package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-bridge.d.ts +2 -2
- package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-renderer.d.ts +9 -4
- package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/wrap-action-dispatch.d.ts +1 -1
- package/dist/server/rsc-entry/wrap-action-dispatch.d.ts.map +1 -1
- package/dist/server/signal-identity.d.ts +43 -0
- package/dist/server/signal-identity.d.ts.map +1 -0
- package/dist/server/slot-resolver.d.ts +4 -3
- package/dist/server/slot-resolver.d.ts.map +1 -1
- package/dist/server/slot-subtree-contain.d.ts.map +1 -1
- package/dist/server/ssr-bridge-types.d.ts +91 -53
- package/dist/server/ssr-bridge-types.d.ts.map +1 -1
- package/dist/server/ssr-entry.d.ts +8 -5
- package/dist/server/ssr-entry.d.ts.map +1 -1
- package/dist/server/ssr-render.d.ts +26 -40
- package/dist/server/ssr-render.d.ts.map +1 -1
- package/dist/server/ssr-wrappers.d.ts +1 -1
- package/dist/server/static-generator.d.ts.map +1 -1
- package/dist/server/stream-utils.d.ts +12 -0
- package/dist/server/stream-utils.d.ts.map +1 -1
- package/dist/server/tracing.d.ts +12 -16
- package/dist/server/tracing.d.ts.map +1 -1
- package/dist/server/types.d.ts +1 -1
- package/dist/server/version-skew.d.ts +3 -3
- package/dist/shared/csrf-reject.d.ts +16 -0
- package/dist/shared/csrf-reject.d.ts.map +1 -0
- package/dist/shared/error-digest.d.ts +28 -0
- package/dist/shared/error-digest.d.ts.map +1 -0
- package/dist/shared/payload-root.d.ts +11 -10
- package/dist/shared/payload-root.d.ts.map +1 -1
- package/dist/shared/rsc-payload-path.d.ts +6 -0
- package/dist/shared/rsc-payload-path.d.ts.map +1 -1
- package/dist/utils/write-file-atomic.d.ts +17 -0
- package/dist/utils/write-file-atomic.d.ts.map +1 -0
- package/docs/api/30-api-server.mdx +17 -14
- package/docs/api/32-api-cache.mdx +51 -23
- package/docs/api/34-api-config.mdx +34 -6
- package/docs/api/36-cli.mdx +11 -1
- package/docs/learn/03-fetching-data.mdx +17 -1
- package/docs/learn/04-access-control.mdx +1 -1
- package/docs/learn/10-caching.mdx +29 -11
- package/docs/learn/11-middleware.mdx +8 -2
- package/docs/learn/12-error-handling.mdx +6 -1
- package/package.json +5 -1
- package/src/adapters/build-output-helper.ts +55 -53
- package/src/adapters/canonicalize-module.ts +29 -0
- package/src/adapters/cloudflare.ts +105 -63
- package/src/adapters/compress-module.ts +16 -5
- package/src/adapters/fs-identity.ts +2 -3
- package/src/adapters/nitro-presets.ts +0 -15
- package/src/adapters/nitro-preview.ts +272 -136
- package/src/adapters/nitro.ts +119 -82
- package/src/adapters/shared.ts +23 -14
- package/src/adapters/types.ts +110 -21
- package/src/analyze/graph-cache.ts +3 -4
- package/src/cache/json-lossy-check.ts +3 -9
- package/src/cache/singleflight.ts +5 -2
- package/src/cache/sizeof.ts +3 -1
- package/src/cache/tag-aware-handler.ts +43 -26
- package/src/cli-check.ts +8 -98
- package/src/cli-context.ts +119 -0
- package/src/cli.ts +19 -28
- package/src/client/browser-dev.ts +1 -1
- package/src/client/browser-entry/action-dispatch.ts +26 -4
- package/src/client/browser-entry/hydrate.ts +53 -58
- package/src/client/browser-entry/index.ts +16 -27
- package/src/client/browser-entry/post-hydration.ts +6 -40
- package/src/client/browser-entry/router-init.ts +66 -84
- package/src/client/error-boundary.tsx +9 -41
- package/src/client/error-reconstituter.tsx +10 -5
- package/src/client/history.ts +18 -21
- package/src/client/index.ts +0 -1
- package/src/client/internal.ts +2 -7
- package/src/client/navigation-commit.ts +35 -18
- package/src/client/navigation-context.ts +3 -39
- package/src/client/react-root.ts +3 -2
- package/src/client/router-pipeline.ts +65 -128
- package/src/client/router-types.ts +46 -44
- package/src/client/router-url.ts +32 -0
- package/src/client/router.ts +43 -22
- package/src/client/rsc-fetch.ts +117 -155
- package/src/client/ssr-data.ts +19 -80
- package/src/client/state.ts +2 -9
- package/src/client/use-pathname.ts +1 -1
- package/src/config-types.ts +2 -1
- package/src/config-validation.ts +2 -1
- package/src/dev-tools/dev-page-shell.ts +18 -0
- package/src/dev-tools/index.ts +0 -2
- package/src/dev-tools/instrumentation.ts +50 -2
- package/src/dev-tools/overlay.ts +8 -238
- package/src/index.ts +24 -14
- package/src/plugin-context.ts +39 -40
- package/src/plugins/build-manifest.ts +4 -11
- package/src/plugins/build-report.ts +70 -70
- package/src/plugins/dev-server.ts +24 -44
- package/src/plugins/entries.ts +2 -1
- package/src/plugins/fonts.ts +35 -7
- package/src/plugins/post-build.ts +327 -0
- package/src/plugins/prebuilt-capture.ts +28 -32
- package/src/plugins/prebuilt.ts +54 -39
- package/src/plugins/prerender-sugar.ts +0 -4
- package/src/plugins/{adapter-build.ts → rsc-assets-manifest.ts} +20 -109
- package/src/plugins/shims.ts +1 -0
- package/src/plugins/static-build.ts +42 -74
- package/src/routing/codegen-write.ts +25 -3
- package/src/routing/segment-codegen.ts +3 -2
- package/src/rsc-runtime/vendor-types.d.ts +8 -0
- package/src/server/access-gate.tsx +2 -1
- package/src/server/action-client.ts +1 -1
- package/src/server/action-handler.ts +253 -110
- package/src/server/actions.ts +73 -25
- package/src/server/als-registry.ts +73 -5
- package/src/server/chain-url-parts.ts +1 -1
- package/src/server/children-interception.ts +2 -1
- package/src/server/cookie-context.ts +18 -48
- package/src/server/csp-nonce.ts +0 -12
- package/src/server/csrf.ts +140 -8
- package/src/server/debug.ts +0 -1
- package/src/server/default-logger.ts +2 -1
- package/src/server/deny-boundary.ts +25 -13
- package/src/server/deny-renderer.ts +30 -97
- package/src/server/error-boundary-wrapper.ts +7 -3
- package/src/server/fallback-error.ts +26 -11
- package/src/server/flight-scripts.ts +1 -1
- package/src/server/head-response.ts +4 -4
- package/src/server/html-injector-core.ts +2 -2
- package/src/server/html-injectors.ts +2 -4
- package/src/server/index.ts +0 -4
- package/src/server/instrumentation.ts +10 -3
- package/src/server/internal.ts +1 -6
- package/src/server/json-status-response.ts +105 -0
- package/src/server/logger.ts +39 -3
- package/src/server/param-coercion.ts +15 -12
- package/src/server/pipeline-helpers.ts +257 -12
- package/src/server/pipeline-interception.ts +133 -0
- package/src/server/pipeline-outcome.ts +103 -31
- package/src/server/pipeline-phases.ts +127 -237
- package/src/server/pipeline.ts +204 -207
- package/src/server/prebuilt/capture-render.ts +118 -0
- package/src/server/prebuilt/capture-routes.ts +104 -0
- package/src/server/prebuilt/capture-state.ts +155 -48
- package/src/server/prebuilt/lifetime.ts +151 -0
- package/src/server/prebuilt/slots.ts +14 -2
- package/src/server/prebuilt/synthetic-store.ts +3 -0
- package/src/server/prebuilt-builder.ts +30 -320
- package/src/server/prebuilt-runtime.ts +125 -129
- package/src/server/primitives.ts +8 -168
- package/src/server/react-cache-bridge.ts +124 -0
- package/src/server/react-cache-scope.ts +104 -0
- package/src/server/render-timeout.ts +20 -0
- package/src/server/render-utils.ts +11 -1
- package/src/server/request-context.ts +36 -9
- package/src/server/route-element-builder.ts +11 -6
- package/src/server/route-handler.ts +36 -23
- package/src/server/route-matcher.ts +15 -1
- package/src/server/rsc-entry/action-middleware-runner.ts +79 -123
- package/src/server/rsc-entry/api-handler.ts +27 -103
- package/src/server/rsc-entry/deny-fallback.ts +93 -26
- package/src/server/rsc-entry/error-renderer.ts +39 -91
- package/src/server/rsc-entry/helpers.ts +2 -4
- package/src/server/rsc-entry/index.ts +64 -58
- package/src/server/rsc-entry/render-route.ts +15 -80
- package/src/server/rsc-entry/render-signals.ts +108 -0
- package/src/server/rsc-entry/revalidate-renderer.ts +56 -57
- package/src/server/rsc-entry/rsc-payload.ts +28 -61
- package/src/server/rsc-entry/rsc-stream.ts +113 -213
- package/src/server/rsc-entry/ssr-bridge.ts +2 -2
- package/src/server/rsc-entry/ssr-renderer.ts +182 -263
- package/src/server/rsc-entry/wrap-action-dispatch.ts +12 -14
- package/src/server/signal-identity.ts +112 -0
- package/src/server/slot-resolver.ts +18 -18
- package/src/server/slot-subtree-contain.ts +2 -1
- package/src/server/ssr-bridge-types.ts +92 -56
- package/src/server/ssr-entry.ts +87 -111
- package/src/server/ssr-render.ts +55 -64
- package/src/server/ssr-wrappers.tsx +2 -2
- package/src/server/static-generator.ts +7 -42
- package/src/server/static-not-found.ts +3 -3
- package/src/server/stream-utils.ts +51 -0
- package/src/server/tracing.ts +58 -75
- package/src/server/types.ts +1 -1
- package/src/server/version-skew.ts +5 -5
- package/src/shared/csrf-reject.ts +15 -0
- package/src/shared/error-digest.ts +46 -0
- package/src/shared/payload-root.ts +11 -10
- package/src/shared/rsc-payload-path.ts +8 -1
- package/src/utils/write-file-atomic.ts +32 -0
- package/dist/_chunks/actions-jNrXdzgs.js +0 -346
- package/dist/_chunks/actions-jNrXdzgs.js.map +0 -1
- package/dist/_chunks/als-registry-C6kcfprT.js.map +0 -1
- package/dist/_chunks/build-manifest-DTmSGLRz.js.map +0 -1
- package/dist/_chunks/build-output-helper-9dqCv1pZ.js.map +0 -1
- package/dist/_chunks/cache-api-CUD9Ezaq.js.map +0 -1
- package/dist/_chunks/cli-check-G8o30ldg.js.map +0 -1
- package/dist/_chunks/convention-lint-5KzoMg_A.js.map +0 -1
- package/dist/_chunks/dev-server-BzBxgYAV.js.map +0 -1
- package/dist/_chunks/error-boundary-BrHmG-2X.js.map +0 -1
- package/dist/_chunks/fs-identity-D7vb6GdI.js.map +0 -1
- package/dist/_chunks/graph-cache-CP4GEmf9.js.map +0 -1
- package/dist/_chunks/json-lossy-check-ClNvBM_3.js.map +0 -1
- package/dist/_chunks/logger-k2DQ4EUf.js.map +0 -1
- package/dist/_chunks/navigation-context-D0TU0Jog.js.map +0 -1
- package/dist/_chunks/plugin-context-8idfR3UZ.js.map +0 -1
- package/dist/_chunks/primitives-DLAnvsrk.js.map +0 -1
- package/dist/_chunks/segment-context-D9_89u34.js +0 -34
- package/dist/_chunks/segment-context-D9_89u34.js.map +0 -1
- package/dist/_chunks/sizeof-lXffQ1Vr.js.map +0 -1
- package/dist/_chunks/ssr-data-D6T6Y3ef.js +0 -60
- package/dist/_chunks/ssr-data-D6T6Y3ef.js.map +0 -1
- package/dist/_chunks/state-FippDgxN.js.map +0 -1
- package/dist/_chunks/status-page-marker-CNbpUOPB.js.map +0 -1
- package/dist/client/types.d.ts +0 -14
- package/dist/client/types.d.ts.map +0 -1
- package/dist/plugins/adapter-build.d.ts +0 -38
- package/dist/plugins/adapter-build.d.ts.map +0 -1
- package/dist/server/asset-headers.d.ts +0 -32
- package/dist/server/asset-headers.d.ts.map +0 -1
- package/dist/server/dev-source-map.d.ts +0 -22
- package/dist/server/dev-source-map.d.ts.map +0 -1
- package/src/client/types.ts +0 -21
- package/src/server/asset-headers.ts +0 -59
- package/src/server/dev-source-map.ts +0 -31
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
* [timber] INFO message method=GET path=/dashboard status=200 durationMs=43 trace_id=4bf92f35
|
|
12
12
|
*
|
|
13
13
|
* Behavior:
|
|
14
|
-
* -
|
|
14
|
+
* - `info` and `debug` suppressed in dev mode (dev logging handles them);
|
|
15
|
+
* `warn` and `error` are always written (TIM-555)
|
|
15
16
|
* - `debug` suppressed unless TIMBER_DEBUG is set
|
|
16
17
|
* - Replaced entirely when a custom logger is set via `setLogger()`
|
|
17
18
|
*
|
|
@@ -39,8 +39,9 @@ import { ErrorReconstituter } from '../client/error-reconstituter.tsx';
|
|
|
39
39
|
import type { SerializableError } from '../client/error-reconstituter.tsx';
|
|
40
40
|
import { StatusPageMarker } from '../client/status-page-marker.tsx';
|
|
41
41
|
import { requestContextAls } from './als-registry.ts';
|
|
42
|
-
import {
|
|
43
|
-
import {
|
|
42
|
+
import { DenySignal } from './primitives.ts';
|
|
43
|
+
import { isDenySignal } from './signal-identity.ts';
|
|
44
|
+
import { loadFallbackModule } from './pipeline-helpers.ts';
|
|
44
45
|
import type { ManifestLoader } from './safe-load.ts';
|
|
45
46
|
import { withSpan } from './tracing.ts';
|
|
46
47
|
import { isValidElementType, type LoadedComponent } from './utils/element-type.ts';
|
|
@@ -136,8 +137,12 @@ export type DenyPlacement =
|
|
|
136
137
|
*
|
|
137
138
|
* See TIM-1356.
|
|
138
139
|
*/
|
|
139
|
-
async function loadChainComponent(
|
|
140
|
-
|
|
140
|
+
async function loadChainComponent(
|
|
141
|
+
file: ManifestLoader,
|
|
142
|
+
req: Request,
|
|
143
|
+
segments: ManifestSegmentNode[]
|
|
144
|
+
): Promise<LoadedComponent | null> {
|
|
145
|
+
const mod = await loadFallbackModule(file, req, segments);
|
|
141
146
|
return isValidElementType(mod?.default) ? mod.default : null;
|
|
142
147
|
}
|
|
143
148
|
|
|
@@ -159,7 +164,8 @@ async function loadChainComponent(file: ManifestLoader): Promise<LoadedComponent
|
|
|
159
164
|
export async function buildDenyPageChain(
|
|
160
165
|
segments: ManifestSegmentNode[],
|
|
161
166
|
startIndex: number,
|
|
162
|
-
segmentKeys: string[]
|
|
167
|
+
segmentKeys: string[],
|
|
168
|
+
req: Request
|
|
163
169
|
): Promise<DenyPageEntry[]> {
|
|
164
170
|
const chain: DenyPageEntry[] = [];
|
|
165
171
|
|
|
@@ -176,7 +182,7 @@ export async function buildDenyPageChain(
|
|
|
176
182
|
if (key !== '4xx' && key !== '5xx') {
|
|
177
183
|
const status = parseInt(key, 10);
|
|
178
184
|
if (!isNaN(status)) {
|
|
179
|
-
const component = await loadChainComponent(file);
|
|
185
|
+
const component = await loadChainComponent(file, req, segments);
|
|
180
186
|
if (component) {
|
|
181
187
|
chain.push({
|
|
182
188
|
status,
|
|
@@ -193,7 +199,7 @@ export async function buildDenyPageChain(
|
|
|
193
199
|
// Category catch-alls (4xx.tsx, 5xx.tsx)
|
|
194
200
|
for (const [key, file] of Object.entries(segment.statusFiles)) {
|
|
195
201
|
if (key === '4xx' || key === '5xx') {
|
|
196
|
-
const component = await loadChainComponent(file);
|
|
202
|
+
const component = await loadChainComponent(file, req, segments);
|
|
197
203
|
if (component) {
|
|
198
204
|
const categoryStatus = key === '4xx' ? 400 : 500;
|
|
199
205
|
chain.push({
|
|
@@ -214,7 +220,7 @@ export async function buildDenyPageChain(
|
|
|
214
220
|
for (let i = startIndex; i >= 0; i--) {
|
|
215
221
|
const segment = segments[i];
|
|
216
222
|
if (segment.error) {
|
|
217
|
-
const component = await loadChainComponent(segment.error);
|
|
223
|
+
const component = await loadChainComponent(segment.error, req, segments);
|
|
218
224
|
if (component) {
|
|
219
225
|
chain.push({
|
|
220
226
|
status: null,
|
|
@@ -394,11 +400,17 @@ function renderDenyPage(
|
|
|
394
400
|
* Otherwise it throws — annotated with `ownerKey` when an ancestor owns the
|
|
395
401
|
* file, bare when nothing matched at all.
|
|
396
402
|
*
|
|
397
|
-
* `setDenyStatus` runs on the hoist path too,
|
|
398
|
-
*
|
|
399
|
-
*
|
|
400
|
-
*
|
|
401
|
-
*
|
|
403
|
+
* `setDenyStatus` runs on the hoist path too, *before* the throw, for one
|
|
404
|
+
* case. Normally Flight's `onError` captures the rethrown signal within the
|
|
405
|
+
* renderer's promotion cap, and the pipeline renders the deny page with
|
|
406
|
+
* `deny.status` — the recorded status goes unread. When the signal lands
|
|
407
|
+
* after the cap but within the detection window that follows, the renderer
|
|
408
|
+
* discards it (never promoted) and streams the document it already has;
|
|
409
|
+
* `getDenyStatus()`, read once as the renderer returns, gives that document
|
|
410
|
+
* the deny's 4xx instead of a 200. A deny later than that commits 200. Pinned by
|
|
411
|
+
* `tests/late-hoisted-deny-status.test.ts`. The RSC payload path never
|
|
412
|
+
* reads it — a Flight payload response is always 200 and the row itself
|
|
413
|
+
* carries the deny (TIM-1495).
|
|
402
414
|
*
|
|
403
415
|
* Either branch leaves part of the matched chain unmounted — hoisting sends
|
|
404
416
|
* the render to a boundary that discards everything below it, and a layout
|
|
@@ -20,12 +20,11 @@ import { renderToReadableStream } from '../rsc-runtime/rsc.ts';
|
|
|
20
20
|
|
|
21
21
|
import { DenySignal } from './primitives.ts';
|
|
22
22
|
import { appVisibleSearch } from '../shared/rsc-cache-key.ts';
|
|
23
|
-
import { getSlotParamsForClient } from './request-context.ts';
|
|
24
23
|
import { withPublishedParams } from './publish-params.ts';
|
|
25
24
|
import { renderDenyEntry, type DenyEntryShape } from './deny-boundary.ts';
|
|
26
25
|
import { getCookiesForSsr } from './cookie-context.ts';
|
|
27
26
|
import { logRenderError } from './logger.ts';
|
|
28
|
-
import {
|
|
27
|
+
import { loadFallbackModule, reportRenderError } from './pipeline-helpers.ts';
|
|
29
28
|
import { isDebug } from './debug.ts';
|
|
30
29
|
import { resolveMetadata, renderMetadataToElements } from './metadata.ts';
|
|
31
30
|
import { headElementsToReact } from './metadata.ts';
|
|
@@ -33,8 +32,9 @@ import { resolveStatusFile } from './status-code-resolver.ts';
|
|
|
33
32
|
import { defaultStatusPageResponse } from './default-status-page.ts';
|
|
34
33
|
import { rscErrorEnvelope } from './rsc-error-envelope.ts';
|
|
35
34
|
import type { ManifestSegmentNode } from './route-matcher.ts';
|
|
35
|
+
import { renderJsonStatusFile } from './json-status-response.ts';
|
|
36
36
|
import type { RouteMatch } from './pipeline.ts';
|
|
37
|
-
import type { NavContext } from './ssr-bridge-types.ts';
|
|
37
|
+
import type { NavContext, SsrRenderResult } from './ssr-bridge-types.ts';
|
|
38
38
|
import { flightInitScript } from './flight-scripts.ts';
|
|
39
39
|
import { getCspNonce } from './csp-nonce.ts';
|
|
40
40
|
import type { ClientBootstrapConfig } from './html-injectors.ts';
|
|
@@ -52,15 +52,7 @@ export interface LayoutEntry {
|
|
|
52
52
|
export type CallSsrFn = (
|
|
53
53
|
rscStream: ReadableStream<Uint8Array>,
|
|
54
54
|
navContext: NavContext
|
|
55
|
-
) => Promise<
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Check if the leaf segment is an API route (has route.ts).
|
|
59
|
-
*/
|
|
60
|
-
function isApiRoute(segments: ReadonlyArray<ManifestSegmentNode>): boolean {
|
|
61
|
-
const leaf = segments[segments.length - 1];
|
|
62
|
-
return !!leaf?.route;
|
|
63
|
-
}
|
|
55
|
+
) => Promise<SsrRenderResult>;
|
|
64
56
|
|
|
65
57
|
/**
|
|
66
58
|
* Build the deny page element for a resolved status file with the correct
|
|
@@ -121,19 +113,21 @@ export async function renderDenyPage(
|
|
|
121
113
|
// (the gate-outside-layout rule from TIM-1074). See TIM-1358.
|
|
122
114
|
const maxIndex = firstDeniedIndex < Infinity ? firstDeniedIndex : undefined;
|
|
123
115
|
|
|
124
|
-
//
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
if (jsonResponse) return jsonResponse;
|
|
128
|
-
return bareJsonResponse(deny.status, responseHeaders);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Page routes → component chain first, JSON fallback only if no component found.
|
|
116
|
+
// Page routes → component chain first, JSON fallback only if no component
|
|
117
|
+
// found. A route.ts chain never reaches here: the deny fallback answers it
|
|
118
|
+
// in JSON before choosing a page renderer.
|
|
132
119
|
const resolution = resolveStatusFile(deny.status, segments, 'component', maxIndex);
|
|
133
120
|
|
|
134
121
|
// No component status file — try JSON chain, then the framework default page.
|
|
135
122
|
if (!resolution) {
|
|
136
|
-
const jsonResponse = await
|
|
123
|
+
const jsonResponse = await renderJsonStatusFile(
|
|
124
|
+
req,
|
|
125
|
+
deny.status,
|
|
126
|
+
segments,
|
|
127
|
+
responseHeaders,
|
|
128
|
+
maxIndex,
|
|
129
|
+
deny.data
|
|
130
|
+
);
|
|
137
131
|
if (jsonResponse) return jsonResponse;
|
|
138
132
|
return (
|
|
139
133
|
defaultPage?.(deny.status, responseHeaders) ??
|
|
@@ -159,11 +153,18 @@ export async function renderDenyPage(
|
|
|
159
153
|
// default — or whose module fails to import or evaluate — is not a usable
|
|
160
154
|
// component match: continue down the documented chain (JSON, then framework
|
|
161
155
|
// default) rather than returning an empty body or letting the loader's
|
|
162
|
-
// rejection escape request handling.
|
|
163
|
-
//
|
|
164
|
-
const mod = await
|
|
156
|
+
// rejection escape request handling. `loadFallbackModule` reports the load
|
|
157
|
+
// failure, as it does for every status and error page load.
|
|
158
|
+
const mod = await loadFallbackModule(resolution.file, req, segments);
|
|
165
159
|
if (!mod?.default) {
|
|
166
|
-
const jsonResponse = await
|
|
160
|
+
const jsonResponse = await renderJsonStatusFile(
|
|
161
|
+
req,
|
|
162
|
+
deny.status,
|
|
163
|
+
segments,
|
|
164
|
+
responseHeaders,
|
|
165
|
+
maxIndex,
|
|
166
|
+
deny.data
|
|
167
|
+
);
|
|
167
168
|
if (jsonResponse) return jsonResponse;
|
|
168
169
|
return (
|
|
169
170
|
defaultPage?.(deny.status, responseHeaders) ??
|
|
@@ -209,21 +210,17 @@ export async function renderDenyPage(
|
|
|
209
210
|
const rscStream = renderToReadableStream(withPublishedParams(element), {
|
|
210
211
|
signal: req.signal,
|
|
211
212
|
onError(error: unknown) {
|
|
212
|
-
|
|
213
|
+
reportRenderError(error, req, { segments });
|
|
213
214
|
},
|
|
214
215
|
});
|
|
215
216
|
|
|
216
217
|
const [ssrStream, inlineStream] = teeWithErrorPropagation(rscStream);
|
|
217
218
|
|
|
218
|
-
const slotParams = getSlotParamsForClient();
|
|
219
|
-
|
|
220
219
|
const denyUrl = new URL(req.url);
|
|
221
220
|
const nonce = getCspNonce();
|
|
222
221
|
const navContext: NavContext = {
|
|
223
222
|
pathname: denyUrl.pathname,
|
|
224
223
|
search: appVisibleSearch(denyUrl).search,
|
|
225
|
-
segmentParams: match.segmentParams,
|
|
226
|
-
slotParams,
|
|
227
224
|
statusCode: deny.status,
|
|
228
225
|
responseHeaders,
|
|
229
226
|
headHtml: flightInitScript(nonce),
|
|
@@ -241,7 +238,7 @@ export async function renderDenyPage(
|
|
|
241
238
|
// own deny fallback catches this and can only produce an empty response,
|
|
242
239
|
// and a crashing 404.tsx is exactly when the reader has nothing else to
|
|
243
240
|
// go on (TIM-1258).
|
|
244
|
-
return await callSsr(ssrStream, navContext);
|
|
241
|
+
return (await callSsr(ssrStream, navContext)).response;
|
|
245
242
|
} catch (renderError) {
|
|
246
243
|
logRenderError({ method: req.method, path: new URL(req.url).pathname, error: renderError });
|
|
247
244
|
return defaultStatusPageResponse(deny.status, responseHeaders);
|
|
@@ -283,7 +280,7 @@ export async function renderDenyPageAsRsc(
|
|
|
283
280
|
return denyHardNavigateResponse(deny.status, responseHeaders);
|
|
284
281
|
}
|
|
285
282
|
|
|
286
|
-
const mod = await
|
|
283
|
+
const mod = await loadFallbackModule(resolution.file, req, segments);
|
|
287
284
|
if (!mod?.default) {
|
|
288
285
|
return denyHardNavigateResponse(deny.status, responseHeaders);
|
|
289
286
|
}
|
|
@@ -310,7 +307,7 @@ export async function renderDenyPageAsRsc(
|
|
|
310
307
|
const rscStream = renderToReadableStream(withPublishedParams(element), {
|
|
311
308
|
signal: req.signal,
|
|
312
309
|
onError(error: unknown) {
|
|
313
|
-
|
|
310
|
+
reportRenderError(error, req);
|
|
314
311
|
},
|
|
315
312
|
});
|
|
316
313
|
|
|
@@ -325,68 +322,4 @@ export async function renderDenyPageAsRsc(
|
|
|
325
322
|
});
|
|
326
323
|
}
|
|
327
324
|
|
|
328
|
-
// ─── JSON Rendering ─────────────────────────────────────────────────────────
|
|
329
|
-
|
|
330
|
-
/**
|
|
331
|
-
* Render a JSON status-code file for a DenySignal.
|
|
332
|
-
*
|
|
333
|
-
* JSON status files are returned verbatim with Content-Type: application/json.
|
|
334
|
-
* No React rendering pipeline, no layout wrapping.
|
|
335
|
-
*
|
|
336
|
-
* Returns null if no JSON status file is found (caller should use bare JSON fallback).
|
|
337
|
-
*/
|
|
338
|
-
async function renderDenyPageJson(
|
|
339
|
-
deny: DenySignal,
|
|
340
|
-
segments: ManifestSegmentNode[],
|
|
341
|
-
responseHeaders: Headers,
|
|
342
|
-
maxIndex?: number
|
|
343
|
-
): Promise<Response | null> {
|
|
344
|
-
const resolution = resolveStatusFile(deny.status, segments, 'json', maxIndex);
|
|
345
|
-
|
|
346
|
-
if (!resolution) {
|
|
347
|
-
return null;
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
// JSON status files are loaded as modules that export the JSON content.
|
|
351
|
-
// The manifest's load() imports the .json file, which Vite handles as a
|
|
352
|
-
// default export of the parsed JSON object.
|
|
353
|
-
// A .json status file that fails to load is not a usable match — return
|
|
354
|
-
// null so the caller continues to the framework default rather than
|
|
355
|
-
// rejecting out of the chain.
|
|
356
|
-
// Dev warning: deny(status, { dangerouslyPassData }) carries data but JSON
|
|
357
|
-
// status files are static bodies — the data is silently dropped. The same
|
|
358
|
-
// deny() would deliver the data to a .tsx file's data prop. See
|
|
359
|
-
// design/10-error-handling.md §"Status-Code File Variants".
|
|
360
|
-
if (isDebug() && deny.data !== undefined) {
|
|
361
|
-
console.warn(
|
|
362
|
-
`[timber] deny(${deny.status}, data) resolved to ${resolution.file.filePath}, ` +
|
|
363
|
-
`which is a static JSON file. The data argument is dropped — JSON status files ` +
|
|
364
|
-
`are returned verbatim with no interpolation. If you need the data in the ` +
|
|
365
|
-
`response, use a .tsx status file or a route handler (route.ts).`
|
|
366
|
-
);
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
const mod = await loadModule(resolution.file).catch(() => null);
|
|
370
|
-
if (!mod) return null;
|
|
371
|
-
const jsonContent = mod.default ?? mod;
|
|
372
|
-
|
|
373
|
-
responseHeaders.set('content-type', 'application/json; charset=utf-8');
|
|
374
|
-
return new Response(JSON.stringify(jsonContent), {
|
|
375
|
-
status: deny.status,
|
|
376
|
-
headers: responseHeaders,
|
|
377
|
-
});
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
/**
|
|
381
|
-
* Return a bare JSON error response when no JSON status file exists.
|
|
382
|
-
* This is the framework default for JSON format requests.
|
|
383
|
-
*/
|
|
384
|
-
function bareJsonResponse(status: number, responseHeaders: Headers): Response {
|
|
385
|
-
responseHeaders.set('content-type', 'application/json; charset=utf-8');
|
|
386
|
-
return new Response(JSON.stringify({ error: true, status }), {
|
|
387
|
-
status,
|
|
388
|
-
headers: responseHeaders,
|
|
389
|
-
});
|
|
390
|
-
}
|
|
391
|
-
|
|
392
325
|
// escapeHtml imported from server/utils/escape-html.ts
|
|
@@ -61,10 +61,14 @@ export interface ErrorBoundaryProps {
|
|
|
61
61
|
children: ReactNode;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
/**
|
|
64
|
+
/**
|
|
65
|
+
* How to load a route file's module. Only `default` is read. The server
|
|
66
|
+
* injects `loadFallbackModule`, which reports a failed load and returns
|
|
67
|
+
* `null`, so a broken status or error page is never skipped silently.
|
|
68
|
+
*/
|
|
65
69
|
type BoundaryModuleLoader<TFile> = (
|
|
66
70
|
file: TFile
|
|
67
|
-
) => { default?: unknown } | Promise<{ default?: unknown }>;
|
|
71
|
+
) => { default?: unknown } | null | Promise<{ default?: unknown } | null>;
|
|
68
72
|
|
|
69
73
|
/** Everything the walk needs from its host environment. */
|
|
70
74
|
export interface ErrorBoundaryWrapConfig<TFile, TElement> {
|
|
@@ -98,7 +102,7 @@ async function loadBoundaryComponent<TFile>(
|
|
|
98
102
|
file: TFile,
|
|
99
103
|
loadModule: BoundaryModuleLoader<TFile>
|
|
100
104
|
): Promise<LoadedComponent | null> {
|
|
101
|
-
let mod: { default?: unknown };
|
|
105
|
+
let mod: { default?: unknown } | null;
|
|
102
106
|
try {
|
|
103
107
|
mod = await loadModule(file);
|
|
104
108
|
} catch {
|
|
@@ -8,21 +8,26 @@
|
|
|
8
8
|
* In production: attempts to render root error pages (500.tsx / 5xx.tsx /
|
|
9
9
|
* error.tsx) via the normal RSC → SSR pipeline. Stack traces are never
|
|
10
10
|
* exposed to the client (design/13-security.md principle 4).
|
|
11
|
+
*
|
|
12
|
+
* A route.ts match, in dev or production, gets the API route's JSON format
|
|
13
|
+
* instead: the `500.json` / `5xx.json` chain, then the bare
|
|
14
|
+
* `{"error": true, "status": 500}` body. That is the same format its denies
|
|
15
|
+
* use (design/10-error-handling.md §"JSON Error Pages").
|
|
11
16
|
*/
|
|
12
17
|
|
|
13
18
|
import type { RouteMatch } from './pipeline.ts';
|
|
14
|
-
import type
|
|
19
|
+
import { isApiRouteChain, type ManifestSegmentNode } from './route-matcher.ts';
|
|
15
20
|
import type { ClientBootstrapConfig } from './html-injectors.ts';
|
|
16
21
|
import type { LayoutEntry } from './deny-renderer.ts';
|
|
17
22
|
import type { GlobalErrorFile } from './rsc-entry/error-renderer.ts';
|
|
18
23
|
import { swallow } from './logger.ts';
|
|
19
|
-
import {
|
|
24
|
+
import { reportRenderError } from './pipeline-helpers.ts';
|
|
20
25
|
import { loadModule } from './safe-load.ts';
|
|
21
|
-
import { sourceMapError } from './dev-source-map.ts';
|
|
22
26
|
|
|
23
27
|
/**
|
|
24
28
|
* Render a fallback error page when the render pipeline throws.
|
|
25
29
|
*
|
|
30
|
+
* For a route.ts match: the JSON status chain.
|
|
26
31
|
* In dev: styled HTML with error details.
|
|
27
32
|
* In prod: renders root error pages via renderErrorPage.
|
|
28
33
|
*/
|
|
@@ -30,6 +35,7 @@ export async function renderFallbackError(
|
|
|
30
35
|
error: unknown,
|
|
31
36
|
req: Request,
|
|
32
37
|
responseHeaders: Headers,
|
|
38
|
+
match: RouteMatch | undefined,
|
|
33
39
|
isDev: boolean,
|
|
34
40
|
rootSegment: ManifestSegmentNode,
|
|
35
41
|
clientBootstrap: ClientBootstrapConfig,
|
|
@@ -37,9 +43,13 @@ export async function renderFallbackError(
|
|
|
37
43
|
projectRoot?: string,
|
|
38
44
|
hmrOptions?: import('../dev-tools/dev-page-shell.ts').DevErrorHmrOptions
|
|
39
45
|
): Promise<Response> {
|
|
40
|
-
//
|
|
41
|
-
// shows
|
|
42
|
-
|
|
46
|
+
// An API consumer never gets a page, including the dev error page. The dev
|
|
47
|
+
// overlay still shows the error; it is fed by onPipelineError, not by this
|
|
48
|
+
// response.
|
|
49
|
+
if (match && isApiRouteChain(match.segments)) {
|
|
50
|
+
const { renderJsonStatusResponse } = await import('./json-status-response.ts');
|
|
51
|
+
return renderJsonStatusResponse(req, 500, match.segments, responseHeaders);
|
|
52
|
+
}
|
|
43
53
|
|
|
44
54
|
if (isDev) {
|
|
45
55
|
return renderDevErrorPage(error, projectRoot, hmrOptions);
|
|
@@ -66,16 +76,21 @@ export async function renderFallbackError(
|
|
|
66
76
|
// Layout failed to load — proceed without it. renderErrorPage will
|
|
67
77
|
// attempt segment-level error pages (without layout wrapping) and
|
|
68
78
|
// then fall through to global-error.tsx if those also fail.
|
|
69
|
-
|
|
79
|
+
reportRenderError(layoutError, req, { segments: match?.segments });
|
|
70
80
|
}
|
|
71
|
-
const
|
|
81
|
+
const rootMatch: RouteMatch = {
|
|
82
|
+
segments,
|
|
83
|
+
segmentParams: {},
|
|
84
|
+
rawSegmentParams: {},
|
|
85
|
+
middlewareChain: [],
|
|
86
|
+
};
|
|
72
87
|
return renderErrorPage(
|
|
73
88
|
error,
|
|
74
89
|
500,
|
|
75
90
|
segments,
|
|
76
91
|
layoutComponents,
|
|
77
92
|
req,
|
|
78
|
-
|
|
93
|
+
rootMatch,
|
|
79
94
|
responseHeaders,
|
|
80
95
|
clientBootstrap,
|
|
81
96
|
globalError
|
|
@@ -102,8 +117,8 @@ export async function renderDevErrorPage(
|
|
|
102
117
|
|
|
103
118
|
let html: string;
|
|
104
119
|
try {
|
|
105
|
-
// Dynamic import — keeps dev-error-page.ts and its transitive deps
|
|
106
|
-
// (dev-
|
|
120
|
+
// Dynamic import — keeps dev-tools/error-page.ts and its transitive deps
|
|
121
|
+
// (dev-tools/overlay.ts, dev-tools/terminal.ts) out of production bundles.
|
|
107
122
|
const { generateDevErrorPage } = await import('../dev-tools/error-page.ts');
|
|
108
123
|
html = generateDevErrorPage(err, 'render', root, hmrOptions);
|
|
109
124
|
// Inject Vite client script so the error overlay fires when HMR connects.
|
|
@@ -16,10 +16,10 @@
|
|
|
16
16
|
*
|
|
17
17
|
* The pipeline applies this at its single exit so every response shape is
|
|
18
18
|
* covered — page render, API route, metadata route, deny page, error page,
|
|
19
|
-
* proxy short-circuit. The
|
|
20
|
-
* standalone
|
|
21
|
-
*
|
|
22
|
-
*
|
|
19
|
+
* proxy short-circuit. The unit-level producer that is also reachable as a
|
|
20
|
+
* standalone function (`handleRouteRequest`) calls it too, so it honours HEAD
|
|
21
|
+
* on its own; it shares this implementation rather than repeating it, and
|
|
22
|
+
* applying it twice is a no-op.
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
25
|
/**
|
|
@@ -33,7 +33,7 @@ import {
|
|
|
33
33
|
type FlightInjectionState,
|
|
34
34
|
type FlightInjectionEvent,
|
|
35
35
|
} from './flight-injection-state.ts';
|
|
36
|
-
import { withTimeout, RenderTimeoutError } from './render-timeout.ts';
|
|
36
|
+
import { withTimeout, RenderTimeoutError, resolveRenderTimeoutMs } from './render-timeout.ts';
|
|
37
37
|
|
|
38
38
|
// ─── Encoders / Constants ────────────────────────────────────────────────────
|
|
39
39
|
|
|
@@ -384,7 +384,7 @@ export class FlightInjectorCore {
|
|
|
384
384
|
|
|
385
385
|
constructor(rscStream: ReadableStream<Uint8Array>, options: FlightInjectorOptions = {}) {
|
|
386
386
|
this.rscReader = rscStream.getReader();
|
|
387
|
-
this.timeoutMs = (options.renderTimeoutMs
|
|
387
|
+
this.timeoutMs = resolveRenderTimeoutMs(options.renderTimeoutMs);
|
|
388
388
|
this.errorSignal = options.errorSignal;
|
|
389
389
|
this.nonce = options.nonce;
|
|
390
390
|
this.machine = createMachine<FlightInjectionState, FlightInjectionEvent>({
|
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
suffixFlush,
|
|
32
32
|
} from './html-injector-core.ts';
|
|
33
33
|
import { flightChunkScript } from './flight-scripts.ts';
|
|
34
|
-
import { withTimeout, RenderTimeoutError } from './render-timeout.ts';
|
|
34
|
+
import { withTimeout, RenderTimeoutError, resolveRenderTimeoutMs } from './render-timeout.ts';
|
|
35
35
|
import { createTickCoalescer } from './coalesce-tick.ts';
|
|
36
36
|
|
|
37
37
|
// ─── Buffered Transform ──────────────────────────────────────────────────────
|
|
@@ -207,9 +207,7 @@ export function createInlinedRscStream(
|
|
|
207
207
|
): ReadableStream<Uint8Array> {
|
|
208
208
|
const rscReader = rscStream.getReader();
|
|
209
209
|
const decoder = new TextDecoder('utf-8', { fatal: true });
|
|
210
|
-
|
|
211
|
-
// so a stalled RSC stream can't hang the connection forever.
|
|
212
|
-
const timeoutMs = (renderTimeoutMs ?? 30_000) || 120_000;
|
|
210
|
+
const timeoutMs = resolveRenderTimeoutMs(renderTimeoutMs);
|
|
213
211
|
|
|
214
212
|
return new ReadableStream<Uint8Array>({
|
|
215
213
|
async pull(controller) {
|
package/src/server/index.ts
CHANGED
|
@@ -30,10 +30,6 @@ export {
|
|
|
30
30
|
type DenyOptions,
|
|
31
31
|
type RedirectOptions,
|
|
32
32
|
} from './primitives.ts';
|
|
33
|
-
// RenderError removed from public exports per TIM-724.
|
|
34
|
-
// Use deny({ status: 500, data: ... }) instead. RenderError stays in
|
|
35
|
-
// #server-internal for pipeline catch logic.
|
|
36
|
-
export type { RenderErrorDigest } from './primitives.ts';
|
|
37
33
|
// JsonSerializable moved to @timber-js/app/codec as the single canonical path.
|
|
38
34
|
// Re-export removed per TIM-721.
|
|
39
35
|
|
|
@@ -29,11 +29,18 @@ export interface InstrumentationRequestInfo {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
export interface InstrumentationErrorContext {
|
|
32
|
-
/**
|
|
33
|
-
|
|
32
|
+
/**
|
|
33
|
+
* Which pipeline phase the error occurred in. `'setup'` is route setup
|
|
34
|
+
* between `proxy.ts` and `middleware.ts`: route matching and segment-param
|
|
35
|
+
* coercion (e.g. an `app/schema.ts` codec returning a value a param cannot
|
|
36
|
+
* hold). `'handler'` is `middleware.ts`; `'route'` is a `route.ts` handler
|
|
37
|
+
* or its `access.ts`, or a metadata route handler. design/17 §"Which errors
|
|
38
|
+
* reach it" lists every error that is reported, and those that are not.
|
|
39
|
+
*/
|
|
40
|
+
phase: 'proxy' | 'setup' | 'handler' | 'render' | 'action' | 'route';
|
|
34
41
|
/** The route pattern: '/dashboard/projects/[id]' */
|
|
35
42
|
routePath: string;
|
|
36
|
-
/** Type of route that was matched. */
|
|
43
|
+
/** Type of route that was matched. A metadata route reports as `'route'`. */
|
|
37
44
|
routeType: 'page' | 'route' | 'action';
|
|
38
45
|
/** Always set — OTEL trace ID or UUID fallback. */
|
|
39
46
|
traceId: string;
|
package/src/server/internal.ts
CHANGED
|
@@ -27,8 +27,7 @@ export { getCookie, getSetCookieHeaders } from './cookie-context.ts';
|
|
|
27
27
|
export { coerce } from './form-data.ts';
|
|
28
28
|
|
|
29
29
|
// ── Signal classes (instanceof targets for pipeline catch logic) ──────────
|
|
30
|
-
export { DenySignal, RedirectSignal
|
|
31
|
-
export type { RenderErrorDigest } from './primitives.ts';
|
|
30
|
+
export { DenySignal, RedirectSignal } from './primitives.ts';
|
|
32
31
|
|
|
33
32
|
// ── Pipeline ─────────────────────────────────────────────────────────────
|
|
34
33
|
export { createPipeline } from './pipeline.ts';
|
|
@@ -78,10 +77,6 @@ export type {
|
|
|
78
77
|
SlotDeniedKind,
|
|
79
78
|
} from './status-code-resolver.ts';
|
|
80
79
|
|
|
81
|
-
// ── CSRF Protection ──────────────────────────────────────────────────────
|
|
82
|
-
export { validateCsrf } from './csrf.ts';
|
|
83
|
-
export type { CsrfConfig, CsrfResult } from './csrf.ts';
|
|
84
|
-
|
|
85
80
|
// ── Body Limits ──────────────────────────────────────────────────────────
|
|
86
81
|
export { parseBodySize, enforceBodyLimits, DEFAULT_LIMITS } from './body-limits.ts';
|
|
87
82
|
export type { BodyLimitsConfig, BodyLimitResult, BodyKind } from './body-limits.ts';
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSON status responses — the status-code chain for API consumers.
|
|
3
|
+
*
|
|
4
|
+
* `{status}.json` → `{category}.json`, leaf → root, then the bare
|
|
5
|
+
* `{"error": true, "status": N}` body. No React, so the route.ts path and
|
|
6
|
+
* the pipeline's fallback renderer can use it without loading the RSC
|
|
7
|
+
* runtime.
|
|
8
|
+
*
|
|
9
|
+
* See design/10-error-handling.md §"JSON Error Pages".
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { isDebug } from './debug.ts';
|
|
13
|
+
import { loadFallbackModule } from './pipeline-helpers.ts';
|
|
14
|
+
import { resolveStatusFile } from './status-code-resolver.ts';
|
|
15
|
+
import type { ManifestSegmentNode } from './route-matcher.ts';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Render the JSON status chain for `status` — `{status}.json` →
|
|
19
|
+
* `{category}.json`, leaf → root — ending in the bare
|
|
20
|
+
* `{"error": true, "status": N}` body when no file resolves.
|
|
21
|
+
*
|
|
22
|
+
* This is the one API-route error format (design/10-error-handling.md
|
|
23
|
+
* §"Format Selection for deny()"). A deny from `access.ts` or a handler, and
|
|
24
|
+
* an error the pipeline answers for a route.ts match, all end here.
|
|
25
|
+
*
|
|
26
|
+
* `droppedData` is a deny()'s data. It is only read to warn that a static
|
|
27
|
+
* JSON file cannot carry it.
|
|
28
|
+
*/
|
|
29
|
+
export async function renderJsonStatusResponse(
|
|
30
|
+
req: Request,
|
|
31
|
+
status: number,
|
|
32
|
+
segments: ManifestSegmentNode[],
|
|
33
|
+
responseHeaders: Headers,
|
|
34
|
+
maxIndex?: number,
|
|
35
|
+
droppedData?: unknown
|
|
36
|
+
): Promise<Response> {
|
|
37
|
+
return (
|
|
38
|
+
(await renderJsonStatusFile(req, status, segments, responseHeaders, maxIndex, droppedData)) ??
|
|
39
|
+
bareJsonResponse(status, responseHeaders)
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Render a JSON status-code file for `status`.
|
|
45
|
+
*
|
|
46
|
+
* JSON status files are returned verbatim with Content-Type: application/json.
|
|
47
|
+
* No React rendering pipeline, no layout wrapping.
|
|
48
|
+
*
|
|
49
|
+
* Returns null if no JSON status file is found (caller should use bare JSON fallback).
|
|
50
|
+
*/
|
|
51
|
+
export async function renderJsonStatusFile(
|
|
52
|
+
req: Request,
|
|
53
|
+
status: number,
|
|
54
|
+
segments: ManifestSegmentNode[],
|
|
55
|
+
responseHeaders: Headers,
|
|
56
|
+
maxIndex?: number,
|
|
57
|
+
droppedData?: unknown
|
|
58
|
+
): Promise<Response | null> {
|
|
59
|
+
const resolution = resolveStatusFile(status, segments, 'json', maxIndex);
|
|
60
|
+
|
|
61
|
+
if (!resolution) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// JSON status files are loaded as modules that export the JSON content.
|
|
66
|
+
// The manifest's load() imports the .json file, which Vite handles as a
|
|
67
|
+
// default export of the parsed JSON object.
|
|
68
|
+
// A .json status file that fails to load (reported) is not a usable
|
|
69
|
+
// match — return null so the caller continues to the framework default
|
|
70
|
+
// rather than rejecting out of the chain.
|
|
71
|
+
// Dev warning: deny(status, { dangerouslyPassData }) carries data but JSON
|
|
72
|
+
// status files are static bodies — the data is silently dropped. The same
|
|
73
|
+
// deny() would deliver the data to a .tsx file's data prop. See
|
|
74
|
+
// design/10-error-handling.md §"Status-Code File Variants".
|
|
75
|
+
if (isDebug() && droppedData !== undefined) {
|
|
76
|
+
console.warn(
|
|
77
|
+
`[timber] deny(${status}, data) resolved to ${resolution.file.filePath}, ` +
|
|
78
|
+
`which is a static JSON file. The data argument is dropped — JSON status files ` +
|
|
79
|
+
`are returned verbatim with no interpolation. If you need the data in the ` +
|
|
80
|
+
`response, use a .tsx status file or a route handler (route.ts).`
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const mod = await loadFallbackModule(resolution.file, req, segments);
|
|
85
|
+
if (!mod) return null;
|
|
86
|
+
const jsonContent = mod.default ?? mod;
|
|
87
|
+
|
|
88
|
+
responseHeaders.set('content-type', 'application/json; charset=utf-8');
|
|
89
|
+
return new Response(JSON.stringify(jsonContent), {
|
|
90
|
+
status,
|
|
91
|
+
headers: responseHeaders,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Return a bare JSON error response when no JSON status file exists.
|
|
97
|
+
* This is the framework default for JSON format requests.
|
|
98
|
+
*/
|
|
99
|
+
function bareJsonResponse(status: number, responseHeaders: Headers): Response {
|
|
100
|
+
responseHeaders.set('content-type', 'application/json; charset=utf-8');
|
|
101
|
+
return new Response(JSON.stringify({ error: true, status }), {
|
|
102
|
+
status,
|
|
103
|
+
headers: responseHeaders,
|
|
104
|
+
});
|
|
105
|
+
}
|