@timber-js/app 0.2.0-alpha.207 → 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-BndF-3Td.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-DwQBrLBz.js → status-page-marker-gaihi0KZ.js} +140 -28
- 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 +20 -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 +95 -108
- package/dist/client/internal.js.map +1 -1
- package/dist/client/navigation-commit.d.ts +20 -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 +3 -8
- 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/segment-cache.d.ts +44 -4
- package/dist/client/segment-cache.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 +632 -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/react-resolve.d.ts +49 -0
- package/dist/plugins/react-resolve.d.ts.map +1 -0
- 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 +7 -3
- 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 +35 -21
- package/src/client/index.ts +0 -1
- package/src/client/internal.ts +2 -7
- package/src/client/navigation-commit.ts +41 -18
- package/src/client/navigation-context.ts +3 -39
- package/src/client/react-root.ts +3 -2
- package/src/client/router-pipeline.ts +96 -132
- package/src/client/router-types.ts +46 -44
- package/src/client/router-url.ts +32 -0
- package/src/client/router.ts +62 -21
- package/src/client/rsc-fetch.ts +117 -155
- package/src/client/segment-cache.ts +110 -11
- 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 +26 -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/react-resolve.ts +149 -0
- 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-BndF-3Td.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-DwQBrLBz.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
|
@@ -5,12 +5,11 @@
|
|
|
5
5
|
* pipeline construction. This module owns the steps that happen *after*
|
|
6
6
|
* the pipeline has matched a route and before it commits a response:
|
|
7
7
|
* element-tree build, RSC Flight render, and dispatch to either the SSR
|
|
8
|
-
* HTML path or the RSC payload path.
|
|
9
|
-
*
|
|
10
|
-
* thrown during stream creation) so the entry doesn't carry that logic.
|
|
8
|
+
* HTML path or the RSC payload path. A deny or redirect captured during the
|
|
9
|
+
* render is rethrown to the pipeline, which answers it.
|
|
11
10
|
*
|
|
12
11
|
* The function is parameterized over its dependencies — `clientBootstrap`,
|
|
13
|
-
* `clientJsDisabled`, `
|
|
12
|
+
* `clientJsDisabled`, `renderDenyFallback`, `globalError` — so the entry passes
|
|
14
13
|
* them in once at handler-construction time and they ride along on every
|
|
15
14
|
* call. No globals, no closures over the entry's createRequestHandler
|
|
16
15
|
* scope.
|
|
@@ -27,25 +26,19 @@ import {
|
|
|
27
26
|
collectRouteFonts,
|
|
28
27
|
collectRouteModulepreloads,
|
|
29
28
|
} from '../build-manifest.ts';
|
|
30
|
-
import type { LayoutEntry } from '../deny-renderer.ts';
|
|
31
|
-
import { renderDenyPage, renderDenyPageAsRsc } from '../deny-renderer.ts';
|
|
32
29
|
import type { ClientBootstrapConfig } from '../html-injectors.ts';
|
|
33
30
|
import type { InterceptionContext, RouteMatch } from '../pipeline.ts';
|
|
31
|
+
import { DenySignal } from '../primitives.ts';
|
|
34
32
|
import { buildRouteElement, NoPageComponentError } from '../route-element-builder.ts';
|
|
35
|
-
import { ParamCoercionError } from '../param-coercion.ts';
|
|
36
|
-
import type { ManifestSegmentNode } from '../route-matcher.ts';
|
|
37
33
|
import { recordTiming } from '../server-timing.ts';
|
|
38
34
|
import { parseClientStateTree } from '../state-tree-diff.ts';
|
|
39
35
|
|
|
40
|
-
import { getFirstDeniedSegmentIndex } from '../deny-boundary.ts';
|
|
41
36
|
import { handleApiRoute } from './api-handler.ts';
|
|
42
|
-
import {
|
|
43
|
-
import { buildRedirectResponse } from './helpers.ts';
|
|
37
|
+
import type { DenyFallbackRenderer } from './deny-fallback.ts';
|
|
44
38
|
import { isRscRequest } from '../../shared/rsc-media-type.ts';
|
|
45
39
|
import { buildRscPayloadResponse } from './rsc-payload.ts';
|
|
46
40
|
import { renderRscStream } from './rsc-stream.ts';
|
|
47
41
|
import { renderSsrResponse } from './ssr-renderer.ts';
|
|
48
|
-
import { callSsr } from './ssr-bridge.ts';
|
|
49
42
|
|
|
50
43
|
/**
|
|
51
44
|
* Static-per-handler dependencies for `renderRoute` — captured once at
|
|
@@ -56,7 +49,7 @@ export interface RenderRouteDeps {
|
|
|
56
49
|
clientBootstrap: ClientBootstrapConfig;
|
|
57
50
|
clientJsDisabled: boolean;
|
|
58
51
|
clientSegmentCache: boolean;
|
|
59
|
-
|
|
52
|
+
renderDenyFallback: DenyFallbackRenderer;
|
|
60
53
|
buildManifest: BuildManifest;
|
|
61
54
|
globalError?: { load: () => Promise<unknown>; filePath: string };
|
|
62
55
|
}
|
|
@@ -78,7 +71,7 @@ export async function renderRoute(
|
|
|
78
71
|
deps: RenderRouteDeps,
|
|
79
72
|
interception?: InterceptionContext
|
|
80
73
|
): Promise<Response> {
|
|
81
|
-
const { clientBootstrap, clientJsDisabled,
|
|
74
|
+
const { clientBootstrap, clientJsDisabled, buildManifest, globalError } = deps;
|
|
82
75
|
const segments = match.segments;
|
|
83
76
|
const leaf = segments[segments.length - 1];
|
|
84
77
|
|
|
@@ -113,19 +106,16 @@ export async function renderRoute(
|
|
|
113
106
|
buildManifest.metadataRouteHashes
|
|
114
107
|
);
|
|
115
108
|
} catch (error) {
|
|
116
|
-
//
|
|
117
|
-
//
|
|
118
|
-
//
|
|
119
|
-
//
|
|
120
|
-
|
|
121
|
-
return renderNoMatchPage(req, rootSegment, responseHeaders, clientBootstrap);
|
|
122
|
-
}
|
|
123
|
-
// No PageComponent found — same treatment as param coercion: render custom 404.
|
|
109
|
+
// No PageComponent found — render the app's 404 page as for an
|
|
110
|
+
// unmatched URL: the root chain, not the matched one. No access.ts has
|
|
111
|
+
// run for the matched chain yet, so its layouts must not wrap the page
|
|
112
|
+
// (design/13-security.md). The deny fallback is the one assembler of
|
|
113
|
+
// that page; calling it with no match selects the root chain.
|
|
124
114
|
if (error instanceof NoPageComponentError) {
|
|
125
115
|
if (process.env.NODE_ENV !== 'production') {
|
|
126
116
|
console.warn(`[timber] ${error.message}`);
|
|
127
117
|
}
|
|
128
|
-
return
|
|
118
|
+
return deps.renderDenyFallback(new DenySignal(404), req, responseHeaders);
|
|
129
119
|
}
|
|
130
120
|
throw error;
|
|
131
121
|
}
|
|
@@ -205,67 +195,12 @@ export async function renderRoute(
|
|
|
205
195
|
desc: 'RSC stream init',
|
|
206
196
|
});
|
|
207
197
|
|
|
208
|
-
// Synchronous redirect — redirect() in access.ts or a non-async component
|
|
209
|
-
// throws during renderToReadableStream creation. Return HTTP redirect.
|
|
210
|
-
if (signals.redirectSignal) {
|
|
211
|
-
return buildRedirectResponse(signals.redirectSignal, req, responseHeaders);
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// Synchronous deny — deny() in a non-async component throws during
|
|
215
|
-
// renderToReadableStream creation, caught in the try/catch above.
|
|
216
|
-
if (signals.denySignal) {
|
|
217
|
-
if (isRscRequest(req)) {
|
|
218
|
-
return renderDenyPageAsRsc(
|
|
219
|
-
signals.denySignal,
|
|
220
|
-
segments,
|
|
221
|
-
layoutComponents as LayoutEntry[],
|
|
222
|
-
req,
|
|
223
|
-
responseHeaders,
|
|
224
|
-
getFirstDeniedSegmentIndex()
|
|
225
|
-
);
|
|
226
|
-
}
|
|
227
|
-
return renderDenyPage(
|
|
228
|
-
signals.denySignal,
|
|
229
|
-
segments,
|
|
230
|
-
layoutComponents as LayoutEntry[],
|
|
231
|
-
req,
|
|
232
|
-
match,
|
|
233
|
-
responseHeaders,
|
|
234
|
-
clientBootstrap,
|
|
235
|
-
callSsr,
|
|
236
|
-
undefined,
|
|
237
|
-
getFirstDeniedSegmentIndex()
|
|
238
|
-
);
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
// Synchronous render error — renderToReadableStream threw before
|
|
242
|
-
// creating the stream. Render the error page with correct 5xx status.
|
|
243
|
-
// (Async render errors are tracked in onError and handled after SSR.)
|
|
244
|
-
// An RSC payload request gets the hard-navigate envelope rather than an
|
|
245
|
-
// error page — `renderErrorPage` owns that branch, so every one of its call
|
|
246
|
-
// sites is covered rather than this one alone (TIM-1322).
|
|
247
|
-
if (signals.renderError && !rscStream) {
|
|
248
|
-
return renderErrorPage(
|
|
249
|
-
signals.renderError.error,
|
|
250
|
-
signals.renderError.status,
|
|
251
|
-
segments,
|
|
252
|
-
layoutComponents as LayoutEntry[],
|
|
253
|
-
req,
|
|
254
|
-
match,
|
|
255
|
-
responseHeaders,
|
|
256
|
-
clientBootstrap,
|
|
257
|
-
globalError,
|
|
258
|
-
getFirstDeniedSegmentIndex()
|
|
259
|
-
);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
198
|
// For RSC payload requests (client navigation), return the RSC Flight
|
|
263
199
|
// stream directly — skip SSR HTML rendering entirely.
|
|
264
200
|
// See design/19-client-navigation.md §"RSC Payload Handling"
|
|
265
201
|
if (isRscRequest(req)) {
|
|
266
202
|
return buildRscPayloadResponse(
|
|
267
|
-
|
|
268
|
-
rscStream!,
|
|
203
|
+
rscStream,
|
|
269
204
|
signals,
|
|
270
205
|
segments,
|
|
271
206
|
layoutComponents,
|
|
@@ -278,7 +213,7 @@ export async function renderRoute(
|
|
|
278
213
|
// Pipe through SSR for HTML rendering with streaming Suspense support.
|
|
279
214
|
return renderSsrResponse({
|
|
280
215
|
req,
|
|
281
|
-
rscStream
|
|
216
|
+
rscStream,
|
|
282
217
|
signals,
|
|
283
218
|
segments,
|
|
284
219
|
layoutComponents,
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Render signals — the deny / redirect / unhandled-error state one RSC
|
|
3
|
+
* render captures, and the recorder that writes it.
|
|
4
|
+
*
|
|
5
|
+
* Kept apart from `rsc-stream.ts` so the contract carries no Flight runtime:
|
|
6
|
+
* consumers and tests can hold signals without loading the renderer.
|
|
7
|
+
*
|
|
8
|
+
* Design docs: 02-rendering-pipeline.md §"Single-Pass Rendering",
|
|
9
|
+
* 49-explicit-subsystem-boundaries.md §"C"
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type { DenySignal, RedirectSignal } from '../primitives.ts';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Signal state captured during RSC rendering. Read-only for consumers: only
|
|
16
|
+
* the render that produced it records into it (`createSignalRecorder`).
|
|
17
|
+
*
|
|
18
|
+
* Signals fire asynchronously via `onError` during stream consumption.
|
|
19
|
+
* The first deny wins; a later redirect replaces an earlier one.
|
|
20
|
+
*
|
|
21
|
+
* The two notification channels are values the producer owns and returns,
|
|
22
|
+
* not callback slots a consumer assigns after the fact. A slot only works if
|
|
23
|
+
* no `await` separates `renderRscStream()` from the assignment — add one and
|
|
24
|
+
* an early signal fires into an empty slot with no trace. A promise that has
|
|
25
|
+
* already resolved, and an `AbortSignal` that is already aborted, carry the
|
|
26
|
+
* early event to a late reader.
|
|
27
|
+
*/
|
|
28
|
+
export interface RenderSignals {
|
|
29
|
+
readonly denySignal: DenySignal | null;
|
|
30
|
+
/**
|
|
31
|
+
* The first deny that no in-tree catch site could place — no `owners`, so
|
|
32
|
+
* no boundary may claim its error row and only the re-render fallback can
|
|
33
|
+
* produce a page for it.
|
|
34
|
+
*
|
|
35
|
+
* Tracked apart from `denySignal` because one render can produce both. A
|
|
36
|
+
* deep page can hoist a 404 to a boundary that will render it while an
|
|
37
|
+
* outer layout separately throws a 403 nothing matches; whichever lands in
|
|
38
|
+
* `denySignal` first, the unplaced one still needs the fallback, and
|
|
39
|
+
* deciding from `denySignal.owners` alone would strand it. See TIM-1356.
|
|
40
|
+
*/
|
|
41
|
+
readonly unplacedDeny: DenySignal | null;
|
|
42
|
+
readonly redirectSignal: RedirectSignal | null;
|
|
43
|
+
/**
|
|
44
|
+
* Resolves when the first deny or redirect is captured; never rejects.
|
|
45
|
+
* Consumers race it to react the instant `onError` fires instead of
|
|
46
|
+
* polling with setTimeout/queueMicrotask.
|
|
47
|
+
*/
|
|
48
|
+
readonly captured: Promise<void>;
|
|
49
|
+
/**
|
|
50
|
+
* Aborted when the first unhandled (non-signal) error is captured. Halts
|
|
51
|
+
* Flight data injection into the inline stream (TIM-938).
|
|
52
|
+
*/
|
|
53
|
+
readonly unhandledError: AbortSignal;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** The write side of `RenderSignals`, held by the render that captures. */
|
|
57
|
+
export interface SignalRecorder {
|
|
58
|
+
readonly signals: RenderSignals;
|
|
59
|
+
deny(signal: DenySignal): void;
|
|
60
|
+
redirect(signal: RedirectSignal): void;
|
|
61
|
+
unhandledError(): void;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Create the signal state for one render. `renderRscStream()` records into
|
|
66
|
+
* it from Flight's `onError`; tests record into it to stand in for Flight.
|
|
67
|
+
*/
|
|
68
|
+
export function createSignalRecorder(): SignalRecorder {
|
|
69
|
+
let denySignal: DenySignal | null = null;
|
|
70
|
+
let unplacedDeny: DenySignal | null = null;
|
|
71
|
+
let redirectSignal: RedirectSignal | null = null;
|
|
72
|
+
let notifyCaptured!: () => void;
|
|
73
|
+
const captured = new Promise<void>((resolve) => {
|
|
74
|
+
notifyCaptured = resolve;
|
|
75
|
+
});
|
|
76
|
+
const errorAbort = new AbortController();
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
signals: {
|
|
80
|
+
get denySignal() {
|
|
81
|
+
return denySignal;
|
|
82
|
+
},
|
|
83
|
+
get unplacedDeny() {
|
|
84
|
+
return unplacedDeny;
|
|
85
|
+
},
|
|
86
|
+
get redirectSignal() {
|
|
87
|
+
return redirectSignal;
|
|
88
|
+
},
|
|
89
|
+
captured,
|
|
90
|
+
unhandledError: errorAbort.signal,
|
|
91
|
+
},
|
|
92
|
+
deny(signal) {
|
|
93
|
+
// First-wins: two concurrent denies from separately serialized
|
|
94
|
+
// subtrees must commit a deterministic status. See
|
|
95
|
+
// spike-TIM-1441 §"two-concurrent-denials scenario".
|
|
96
|
+
denySignal ??= signal;
|
|
97
|
+
if (!signal.owners) unplacedDeny ??= signal;
|
|
98
|
+
notifyCaptured();
|
|
99
|
+
},
|
|
100
|
+
redirect(signal) {
|
|
101
|
+
redirectSignal = signal;
|
|
102
|
+
notifyCaptured();
|
|
103
|
+
},
|
|
104
|
+
unhandledError() {
|
|
105
|
+
errorAbort.abort();
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
}
|
|
@@ -30,34 +30,25 @@ import { stringifyCookie } from 'cookie';
|
|
|
30
30
|
|
|
31
31
|
import type { BuildManifest } from '../build-manifest.ts';
|
|
32
32
|
import { canonicalize } from '../canonicalize.ts';
|
|
33
|
-
import { getCookiesForSsr
|
|
33
|
+
import { getCookiesForSsr } from '../cookie-context.ts';
|
|
34
34
|
import { logRenderError } from '../logger.ts';
|
|
35
|
+
import { ParamCoercionError } from '../param-coercion.ts';
|
|
35
36
|
import type { RouteMatch, RouteMatcher } from '../pipeline.ts';
|
|
36
37
|
import { DenySignal, RedirectSignal } from '../primitives.ts';
|
|
37
38
|
import { applyRequestHeaderOverlay, setSegmentParams } from '../request-context.ts';
|
|
38
39
|
import { requestContextAls } from '../als-registry.ts';
|
|
39
40
|
import { buildRouteElement } from '../route-element-builder.ts';
|
|
40
|
-
import
|
|
41
|
+
import { createReactCacheScope } from '../react-cache-scope.ts';
|
|
42
|
+
import {
|
|
43
|
+
RevalidationDropped,
|
|
44
|
+
type RevalidateRenderer,
|
|
45
|
+
type RevalidationResult,
|
|
46
|
+
} from '../actions.ts';
|
|
47
|
+
import type { CoercedParams } from '../../shared/param-value.ts';
|
|
41
48
|
|
|
42
|
-
import { runMiddlewareForAction
|
|
49
|
+
import { runMiddlewareForAction } from './action-middleware-runner.ts';
|
|
43
50
|
import { RSC_CONTENT_TYPE } from '../../shared/rsc-media-type.ts';
|
|
44
51
|
|
|
45
|
-
/**
|
|
46
|
-
* Sentinel thrown when revalidation cannot proceed because middleware
|
|
47
|
-
* returned a short-circuit `Response` (a non-redirect HTTP response that
|
|
48
|
-
* we cannot translate back to an element tree). `executeAction` catches
|
|
49
|
-
* this and drops the revalidation — the action result is still delivered,
|
|
50
|
-
* but no `_tree` is piggybacked onto the response. The matching name
|
|
51
|
-
* `RevalidationDropped` is exported so callers can identify it via
|
|
52
|
-
* `instanceof` without leaking the message text to clients.
|
|
53
|
-
*/
|
|
54
|
-
export class RevalidationDropped extends Error {
|
|
55
|
-
constructor(message: string) {
|
|
56
|
-
super(message);
|
|
57
|
-
this.name = 'RevalidationDropped';
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
52
|
/** Result of validating a `revalidatePath()` argument. */
|
|
62
53
|
type PathValidation =
|
|
63
54
|
| { ok: true; pathname: string; search: string }
|
|
@@ -137,6 +128,9 @@ function serializeCookieMap(cookies: Map<string, string>): string {
|
|
|
137
128
|
}
|
|
138
129
|
}
|
|
139
130
|
|
|
131
|
+
/** Coerce a matched route's raw segment params via its `app/schema.ts` codecs. */
|
|
132
|
+
export type CoerceSegmentParamsFn = (match: RouteMatch) => Promise<CoercedParams>;
|
|
133
|
+
|
|
140
134
|
/** Dependencies for the revalidate renderer factory. */
|
|
141
135
|
export interface RevalidateRendererDeps {
|
|
142
136
|
matchRoute: RouteMatcher;
|
|
@@ -150,7 +144,7 @@ export interface RevalidateRendererDeps {
|
|
|
150
144
|
* The returned renderer:
|
|
151
145
|
* 1. Validates the requested path.
|
|
152
146
|
* 2. Matches the canonicalized path against the route tree.
|
|
153
|
-
* 3. Coerces segment params via the
|
|
147
|
+
* 3. Coerces segment params via the `app/schema.ts` codecs.
|
|
154
148
|
* 4. Runs the matched route's `middleware.ts` chain inside a fresh
|
|
155
149
|
* `runWithRequestContext` scope (via `runMiddlewareForAction`).
|
|
156
150
|
* Deny/redirect signals are re-thrown so `executeAction` can apply
|
|
@@ -222,9 +216,13 @@ export function createRevalidateRendererFactory(
|
|
|
222
216
|
// Only attempt this inside a request context — `getCookiesForSsr`
|
|
223
217
|
// throws otherwise — and bail out gracefully if no context is
|
|
224
218
|
// active (the legacy call-site contract permitted this).
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
219
|
+
//
|
|
220
|
+
// The same map becomes the middleware scope's parsed cookies, so
|
|
221
|
+
// its `runWithRequestContext` skips `parseCookieHeader` — the H-3
|
|
222
|
+
// smuggling primitive mitigated by TIM-868. The Cookie header stays
|
|
223
|
+
// for code that reads `ctx.req.headers.get('cookie')` directly.
|
|
224
|
+
const ryw = requestContextAls.getStore() ? getCookiesForSsr() : undefined;
|
|
225
|
+
if (ryw) {
|
|
228
226
|
if (ryw.size === 0) {
|
|
229
227
|
revalidateHeaders.delete('cookie');
|
|
230
228
|
} else {
|
|
@@ -234,20 +232,29 @@ export function createRevalidateRendererFactory(
|
|
|
234
232
|
const revalidateReq = new Request(revalidateUrl.toString(), {
|
|
235
233
|
headers: revalidateHeaders,
|
|
236
234
|
});
|
|
237
|
-
// Seed the parsed map directly so the child `runWithRequestContext`
|
|
238
|
-
// inside `runMiddlewareForAction` skips `parseCookieHeader` — the
|
|
239
|
-
// same H-3 smuggling primitive mitigated by TIM-868. The Cookie
|
|
240
|
-
// header above remains in place for code that reads
|
|
241
|
-
// `ctx.req.headers.get('cookie')` directly.
|
|
242
|
-
if (inRequestContext) {
|
|
243
|
-
seedRequestCookies(revalidateReq, new Map(ryw));
|
|
244
|
-
}
|
|
245
235
|
|
|
246
|
-
// ── 3. Match the canonical path
|
|
247
|
-
|
|
248
|
-
|
|
236
|
+
// ── 3. Match the canonical path and coerce its params ───────────
|
|
237
|
+
//
|
|
238
|
+
// Coercion runs before middleware, as in the page pipeline, and on
|
|
239
|
+
// both branches below. The match keeps its raw params beside the
|
|
240
|
+
// coerced ones, so slot resolution in step 6 reads URL values.
|
|
241
|
+
const rawMatch = deps.matchRoute(validation.pathname);
|
|
242
|
+
if (!rawMatch) {
|
|
249
243
|
throw new Error(`revalidatePath('${path}') — no matching route`);
|
|
250
244
|
}
|
|
245
|
+
let match: RouteMatch;
|
|
246
|
+
try {
|
|
247
|
+
match = { ...rawMatch, segmentParams: await deps.coerceSegmentParams(rawMatch) };
|
|
248
|
+
} catch (error) {
|
|
249
|
+
// Bad params on the target path — drop revalidation. The action's
|
|
250
|
+
// own response still goes back to the client.
|
|
251
|
+
if (error instanceof ParamCoercionError) {
|
|
252
|
+
throw new RevalidationDropped(
|
|
253
|
+
`revalidatePath('${path}') — segment param coercion failed`
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
throw error;
|
|
257
|
+
}
|
|
251
258
|
|
|
252
259
|
// ── 4. Run middleware in a fresh ALS scope ──────────────────────
|
|
253
260
|
//
|
|
@@ -256,25 +263,22 @@ export function createRevalidateRendererFactory(
|
|
|
256
263
|
// overlay) — matching the page pipeline's behavior in
|
|
257
264
|
// `handleRequest` where `runMiddlewarePhase` is gated on
|
|
258
265
|
// `middlewareChain.length > 0`.
|
|
266
|
+
//
|
|
267
|
+
// The scope opened here is fresh — the action body read through its
|
|
268
|
+
// own scope before it mutated — and the revalidated tree renders in it
|
|
269
|
+
// later, so this middleware shares React.cache with that render.
|
|
270
|
+
const reactCacheScope = createReactCacheScope();
|
|
259
271
|
let overlay: Headers | undefined;
|
|
260
272
|
if (match.middlewareChain.length > 0) {
|
|
261
|
-
const outcome = await runMiddlewareForAction(
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
);
|
|
273
|
+
const outcome = await runMiddlewareForAction(revalidateReq, match, {
|
|
274
|
+
reactCacheScope,
|
|
275
|
+
cookies: ryw,
|
|
276
|
+
});
|
|
266
277
|
|
|
267
|
-
if (outcome.kind === 'param-coercion-error') {
|
|
268
|
-
// Bad params on the target path — drop revalidation. The
|
|
269
|
-
// action's own response still goes back to the client.
|
|
270
|
-
throw new RevalidationDropped(
|
|
271
|
-
`revalidatePath('${path}') — segment param coercion failed`
|
|
272
|
-
);
|
|
273
|
-
}
|
|
274
278
|
if (outcome.kind === 'error') {
|
|
275
|
-
// Re-throw unhandled middleware errors so `executeAction`
|
|
276
|
-
//
|
|
277
|
-
//
|
|
279
|
+
// Re-throw unhandled middleware errors so `executeAction` logs
|
|
280
|
+
// them and the action handler reports them. Not surfaced to the
|
|
281
|
+
// action client (revalidation is best-effort).
|
|
278
282
|
throw outcome.error;
|
|
279
283
|
}
|
|
280
284
|
if (outcome.kind === 'redirect') {
|
|
@@ -311,15 +315,9 @@ export function createRevalidateRendererFactory(
|
|
|
311
315
|
}
|
|
312
316
|
|
|
313
317
|
// `continue` — capture the overlay so we can apply it to the
|
|
314
|
-
// action's request-context store below.
|
|
315
|
-
//
|
|
316
|
-
// see the module docstring for why.
|
|
318
|
+
// action's request-context store below. Cookies the middleware set
|
|
319
|
+
// are not forwarded; see this factory's docstring for why.
|
|
317
320
|
overlay = outcome.overlay;
|
|
318
|
-
} else {
|
|
319
|
-
// No middleware on the target — still coerce params so segment
|
|
320
|
-
// params reach `setSegmentParams` typed. `runMiddlewareForAction`
|
|
321
|
-
// would have done this for us; do it manually on the bypass path.
|
|
322
|
-
await deps.coerceSegmentParams(match);
|
|
323
321
|
}
|
|
324
322
|
|
|
325
323
|
// ── 5. Lift state onto the action's ALS store ───────────────────
|
|
@@ -344,6 +342,7 @@ export function createRevalidateRendererFactory(
|
|
|
344
342
|
);
|
|
345
343
|
return {
|
|
346
344
|
payload: routeResult.payload,
|
|
345
|
+
reactCacheScope,
|
|
347
346
|
};
|
|
348
347
|
};
|
|
349
348
|
};
|
|
@@ -19,19 +19,16 @@
|
|
|
19
19
|
* 04-authorization.md §"Status codes on the RSC payload path"
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
import type { LayoutEntry } from '../deny-renderer.ts';
|
|
23
|
-
import { renderDenyPageAsRsc } from '../deny-renderer.ts';
|
|
24
|
-
import type { RedirectSignal } from '../primitives.ts';
|
|
25
22
|
import type { LayoutComponentEntry } from '../route-element-builder.ts';
|
|
26
23
|
import type { ManifestSegmentNode } from '../route-matcher.ts';
|
|
27
24
|
import type { SlotSkipEntry } from '../slot-resolver.ts';
|
|
28
25
|
|
|
29
|
-
import {
|
|
26
|
+
import { buildSegmentInfo } from './helpers.ts';
|
|
30
27
|
import { RSC_CONTENT_TYPE } from '../../shared/rsc-media-type.ts';
|
|
31
28
|
|
|
32
29
|
import { rscErrorEnvelope } from '../rsc-error-envelope.ts';
|
|
33
30
|
|
|
34
|
-
import type { RenderSignals } from './
|
|
31
|
+
import type { RenderSignals } from './render-signals.ts';
|
|
35
32
|
|
|
36
33
|
/**
|
|
37
34
|
* Ceiling on waiting for a first chunk that is already in flight, used only
|
|
@@ -55,14 +52,17 @@ const FIRST_CHUNK_CEILING_MS = 50;
|
|
|
55
52
|
* plus one macrotask turn. Nothing is held for it. A signal that lands
|
|
56
53
|
* inside the window still gets a server-level answer — a redirect response,
|
|
57
54
|
* the fallback deny page, the hard-navigate envelope — because the race
|
|
58
|
-
* below and the one timer turn after it deliver it for free.
|
|
55
|
+
* below and the one timer turn after it deliver it for free. This function
|
|
56
|
+
* reports that signal rather than answering it: it cancels the stream and
|
|
57
|
+
* rethrows, and the pipeline's outcome translator builds the redirect or
|
|
58
|
+
* calls the deny fallback (`rsc-entry/deny-fallback.ts`), exactly as for a
|
|
59
|
+
* signal thrown out of render (design/49 §"C"). A signal that
|
|
59
60
|
* lands after it is a row in the stream, and the client's boundaries answer
|
|
60
61
|
* it. Waiting for the shell components to settle (TIM-1045, TIM-1208) made
|
|
61
62
|
* the payload path pretend to a status contract it could not keep for
|
|
62
63
|
* nested components, and was removed in TIM-1495.
|
|
63
64
|
*/
|
|
64
65
|
export async function buildRscPayloadResponse(
|
|
65
|
-
req: Request,
|
|
66
66
|
rscStream: ReadableStream<Uint8Array>,
|
|
67
67
|
signals: RenderSignals,
|
|
68
68
|
segments: ManifestSegmentNode[],
|
|
@@ -73,8 +73,8 @@ export async function buildRscPayloadResponse(
|
|
|
73
73
|
): Promise<Response> {
|
|
74
74
|
// Read the first chunk from the RSC stream before committing headers.
|
|
75
75
|
// Race the first read against signal detection — if an async component
|
|
76
|
-
// throws a RedirectSignal or DenySignal, the onError callback
|
|
77
|
-
// signals.
|
|
76
|
+
// throws a RedirectSignal or DenySignal, the onError callback resolves
|
|
77
|
+
// signals.captured and we can react immediately without waiting for
|
|
78
78
|
// the full macrotask queue.
|
|
79
79
|
//
|
|
80
80
|
// The rejection chain for an async-wrapped page component:
|
|
@@ -88,9 +88,6 @@ export async function buildRscPayloadResponse(
|
|
|
88
88
|
// (no signal). A 50ms ceiling timeout guards against edge cases
|
|
89
89
|
// where onError never fires.
|
|
90
90
|
const reader = rscStream.getReader();
|
|
91
|
-
const signalDetected = new Promise<void>((resolve) => {
|
|
92
|
-
signals.onSignal = resolve;
|
|
93
|
-
});
|
|
94
91
|
|
|
95
92
|
type RaceResult =
|
|
96
93
|
| { type: 'data'; chunk: ReadableStreamReadResult<Uint8Array> }
|
|
@@ -108,14 +105,14 @@ export async function buildRscPayloadResponse(
|
|
|
108
105
|
try {
|
|
109
106
|
first = await Promise.race([
|
|
110
107
|
pendingRead.then((chunk) => ({ type: 'data' as const, chunk })),
|
|
111
|
-
|
|
108
|
+
signals.captured.then(() => ({ type: 'signal' as const })),
|
|
112
109
|
]);
|
|
113
110
|
} catch (_readError) {
|
|
114
|
-
// RSC stream
|
|
111
|
+
// The RSC stream itself errored on first read. (A component's error is
|
|
112
|
+
// not this: it arrives as an error row in a stream that reads fine.)
|
|
115
113
|
// Return an error response so the client can hard-navigate for the
|
|
116
114
|
// SSR-rendered error page. See design/10-error-handling.md.
|
|
117
115
|
reader.cancel().catch(() => {});
|
|
118
|
-
signals.onSignal = undefined;
|
|
119
116
|
return rscErrorEnvelope(500, responseHeaders);
|
|
120
117
|
}
|
|
121
118
|
|
|
@@ -136,15 +133,14 @@ export async function buildRscPayloadResponse(
|
|
|
136
133
|
await new Promise<void>((r) => setTimeout(r, 0));
|
|
137
134
|
}
|
|
138
135
|
|
|
139
|
-
//
|
|
140
|
-
//
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
//
|
|
144
|
-
|
|
145
|
-
if (trackedRedirect) {
|
|
136
|
+
// The window has closed: signals are read once, here, and one arriving
|
|
137
|
+
// after this is a row in the stream the client answers.
|
|
138
|
+
//
|
|
139
|
+
// A redirect or an unplaced deny replaces the payload, so the stream is
|
|
140
|
+
// released before the signal is rethrown to the pipeline.
|
|
141
|
+
if (signals.redirectSignal) {
|
|
146
142
|
reader.cancel().catch(() => {});
|
|
147
|
-
|
|
143
|
+
throw signals.redirectSignal;
|
|
148
144
|
}
|
|
149
145
|
// An addressed deny needs no fallback: the payload already carries its error
|
|
150
146
|
// row, aimed at the boundary the client has mounted at that segment, which
|
|
@@ -156,47 +152,18 @@ export async function buildRscPayloadResponse(
|
|
|
156
152
|
// of them. A deny nothing could place has no boundary that may claim it, so
|
|
157
153
|
// its row would otherwise stream to a client with nothing to render it —
|
|
158
154
|
// and it needs the fallback whether or not some other deny was addressed
|
|
159
|
-
// first. See TIM-1356.
|
|
155
|
+
// first. See TIM-1356. The fallback also owns the hard-navigate answer
|
|
156
|
+
// for a deny AccessGate marked `_hardNavigate` (TIM-1363).
|
|
160
157
|
if (signals.unplacedDeny) {
|
|
161
158
|
reader.cancel().catch(() => {});
|
|
162
|
-
|
|
163
|
-
// A skipped segment whose access just flipped to deny marks the signal
|
|
164
|
-
// for hard-navigate: rendering a deny page here would execute the denied
|
|
165
|
-
// segment's protected layout and place it inside cached client chrome
|
|
166
|
-
// (TIM-1074). Return rscErrorEnvelope so the client hard-navigates for
|
|
167
|
-
// a clean full render with correct deny page placement. See TIM-1363.
|
|
168
|
-
if (signals.unplacedDeny._hardNavigate) {
|
|
169
|
-
return rscErrorEnvelope(signals.unplacedDeny.status, responseHeaders);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// Read the denied segment index from ALS — set by AccessGate during
|
|
173
|
-
// render. See TIM-1358, TIM-1365.
|
|
174
|
-
const { getFirstDeniedSegmentIndex: getDeniedIdx } = await import('../deny-boundary.ts');
|
|
175
|
-
return renderDenyPageAsRsc(
|
|
176
|
-
signals.unplacedDeny,
|
|
177
|
-
segments,
|
|
178
|
-
layoutComponents as LayoutEntry[],
|
|
179
|
-
req,
|
|
180
|
-
responseHeaders,
|
|
181
|
-
getDeniedIdx()
|
|
182
|
-
);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// Check for unhandled errors (RenderError or plain Error).
|
|
186
|
-
// These aren't redirect/deny signals but the RSC stream will be broken.
|
|
187
|
-
// Return an error response so the client can hard-navigate for the
|
|
188
|
-
// SSR-rendered error page. See design/10-error-handling.md
|
|
189
|
-
// §"Error Page Rendering for Client Navigation".
|
|
190
|
-
if (signals.renderError) {
|
|
191
|
-
reader.cancel().catch(() => {});
|
|
192
|
-
return rscErrorEnvelope(signals.renderError.status, responseHeaders);
|
|
159
|
+
throw signals.unplacedDeny;
|
|
193
160
|
}
|
|
194
161
|
|
|
195
|
-
// Extract the first chunk from the race result.
|
|
196
|
-
//
|
|
197
|
-
//
|
|
198
|
-
//
|
|
199
|
-
//
|
|
162
|
+
// Extract the first chunk from the race result. If a signal won the race,
|
|
163
|
+
// the redirect and the unplaced deny were rethrown above, so only an
|
|
164
|
+
// addressed deny reaches the second branch. The last branch is a fail-safe
|
|
165
|
+
// for a signal that is neither: it cancels the reader rather than issuing
|
|
166
|
+
// a bare read() that could hang forever on a stalled stream (TIM-519).
|
|
200
167
|
let firstRead: ReadableStreamReadResult<Uint8Array>;
|
|
201
168
|
if (first.type === 'data') {
|
|
202
169
|
firstRead = first.chunk;
|
|
@@ -219,7 +186,7 @@ export async function buildRscPayloadResponse(
|
|
|
219
186
|
// absent, and fabricating `done: true` here would produce the very empty
|
|
220
187
|
// 4xx this branch exists to prevent.
|
|
221
188
|
//
|
|
222
|
-
// Nor can it fall to
|
|
189
|
+
// Nor can it fall to the deny fallback. That renderer re-resolves from
|
|
223
190
|
// the FULL leaf chain and wraps whatever it finds, ignoring `ownerKey` —
|
|
224
191
|
// so an `/admin` denial addressed to a root `4xx.tsx` would come back as
|
|
225
192
|
// `/admin/secret/403.tsx` with the denied layouts executed, which is the
|