@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
|
@@ -38,11 +38,11 @@ import { createElement } from 'react';
|
|
|
38
38
|
import { requestContextAls, type RequestContextStore } from './als-registry.ts';
|
|
39
39
|
import type { CoercedParams } from '../shared/param-value.ts';
|
|
40
40
|
import type { SlotParamsRecord } from '../shared/slot-params.ts';
|
|
41
|
-
import { computeComponentCacheKey,
|
|
41
|
+
import { computeComponentCacheKey, tryCanonicalize } from './prebuilt/cache-key.ts';
|
|
42
42
|
import {
|
|
43
|
-
isChildrenSlotOutletElement,
|
|
44
43
|
resolveSlotNames,
|
|
45
44
|
prepareSlotRender,
|
|
45
|
+
withoutChildrenOutlet,
|
|
46
46
|
wrapInSlotsProvider,
|
|
47
47
|
} from './prebuilt/slots.ts';
|
|
48
48
|
import {
|
|
@@ -51,11 +51,12 @@ import {
|
|
|
51
51
|
shouldCheckKeyDiscipline,
|
|
52
52
|
} from './prebuilt/key-discipline.ts';
|
|
53
53
|
import {
|
|
54
|
+
createCaptureScope,
|
|
54
55
|
isCaptureActive,
|
|
55
56
|
noteWrapperRender,
|
|
56
|
-
|
|
57
|
-
endCapture,
|
|
57
|
+
type NestedWrapperRender,
|
|
58
58
|
} from './prebuilt/capture-state.ts';
|
|
59
|
+
import { hasRuntimeLifetime, resolveTags, warnNestingClamps } from './prebuilt/lifetime.ts';
|
|
59
60
|
import {
|
|
60
61
|
hasPrebuiltPayloadSource,
|
|
61
62
|
lookupPrebuiltPayload,
|
|
@@ -64,6 +65,10 @@ import {
|
|
|
64
65
|
} from './prebuilt/payload-source.ts';
|
|
65
66
|
import { lookupOverlay, storeOverlayEntry, overlayKey } from './prebuilt/overlay.ts';
|
|
66
67
|
import { getWaitUntil } from './waituntil-bridge.ts';
|
|
68
|
+
import { runBackgroundFlight } from './pipeline-helpers.ts';
|
|
69
|
+
import { runOutsideReactCacheScope } from './react-cache-scope.ts';
|
|
70
|
+
import { readAllBytesWithDeadline } from './stream-utils.ts';
|
|
71
|
+
import { DEFAULT_RENDER_TIMEOUT_MS } from './render-timeout.ts';
|
|
67
72
|
import { createSingleflight } from '../cache/singleflight.ts';
|
|
68
73
|
import {
|
|
69
74
|
currentInvalidationEpoch,
|
|
@@ -72,10 +77,12 @@ import {
|
|
|
72
77
|
} from '../cache/invalidation-epoch.ts';
|
|
73
78
|
|
|
74
79
|
/** Default timeout for component re-renders (overridden by renderTimeoutMs). */
|
|
75
|
-
const DEFAULT_COMPONENT_TIMEOUT_MS =
|
|
80
|
+
const DEFAULT_COMPONENT_TIMEOUT_MS = DEFAULT_RENDER_TIMEOUT_MS;
|
|
76
81
|
|
|
77
82
|
/** Singleflight for component re-renders (inline and background). */
|
|
78
|
-
let componentSingleflight = createSingleflight({
|
|
83
|
+
let componentSingleflight = createSingleflight({
|
|
84
|
+
timeoutMs: DEFAULT_COMPONENT_TIMEOUT_MS,
|
|
85
|
+
});
|
|
79
86
|
let componentTimeoutMs = DEFAULT_COMPONENT_TIMEOUT_MS;
|
|
80
87
|
|
|
81
88
|
/**
|
|
@@ -89,6 +96,14 @@ export function setComponentRefreshTimeout(timeoutMs: number): void {
|
|
|
89
96
|
|
|
90
97
|
let warnedNoWaitUntil = false;
|
|
91
98
|
|
|
99
|
+
/**
|
|
100
|
+
* (outer, inner) pairs already warned about by request-time captures.
|
|
101
|
+
* Process-wide: re-renders of a hot component repeat, and the warning is
|
|
102
|
+
* about the code, not the request. Bounded by the number of wrapped
|
|
103
|
+
* components in the app.
|
|
104
|
+
*/
|
|
105
|
+
const warnedNestingPairs = new Set<string>();
|
|
106
|
+
|
|
92
107
|
/**
|
|
93
108
|
* Options captured from the `cache.component(fn, opts)` call site.
|
|
94
109
|
*
|
|
@@ -205,12 +220,7 @@ function isSlotRenderKeyable(dataProps: Record<string, unknown>): boolean {
|
|
|
205
220
|
if (!store) return false;
|
|
206
221
|
const keyParams = resolveKeyParams(store);
|
|
207
222
|
if (keyParams === null) return false;
|
|
208
|
-
|
|
209
|
-
if (isChildrenSlotOutletElement(keyProps.children)) {
|
|
210
|
-
const { children: _children, ...rest } = keyProps;
|
|
211
|
-
keyProps = rest;
|
|
212
|
-
}
|
|
213
|
-
return computeComponentCacheKey(keyProps, keyParams) !== null;
|
|
223
|
+
return computeComponentCacheKey(withoutChildrenOutlet(dataProps), keyParams) !== null;
|
|
214
224
|
}
|
|
215
225
|
|
|
216
226
|
/** Wrap payload bytes as a single-chunk ReadableStream for the decoder. */
|
|
@@ -223,28 +233,6 @@ function bytesToStream(bytes: Uint8Array): ReadableStream<Uint8Array> {
|
|
|
223
233
|
});
|
|
224
234
|
}
|
|
225
235
|
|
|
226
|
-
/** Whether the component has a runtime lifetime (ttl or tags). */
|
|
227
|
-
function hasRuntimeLifetime(options: PrebuiltComponentOptions): boolean {
|
|
228
|
-
return options.ttl !== undefined || (options.tags !== undefined && options.tags !== null);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
/**
|
|
232
|
-
* Resolve tags from options (may be static array or function of props).
|
|
233
|
-
* Function-form tags receive DATA props only — slot props are excluded so
|
|
234
|
-
* the tags fn never sees SlotOutlet placeholders (capture paths pass
|
|
235
|
-
* placeholder-substituted props) and tags stay deterministic per key.
|
|
236
|
-
*/
|
|
237
|
-
function resolveTags(options: PrebuiltComponentOptions, props: Record<string, unknown>): string[] {
|
|
238
|
-
if (!options.tags) return [];
|
|
239
|
-
if (Array.isArray(options.tags)) return options.tags;
|
|
240
|
-
const slots = options.slots;
|
|
241
|
-
// The split cannot fail here — capture paths pass framework-built shell
|
|
242
|
-
// props — but stay total: fall back to the props as given.
|
|
243
|
-
const fnProps =
|
|
244
|
-
slots && slots.length > 0 ? (splitSlotProps(props, slots)?.dataProps ?? props) : props;
|
|
245
|
-
return options.tags(fnProps);
|
|
246
|
-
}
|
|
247
|
-
|
|
248
236
|
// ─── Slot components (TIM-1173) ──────────────────────────────────────────
|
|
249
237
|
|
|
250
238
|
/**
|
|
@@ -324,6 +312,12 @@ function getCaptureTimeoutMs(): number {
|
|
|
324
312
|
return componentTimeoutMs;
|
|
325
313
|
}
|
|
326
314
|
|
|
315
|
+
/** A request-time capture: the payload and the wrappers baked into it. */
|
|
316
|
+
interface CapturedPayload {
|
|
317
|
+
bytes: Uint8Array;
|
|
318
|
+
nested: NestedWrapperRender[];
|
|
319
|
+
}
|
|
320
|
+
|
|
327
321
|
/**
|
|
328
322
|
* Render a component in isolation and capture its flight payload bytes.
|
|
329
323
|
* Used for inline re-renders (tombstone/miss) and SWR background re-renders.
|
|
@@ -334,15 +328,19 @@ function getCaptureTimeoutMs(): number {
|
|
|
334
328
|
async function captureComponentPayload(
|
|
335
329
|
id: string,
|
|
336
330
|
component: ServerComponent,
|
|
337
|
-
props: Record<string, unknown
|
|
338
|
-
|
|
331
|
+
props: Record<string, unknown>,
|
|
332
|
+
options: PrebuiltComponentOptions
|
|
333
|
+
): Promise<CapturedPayload> {
|
|
339
334
|
const { renderToReadableStream } = requireRscFunctions();
|
|
340
335
|
const element = createElement(component as RenderableComponent, props);
|
|
341
|
-
//
|
|
342
|
-
// (bake flat into this entry) per design/45 §Nesting Semantics.
|
|
343
|
-
//
|
|
344
|
-
//
|
|
345
|
-
|
|
336
|
+
// Render inside a capture scope so nested cache.component wrappers render
|
|
337
|
+
// live (bake flat into this entry) per design/45 §Nesting Semantics. The
|
|
338
|
+
// scope is this capture's async context only — concurrent requests
|
|
339
|
+
// rendering the same or other wrapped components never see it (TIM-1536).
|
|
340
|
+
const capture = createCaptureScope(id, options, props);
|
|
341
|
+
// The first error the capture render hit, kept so a failed capture
|
|
342
|
+
// reports the component's own error rather than a stand-in.
|
|
343
|
+
let renderError: { error: unknown } | undefined;
|
|
346
344
|
|
|
347
345
|
// Key-discipline diagnostic (design/45 §Enforcement): proxy the ALS
|
|
348
346
|
// store to detect request-context reads during the capture render.
|
|
@@ -350,59 +348,31 @@ async function captureComponentPayload(
|
|
|
350
348
|
const store = requestContextAls.getStore();
|
|
351
349
|
const discipline = store && shouldCheckKeyDiscipline(id) ? createKeyDisciplineProxy(store) : null;
|
|
352
350
|
|
|
353
|
-
const doCapture =
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
timer = setTimeout(
|
|
379
|
-
() => reject(new Error(`[timber] component re-render stream read timed out`)),
|
|
380
|
-
remaining
|
|
381
|
-
);
|
|
382
|
-
}),
|
|
383
|
-
]);
|
|
384
|
-
clearTimeout(timer);
|
|
385
|
-
if (done) break;
|
|
386
|
-
chunks.push(value);
|
|
387
|
-
totalLength += value.byteLength;
|
|
388
|
-
}
|
|
389
|
-
} finally {
|
|
390
|
-
reader.cancel().catch(() => {});
|
|
391
|
-
}
|
|
392
|
-
if (renderErrored) {
|
|
393
|
-
throw new Error('[timber] component re-render produced error rows — not caching');
|
|
394
|
-
}
|
|
395
|
-
const result = new Uint8Array(totalLength);
|
|
396
|
-
let offset = 0;
|
|
397
|
-
for (const chunk of chunks) {
|
|
398
|
-
result.set(chunk, offset);
|
|
399
|
-
offset += chunk.byteLength;
|
|
400
|
-
}
|
|
401
|
-
return result;
|
|
402
|
-
} finally {
|
|
403
|
-
endCapture();
|
|
404
|
-
}
|
|
405
|
-
};
|
|
351
|
+
const doCapture = (): Promise<Uint8Array> =>
|
|
352
|
+
capture.run(async () => {
|
|
353
|
+
// Outside the request's React.cache scope: this payload is stored
|
|
354
|
+
// cross-request (and the capture is singleflight-coalesced across
|
|
355
|
+
// requests), so it must not bake in values memoized for the request
|
|
356
|
+
// that happened to trigger it. Flight gives the capture its own
|
|
357
|
+
// per-render cache instead (TIM-1529).
|
|
358
|
+
const stream: ReadableStream<Uint8Array> = runOutsideReactCacheScope(() =>
|
|
359
|
+
renderToReadableStream(element, {
|
|
360
|
+
onError(error: unknown) {
|
|
361
|
+
renderError ??= { error };
|
|
362
|
+
return '';
|
|
363
|
+
},
|
|
364
|
+
})
|
|
365
|
+
);
|
|
366
|
+
const bytes = await readAllBytesWithDeadline(
|
|
367
|
+
stream,
|
|
368
|
+
getCaptureTimeoutMs(),
|
|
369
|
+
'[timber] component re-render capture'
|
|
370
|
+
);
|
|
371
|
+
// Error rows are never cached. The component's own error is what
|
|
372
|
+
// failed, so it is what the caller logs and reports.
|
|
373
|
+
if (renderError) throw renderError.error;
|
|
374
|
+
return bytes;
|
|
375
|
+
});
|
|
406
376
|
|
|
407
377
|
const bytes = discipline
|
|
408
378
|
? await requestContextAls.run(discipline.proxy, doCapture)
|
|
@@ -412,7 +382,28 @@ async function captureComponentPayload(
|
|
|
412
382
|
emitKeyDisciplineWarning(id, discipline.accessedApis);
|
|
413
383
|
}
|
|
414
384
|
|
|
415
|
-
return bytes;
|
|
385
|
+
return { bytes, nested: capture.nestedRenders() };
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Store a captured entry in the overlay, then say which embedded
|
|
390
|
+
* components it clamps (design/45 §Nesting Semantics, TIM-1545). The
|
|
391
|
+
* warning follows the store: a capture that is discarded (aborted,
|
|
392
|
+
* invalidated mid-render, failed store) holds no clamped copy, and must
|
|
393
|
+
* not spend the pair's one warning.
|
|
394
|
+
*/
|
|
395
|
+
async function storeCapturedEntry(
|
|
396
|
+
id: string,
|
|
397
|
+
cacheKey: string,
|
|
398
|
+
captured: CapturedPayload,
|
|
399
|
+
options: PrebuiltComponentOptions,
|
|
400
|
+
tags: string[],
|
|
401
|
+
hasSeed: boolean
|
|
402
|
+
): Promise<void> {
|
|
403
|
+
await storeOverlayEntry(id, cacheKey, captured.bytes, { ttl: options.ttl, tags, hasSeed });
|
|
404
|
+
warnNestingClamps({ id, options, tags }, captured.nested, warnedNestingPairs, (m) =>
|
|
405
|
+
console.warn(m)
|
|
406
|
+
);
|
|
416
407
|
}
|
|
417
408
|
|
|
418
409
|
/**
|
|
@@ -435,7 +426,7 @@ async function inlineRerender(
|
|
|
435
426
|
try {
|
|
436
427
|
const payload = await componentSingleflight.do(sfKey, async (signal) => {
|
|
437
428
|
const startEpoch = currentInvalidationEpoch();
|
|
438
|
-
const
|
|
429
|
+
const captured = await captureComponentPayload(id, component, props, options);
|
|
439
430
|
// Skip the store if aborted (singleflight timeout) or if the
|
|
440
431
|
// key/tags were invalidated while rendering (TIM-1028 guard).
|
|
441
432
|
if (
|
|
@@ -443,13 +434,9 @@ async function inlineRerender(
|
|
|
443
434
|
hasRuntimeLifetime(options) &&
|
|
444
435
|
!wasInvalidatedSince(startEpoch, oKey, tags)
|
|
445
436
|
) {
|
|
446
|
-
await
|
|
447
|
-
ttl: options.ttl,
|
|
448
|
-
tags,
|
|
449
|
-
hasSeed,
|
|
450
|
-
});
|
|
437
|
+
await storeCapturedEntry(id, cacheKey, captured, options, tags, hasSeed);
|
|
451
438
|
}
|
|
452
|
-
return bytes;
|
|
439
|
+
return captured.bytes;
|
|
453
440
|
});
|
|
454
441
|
return await revivePayload(id, payload, outcome);
|
|
455
442
|
} catch (error) {
|
|
@@ -461,10 +448,12 @@ async function inlineRerender(
|
|
|
461
448
|
/**
|
|
462
449
|
* Snapshot the request context values needed for a background re-render.
|
|
463
450
|
* Creates a FRESH store with copied values — the original ALS store is
|
|
464
|
-
* not referenced after capture.
|
|
451
|
+
* not referenced after capture. The `Request` itself is shared, not
|
|
452
|
+
* copied: the re-render reports its failure against it.
|
|
465
453
|
*/
|
|
466
454
|
function snapshotRequestContext(store: RequestContextStore): RequestContextStore {
|
|
467
455
|
return {
|
|
456
|
+
request: store.request,
|
|
468
457
|
headers: new Headers(store.headers),
|
|
469
458
|
originalHeaders: new Headers(store.originalHeaders),
|
|
470
459
|
cookieHeader: store.cookieHeader,
|
|
@@ -499,19 +488,28 @@ function backgroundRerender(
|
|
|
499
488
|
|
|
500
489
|
const work = requestContextAls.run(snapshot, () =>
|
|
501
490
|
componentSingleflight
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
491
|
+
// The stale payload already answered the request, so nothing else sees
|
|
492
|
+
// a failure here: logged and reported once per flight. Inline re-render
|
|
493
|
+
// and revive failures are only logged: a live render answers instead.
|
|
494
|
+
.do(sfKey, (signal) =>
|
|
495
|
+
runBackgroundFlight(
|
|
496
|
+
signal,
|
|
497
|
+
async () => {
|
|
498
|
+
const captured = await captureComponentPayload(id, component, props, options);
|
|
499
|
+
if (!signal.aborted && !wasInvalidatedSince(startEpoch, oKey, tags)) {
|
|
500
|
+
await storeCapturedEntry(id, cacheKey, captured, options, tags, hasSeed);
|
|
501
|
+
}
|
|
502
|
+
},
|
|
503
|
+
(error) =>
|
|
504
|
+
console.error(
|
|
505
|
+
`[timber] cache.component background re-render failed for "${id}":`,
|
|
506
|
+
error
|
|
507
|
+
)
|
|
508
|
+
)
|
|
509
|
+
)
|
|
510
|
+
// runBackgroundFlight never rejects; only the singleflight timeout,
|
|
511
|
+
// which it already reported, can reject the flight.
|
|
512
|
+
.catch(() => {})
|
|
515
513
|
);
|
|
516
514
|
|
|
517
515
|
if (waitUntil) {
|
|
@@ -564,12 +562,10 @@ async function tryRevivePayload(
|
|
|
564
562
|
// unkey the render there any more than on the non-slot path (codex P2
|
|
565
563
|
// on PR #890).
|
|
566
564
|
const allProps = (props ?? {}) as Record<string, unknown>;
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
}
|
|
572
|
-
const cacheKey = computeComponentCacheKey(keyProps, keyParams);
|
|
565
|
+
const cacheKey = computeComponentCacheKey(
|
|
566
|
+
withoutChildrenOutlet(keyPropsOverride ?? allProps),
|
|
567
|
+
keyParams
|
|
568
|
+
);
|
|
573
569
|
if (cacheKey === null) return null;
|
|
574
570
|
|
|
575
571
|
const outcome =
|
|
@@ -717,16 +713,16 @@ export function __prebuilt<C extends ServerComponent>(
|
|
|
717
713
|
registry.set(id, { id, component, options });
|
|
718
714
|
|
|
719
715
|
const wrapper = async (props: Parameters<C>[0]) => {
|
|
720
|
-
//
|
|
721
|
-
//
|
|
722
|
-
//
|
|
723
|
-
noteWrapperRender(id, options);
|
|
716
|
+
// Report this render to the enclosing capture, if any — cycle
|
|
717
|
+
// detection (throws) and nesting-clamp warnings (design/45 §Nesting
|
|
718
|
+
// Semantics). Outside a capture this is a single store lookup.
|
|
719
|
+
noteWrapperRender(id, options, props as Record<string, unknown>);
|
|
724
720
|
if (isCaptureActive()) {
|
|
725
|
-
// Nested wrapper inside a
|
|
726
|
-
//
|
|
721
|
+
// Nested wrapper inside a capture: render live so the subtree
|
|
722
|
+
// bakes flat into the enclosing entry (design/45 §Nesting).
|
|
727
723
|
// This deliberately bypasses fallbackOnMissingSegmentParams: false —
|
|
728
724
|
// that option means "never serve non-prebuilt content", and a
|
|
729
|
-
//
|
|
725
|
+
// capture render IS the cached content; throwing here would
|
|
730
726
|
// spuriously fail the outer entry (codex P2 on PR #836).
|
|
731
727
|
return createElement(component as RenderableComponent, props as Record<string, unknown>);
|
|
732
728
|
}
|
package/src/server/primitives.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Server-side primitives: deny, redirect, redirectExternal,
|
|
1
|
+
// Server-side primitives: deny, redirect, redirectExternal, waitUntil
|
|
2
2
|
//
|
|
3
3
|
// These are the core runtime signals that components, middleware, and access gates
|
|
4
4
|
// use to control request flow. See design/10-error-handling.md.
|
|
@@ -8,6 +8,7 @@ import { getWaitUntil as _getWaitUntil } from './waituntil-bridge.ts';
|
|
|
8
8
|
import { isDebug } from './debug.ts';
|
|
9
9
|
import { getRequestSearchString } from './request-context.ts';
|
|
10
10
|
import { mergePreservedSearchParams } from '../shared/merge-search-params.ts';
|
|
11
|
+
import { DENY_BRAND, REDIRECT_BRAND } from './signal-identity.ts';
|
|
11
12
|
import {
|
|
12
13
|
assertRelativeRedirectPath,
|
|
13
14
|
validateExternalRedirectUrl,
|
|
@@ -97,71 +98,19 @@ function warnIfNotSerializable(data: unknown, callerName: string): void {
|
|
|
97
98
|
if (issue) {
|
|
98
99
|
console.warn(
|
|
99
100
|
`[timber] ${callerName}: ${issue}. ` +
|
|
100
|
-
'Data passed to deny()
|
|
101
|
+
'Data passed to deny() must be JSON-serializable because ' +
|
|
101
102
|
'the post-flush path uses JSON.stringify, not React Flight.'
|
|
102
103
|
);
|
|
103
104
|
}
|
|
104
105
|
}
|
|
105
106
|
|
|
106
|
-
// ─── Signal branding ────────────────────────────────────────────────────────
|
|
107
|
-
//
|
|
108
|
-
// Catch sites must NOT use `instanceof` on these classes. In dev, an HMR
|
|
109
|
-
// program reload clears the RSC module cache; a request that is mid-render
|
|
110
|
-
// still holds the catch sites from the old evaluation of this module while
|
|
111
|
-
// user code loaded after the reload throws from the new one. The two
|
|
112
|
-
// evaluations are distinct classes, so `instanceof` fails and a correct
|
|
113
|
-
// deny() falls through every catch site as an unhandled 500 (TIM-1499).
|
|
114
|
-
//
|
|
115
|
-
// Each class stamps a `Symbol.for` brand on its instances in the constructor.
|
|
116
|
-
// `Symbol.for` keys live in the realm-wide symbol registry, so every
|
|
117
|
-
// evaluation of this module — and every module graph in the same process —
|
|
118
|
-
// agrees on the key. The `is*` predicates below check the brand and are the
|
|
119
|
-
// only supported way to detect a signal. The classes themselves are NOT
|
|
120
|
-
// anchored on globalThis: a re-evaluated module must hand out its own
|
|
121
|
-
// (possibly updated) class, not a stale one.
|
|
122
|
-
//
|
|
123
|
-
// See design/18-build-system.md §"Dev Mode: Signal Identity Across Program Reloads".
|
|
124
|
-
|
|
125
|
-
const DENY_BRAND: unique symbol = Symbol.for('timber:signal.deny');
|
|
126
|
-
const REDIRECT_BRAND: unique symbol = Symbol.for('timber:signal.redirect');
|
|
127
|
-
const RENDER_ERROR_BRAND: unique symbol = Symbol.for('timber:signal.render-error');
|
|
128
|
-
const SSR_STREAM_ERROR_BRAND: unique symbol = Symbol.for('timber:signal.ssr-stream-error');
|
|
129
|
-
|
|
130
|
-
function hasBrand(value: unknown, brand: symbol): boolean {
|
|
131
|
-
return typeof value === 'object' && value !== null && brand in value;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/** True for any `DenySignal`, regardless of which module evaluation created it. */
|
|
135
|
-
export function isDenySignal(error: unknown): error is DenySignal {
|
|
136
|
-
return hasBrand(error, DENY_BRAND);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/** True for any `RedirectSignal`, regardless of which module evaluation created it. */
|
|
140
|
-
export function isRedirectSignal(error: unknown): error is RedirectSignal {
|
|
141
|
-
return hasBrand(error, REDIRECT_BRAND);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/** True for any `RenderError`, regardless of which module evaluation created it. */
|
|
145
|
-
export function isRenderError(error: unknown): error is RenderError {
|
|
146
|
-
return hasBrand(error, RENDER_ERROR_BRAND);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* True for any `SsrStreamError`. This one also crosses Vite environments:
|
|
151
|
-
* it is thrown in SSR and caught in RSC, which are separate module graphs in
|
|
152
|
-
* the same process — the brand is the only identity the two share.
|
|
153
|
-
*/
|
|
154
|
-
export function isSsrStreamError(error: unknown): error is SsrStreamError {
|
|
155
|
-
return hasBrand(error, SSR_STREAM_ERROR_BRAND);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
107
|
// ─── DenySignal ─────────────────────────────────────────────────────────────
|
|
159
108
|
|
|
160
109
|
/**
|
|
161
110
|
* Render-phase signal thrown by `deny()`. Caught by the framework to produce
|
|
162
111
|
* the correct HTTP status code (segment context) or graceful degradation (slot context).
|
|
163
112
|
*
|
|
164
|
-
* Detect with `isDenySignal()`, never `instanceof` — see "Signal branding"
|
|
113
|
+
* Detect with `isDenySignal()`, never `instanceof` — see "Signal branding" in signal-identity.ts.
|
|
165
114
|
*/
|
|
166
115
|
export class DenySignal extends Error {
|
|
167
116
|
readonly [DENY_BRAND] = true;
|
|
@@ -256,9 +205,9 @@ export interface DenyOptions {
|
|
|
256
205
|
* deny(404, { dangerouslyPassData: { resourceId: params.id } }) // explicit client opt-in
|
|
257
206
|
* ```
|
|
258
207
|
*
|
|
259
|
-
* Accepts any 4xx or 5xx status code
|
|
260
|
-
*
|
|
261
|
-
*
|
|
208
|
+
* Accepts any 4xx or 5xx status code — it is also how a page renders a 5xx
|
|
209
|
+
* status file with data. An unplanned throw needs no primitive: it renders
|
|
210
|
+
* the error page with a 500.
|
|
262
211
|
*
|
|
263
212
|
* @param status - HTTP status code (4xx or 5xx). Default: 403.
|
|
264
213
|
* @param options - Optional message and/or data to pass to the client.
|
|
@@ -284,7 +233,7 @@ export { RedirectType } from '../shared/redirect-type.ts';
|
|
|
284
233
|
* Render-phase signal thrown by `redirect()` and `redirectExternal()`.
|
|
285
234
|
* Caught by the framework to produce a 3xx response or client-side navigation.
|
|
286
235
|
*
|
|
287
|
-
* Detect with `isRedirectSignal()`, never `instanceof` — see "Signal branding"
|
|
236
|
+
* Detect with `isRedirectSignal()`, never `instanceof` — see "Signal branding" in signal-identity.ts.
|
|
288
237
|
*/
|
|
289
238
|
export class RedirectSignal extends Error {
|
|
290
239
|
readonly [REDIRECT_BRAND] = true;
|
|
@@ -301,33 +250,6 @@ export class RedirectSignal extends Error {
|
|
|
301
250
|
|
|
302
251
|
// ─── Signal Detection ───────────────────────────────────────────────────────
|
|
303
252
|
|
|
304
|
-
/**
|
|
305
|
-
* Returns true if the error is a framework control-flow signal (RedirectSignal
|
|
306
|
-
* or DenySignal) rather than a genuine application error. Works both for direct
|
|
307
|
-
* instances (RSC-side) and deserialized digest errors (SSR cross-boundary).
|
|
308
|
-
*
|
|
309
|
-
* See also: isFrameworkSignalError() in client/browser-dev.ts (client-only).
|
|
310
|
-
*/
|
|
311
|
-
export function isControlFlowSignal(error: unknown): boolean {
|
|
312
|
-
if (isDenySignal(error) || isRedirectSignal(error)) {
|
|
313
|
-
return true;
|
|
314
|
-
}
|
|
315
|
-
if (error && typeof error === 'object') {
|
|
316
|
-
const digest = (error as { digest?: unknown }).digest;
|
|
317
|
-
if (typeof digest === 'string') {
|
|
318
|
-
try {
|
|
319
|
-
const parsed = JSON.parse(digest) as { type?: unknown } | null;
|
|
320
|
-
if (parsed && typeof parsed === 'object') {
|
|
321
|
-
return parsed.type === 'redirect' || parsed.type === 'deny';
|
|
322
|
-
}
|
|
323
|
-
} catch {
|
|
324
|
-
// Not valid digest JSON
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
return false;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
253
|
/**
|
|
332
254
|
* Options for redirect() — alternative to passing a bare status code.
|
|
333
255
|
*/
|
|
@@ -420,61 +342,6 @@ export function redirectExternal(url: string, allowList: string[], status: numbe
|
|
|
420
342
|
throw new RedirectSignal(canonicalUrl, status);
|
|
421
343
|
}
|
|
422
344
|
|
|
423
|
-
// ─── RenderError ────────────────────────────────────────────────────────────
|
|
424
|
-
|
|
425
|
-
/**
|
|
426
|
-
* Typed digest that crosses the RSC → client boundary.
|
|
427
|
-
* The `code` identifies the error class; `data` carries JSON-serializable context.
|
|
428
|
-
*/
|
|
429
|
-
export interface RenderErrorDigest<
|
|
430
|
-
TCode extends string = string,
|
|
431
|
-
TData extends JsonSerializable = JsonSerializable,
|
|
432
|
-
> {
|
|
433
|
-
code: TCode;
|
|
434
|
-
data: TData;
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
/**
|
|
438
|
-
* Typed throw for render-phase errors that carry structured context to error boundaries.
|
|
439
|
-
*
|
|
440
|
-
* The `digest` (code + data) is serialized into the RSC stream separately from the
|
|
441
|
-
* Error instance — only the digest crosses the RSC → client boundary.
|
|
442
|
-
*
|
|
443
|
-
* @example
|
|
444
|
-
* ```ts
|
|
445
|
-
* throw new RenderError('PRODUCT_NOT_FOUND', {
|
|
446
|
-
* title: 'Product not found',
|
|
447
|
-
* resourceId: params.id,
|
|
448
|
-
* })
|
|
449
|
-
* ```
|
|
450
|
-
*
|
|
451
|
-
* Detect with `isRenderError()`, never `instanceof` — see "Signal branding" above.
|
|
452
|
-
*/
|
|
453
|
-
export class RenderError<
|
|
454
|
-
TCode extends string = string,
|
|
455
|
-
TData extends JsonSerializable = JsonSerializable,
|
|
456
|
-
> extends Error {
|
|
457
|
-
readonly [RENDER_ERROR_BRAND] = true;
|
|
458
|
-
readonly code: TCode;
|
|
459
|
-
readonly digest: RenderErrorDigest<TCode, TData>;
|
|
460
|
-
readonly status: number;
|
|
461
|
-
|
|
462
|
-
constructor(code: TCode, data: TData, options?: { status?: number }) {
|
|
463
|
-
super(`RenderError: ${code}`);
|
|
464
|
-
this.name = 'RenderError';
|
|
465
|
-
this.code = code;
|
|
466
|
-
this.digest = { code, data };
|
|
467
|
-
|
|
468
|
-
warnIfNotSerializable(data, 'RenderError');
|
|
469
|
-
|
|
470
|
-
const status = options?.status ?? 500;
|
|
471
|
-
if (status < 400 || status > 599) {
|
|
472
|
-
throw new Error(`RenderError status must be 4xx or 5xx, got ${status}.`);
|
|
473
|
-
}
|
|
474
|
-
this.status = status;
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
|
|
478
345
|
// ─── waitUntil ──────────────────────────────────────────────────────────────
|
|
479
346
|
|
|
480
347
|
// Intentional per-app singleton — warn-once flag that persists for the
|
|
@@ -515,30 +382,3 @@ export function waitUntil(promise: Promise<unknown>): void {
|
|
|
515
382
|
export function _resetWaitUntilWarning(): void {
|
|
516
383
|
_waitUntilWarned = false;
|
|
517
384
|
}
|
|
518
|
-
|
|
519
|
-
// ─── SsrStreamError ─────────────────────────────────────────────────────────
|
|
520
|
-
|
|
521
|
-
/**
|
|
522
|
-
* Error thrown when SSR's renderToReadableStream fails due to an error
|
|
523
|
-
* in the decoded RSC stream (e.g., uncontained slot errors).
|
|
524
|
-
*
|
|
525
|
-
* The RSC entry checks for this error type in its catch block to avoid
|
|
526
|
-
* re-executing server components via renderDenyPage. Instead, it renders
|
|
527
|
-
* a bare deny/error page without layout wrapping.
|
|
528
|
-
*
|
|
529
|
-
* Defined in primitives.ts (not ssr-entry.ts) because ssr-entry.ts imports
|
|
530
|
-
* react-dom/server which cannot be loaded in the RSC environment.
|
|
531
|
-
*
|
|
532
|
-
* Detect with `isSsrStreamError()` — it is thrown in the SSR environment and
|
|
533
|
-
* caught in RSC, so `instanceof` never matches. See "Signal branding" above.
|
|
534
|
-
*/
|
|
535
|
-
export class SsrStreamError extends Error {
|
|
536
|
-
readonly [SSR_STREAM_ERROR_BRAND] = true;
|
|
537
|
-
override readonly cause: unknown;
|
|
538
|
-
|
|
539
|
-
constructor(message: string, cause: unknown) {
|
|
540
|
-
super(message);
|
|
541
|
-
this.name = 'SsrStreamError';
|
|
542
|
-
this.cause = cause;
|
|
543
|
-
}
|
|
544
|
-
}
|