@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
|
@@ -18,7 +18,6 @@
|
|
|
18
18
|
* this in try/catch.
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
-
import { getCookiesForSsr, getSetCookieHeaders } from '../cookie-context.ts';
|
|
22
21
|
import {
|
|
23
22
|
applyRequestHeaderOverlay,
|
|
24
23
|
runWithRequestContext,
|
|
@@ -26,149 +25,106 @@ import {
|
|
|
26
25
|
setSegmentParams,
|
|
27
26
|
} from '../request-context.ts';
|
|
28
27
|
import { runMiddlewareChain } from '../middleware-runner.ts';
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
28
|
+
import { DenySignal, RedirectSignal } from '../primitives.ts';
|
|
29
|
+
import { isDenySignal, isRedirectSignal } from '../signal-identity.ts';
|
|
31
30
|
import type { RouteMatch } from '../pipeline.ts';
|
|
32
31
|
import type { MiddlewareContext } from '../types.ts';
|
|
33
32
|
import { requestCspNonce } from '../csp-nonce.ts';
|
|
34
|
-
|
|
35
|
-
/** Coerce a matched route's segment params via its `params.ts` codecs. */
|
|
36
|
-
export type CoerceSegmentParamsFn = (match: RouteMatch) => Promise<void>;
|
|
33
|
+
import type { ReactCacheScope } from '../react-cache-scope.ts';
|
|
37
34
|
|
|
38
35
|
/**
|
|
39
|
-
* Outcome of running
|
|
40
|
-
*
|
|
41
|
-
*
|
|
36
|
+
* Outcome of running a route's middleware chain, surfaced from the inner
|
|
37
|
+
* `runWithRequestContext` scope as a value. Its one consumer is the
|
|
38
|
+
* revalidation renderer, which turns every variant but `continue` into
|
|
39
|
+
* a thrown signal or a dropped revalidation.
|
|
42
40
|
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
* writes).
|
|
41
|
+
* Only `continue` carries state out of the scope: the request-header
|
|
42
|
+
* overlay, which the renderer applies to the action's scope so the
|
|
43
|
+
* revalidated tree sees middleware-injected headers. Cookies the chain sets
|
|
44
|
+
* stay in the inner scope and are discarded with it; see the renderer's
|
|
45
|
+
* docstring for why.
|
|
49
46
|
*/
|
|
50
47
|
export type MiddlewareOutcome =
|
|
51
|
-
| {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
signal: RedirectSignal;
|
|
65
|
-
setCookieHeaders: string[];
|
|
66
|
-
}
|
|
67
|
-
| {
|
|
68
|
-
kind: 'deny';
|
|
69
|
-
signal: DenySignal;
|
|
70
|
-
match: RouteMatch;
|
|
71
|
-
setCookieHeaders: string[];
|
|
72
|
-
}
|
|
73
|
-
| {
|
|
74
|
-
kind: 'param-coercion-error';
|
|
75
|
-
}
|
|
76
|
-
| {
|
|
77
|
-
kind: 'error';
|
|
78
|
-
error: unknown;
|
|
79
|
-
};
|
|
48
|
+
| { kind: 'continue'; overlay: Headers }
|
|
49
|
+
| { kind: 'short-circuit'; response: Response }
|
|
50
|
+
| { kind: 'redirect'; signal: RedirectSignal }
|
|
51
|
+
| { kind: 'deny'; signal: DenySignal }
|
|
52
|
+
| { kind: 'error'; error: unknown };
|
|
53
|
+
|
|
54
|
+
/** The inner request scope's inputs, besides the request itself. */
|
|
55
|
+
export interface MiddlewareScope {
|
|
56
|
+
/** The `React.cache` scope the revalidated tree will render in. */
|
|
57
|
+
reactCacheScope: ReactCacheScope;
|
|
58
|
+
/** The action's post-mutation cookies, as the inner scope's cookies. */
|
|
59
|
+
cookies?: Map<string, string>;
|
|
60
|
+
}
|
|
80
61
|
|
|
81
62
|
/**
|
|
82
63
|
* Run the matched route's middleware chain inside a fresh request-context
|
|
83
|
-
* scope, captured as a `MiddlewareOutcome` value
|
|
84
|
-
*
|
|
64
|
+
* scope, captured as a `MiddlewareOutcome` value.
|
|
65
|
+
*
|
|
66
|
+
* `match` must already carry coerced segment params: coercion runs before
|
|
67
|
+
* middleware, in the caller, as it does in the page pipeline.
|
|
85
68
|
*/
|
|
86
69
|
export async function runMiddlewareForAction(
|
|
87
70
|
req: Request,
|
|
88
71
|
match: RouteMatch,
|
|
89
|
-
|
|
72
|
+
{ reactCacheScope, cookies }: MiddlewareScope
|
|
90
73
|
): Promise<MiddlewareOutcome> {
|
|
91
|
-
return runWithRequestContext(
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
} catch (err) {
|
|
96
|
-
if (err instanceof ParamCoercionError) {
|
|
97
|
-
return { kind: 'param-coercion-error' };
|
|
98
|
-
}
|
|
99
|
-
return { kind: 'error', error: err };
|
|
100
|
-
}
|
|
101
|
-
setSegmentParams(match.segmentParams);
|
|
74
|
+
return runWithRequestContext(
|
|
75
|
+
req,
|
|
76
|
+
async (): Promise<MiddlewareOutcome> => {
|
|
77
|
+
setSegmentParams(match.segmentParams);
|
|
102
78
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
79
|
+
// ─── Build the middleware context ───────────────────────────────
|
|
80
|
+
const responseHeaders = new Headers();
|
|
81
|
+
const requestHeaderOverlay = new Headers();
|
|
82
|
+
const ctx: MiddlewareContext = {
|
|
83
|
+
req,
|
|
84
|
+
requestHeaders: requestHeaderOverlay,
|
|
85
|
+
headers: responseHeaders,
|
|
86
|
+
segmentParams: match.segmentParams,
|
|
87
|
+
// 103 Early Hints are a page-render concern — server actions are
|
|
88
|
+
// RPC and never produce HTML, so there is nothing to hint about.
|
|
89
|
+
// Provide a no-op so user middleware can call `ctx.earlyHints()`
|
|
90
|
+
// unconditionally without branching on request kind.
|
|
91
|
+
earlyHints: () => {},
|
|
92
|
+
// Same reasoning: an action response carries no inline scripts, so a
|
|
93
|
+
// nonce has nothing to stamp. Still a real value so middleware that
|
|
94
|
+
// builds its CSP header unconditionally keeps working.
|
|
95
|
+
get nonce() {
|
|
96
|
+
return requestCspNonce();
|
|
97
|
+
},
|
|
98
|
+
};
|
|
123
99
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
try {
|
|
127
|
-
let middlewareResponse: Response | undefined;
|
|
100
|
+
// ─── Run the chain ──────────────────────────────────────────────
|
|
101
|
+
setMutableCookieContext(true);
|
|
128
102
|
try {
|
|
129
|
-
middlewareResponse
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
};
|
|
103
|
+
let middlewareResponse: Response | undefined;
|
|
104
|
+
try {
|
|
105
|
+
middlewareResponse = await runMiddlewareChain(match.middlewareChain, ctx);
|
|
106
|
+
} catch (err) {
|
|
107
|
+
if (isRedirectSignal(err)) return { kind: 'redirect', signal: err };
|
|
108
|
+
if (isDenySignal(err)) return { kind: 'deny', signal: err };
|
|
109
|
+
return { kind: 'error', error: err };
|
|
137
110
|
}
|
|
138
|
-
if (isDenySignal(err)) {
|
|
139
|
-
return {
|
|
140
|
-
kind: 'deny',
|
|
141
|
-
signal: err,
|
|
142
|
-
match,
|
|
143
|
-
setCookieHeaders: getSetCookieHeaders(),
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
return { kind: 'error', error: err };
|
|
147
|
-
}
|
|
148
111
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
response: middlewareResponse,
|
|
153
|
-
setCookieHeaders: getSetCookieHeaders(),
|
|
154
|
-
};
|
|
155
|
-
}
|
|
112
|
+
if (middlewareResponse) {
|
|
113
|
+
return { kind: 'short-circuit', response: middlewareResponse };
|
|
114
|
+
}
|
|
156
115
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
116
|
+
// Middleware passed — apply the request-header overlay to the
|
|
117
|
+
// current scope so any code that might still read it within
|
|
118
|
+
// this scope sees the merged view. The overlay is also captured
|
|
119
|
+
// in the outcome so the caller can re-apply it inside the
|
|
120
|
+
// action's request-context scope (which is a separate ALS run).
|
|
121
|
+
applyRequestHeaderOverlay(requestHeaderOverlay);
|
|
163
122
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
setMutableCookieContext(false);
|
|
172
|
-
}
|
|
173
|
-
});
|
|
123
|
+
return { kind: 'continue', overlay: requestHeaderOverlay };
|
|
124
|
+
} finally {
|
|
125
|
+
setMutableCookieContext(false);
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
{ reactCacheScope, cookies }
|
|
129
|
+
);
|
|
174
130
|
}
|
|
@@ -4,15 +4,20 @@
|
|
|
4
4
|
* Runs access.ts standalone for all segments in the chain (no React render
|
|
5
5
|
* pass, no AccessGate component). Then dispatches to the route handler.
|
|
6
6
|
* See design/04-authorization.md §"Auth in API Routes".
|
|
7
|
+
*
|
|
8
|
+
* Nothing thrown here is answered here. A `deny()` or `redirect()` from
|
|
9
|
+
* `access.ts` or a method handler, and every other error, propagates to the
|
|
10
|
+
* pipeline: its deny fallback answers a route.ts match in the JSON status
|
|
11
|
+
* format, its redirect builder sends the 3xx, and its error outcome answers
|
|
12
|
+
* errors in the same JSON format. There is one translator for each, not one
|
|
13
|
+
* per route type (TIM-1537, TIM-1533).
|
|
7
14
|
*/
|
|
8
15
|
|
|
9
16
|
import { withSpan, setSpanAttribute } from '../tracing.ts';
|
|
10
17
|
import type { ManifestSegmentNode } from '../route-matcher.ts';
|
|
11
18
|
import { loadModule } from '../safe-load.ts';
|
|
12
|
-
import { isDenySignal, isRedirectSignal
|
|
19
|
+
import { isDenySignal, isRedirectSignal } from '../signal-identity.ts';
|
|
13
20
|
import { handleRouteRequest } from '../route-handler.ts';
|
|
14
|
-
import { stripHeadBody } from '../head-response.ts';
|
|
15
|
-
import { isDebug } from '../debug.ts';
|
|
16
21
|
import type { RouteModule } from '../route-handler.ts';
|
|
17
22
|
import type { RouteContext } from '../types.ts';
|
|
18
23
|
|
|
@@ -40,33 +45,27 @@ export async function handleApiRoute(
|
|
|
40
45
|
const accessMod = await loadModule(segment.access);
|
|
41
46
|
const accessFn = accessMod.default as (() => unknown) | undefined;
|
|
42
47
|
if (accessFn) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
await setSpanAttribute('timber.deny_file', error.sourceFile);
|
|
57
|
-
}
|
|
58
|
-
} else if (isRedirectSignal(error)) {
|
|
59
|
-
await setSpanAttribute('timber.result', 'redirect');
|
|
48
|
+
await withSpan(
|
|
49
|
+
'timber.access',
|
|
50
|
+
{ 'timber.segment': segment.segmentName ?? 'unknown' },
|
|
51
|
+
async () => {
|
|
52
|
+
try {
|
|
53
|
+
await accessFn();
|
|
54
|
+
await setSpanAttribute('timber.result', 'pass');
|
|
55
|
+
} catch (error) {
|
|
56
|
+
if (isDenySignal(error)) {
|
|
57
|
+
await setSpanAttribute('timber.result', 'deny');
|
|
58
|
+
await setSpanAttribute('timber.deny_status', error.status);
|
|
59
|
+
if (error.sourceFile) {
|
|
60
|
+
await setSpanAttribute('timber.deny_file', error.sourceFile);
|
|
60
61
|
}
|
|
61
|
-
|
|
62
|
+
} else if (isRedirectSignal(error)) {
|
|
63
|
+
await setSpanAttribute('timber.result', 'redirect');
|
|
62
64
|
}
|
|
65
|
+
throw error;
|
|
63
66
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
const signalResponse = await translateApiSignal(error, req, segments, responseHeaders);
|
|
67
|
-
if (signalResponse) return signalResponse;
|
|
68
|
-
throw error;
|
|
69
|
-
}
|
|
67
|
+
}
|
|
68
|
+
);
|
|
70
69
|
}
|
|
71
70
|
}
|
|
72
71
|
}
|
|
@@ -77,80 +76,5 @@ export async function handleApiRoute(
|
|
|
77
76
|
// the request-context ALS that the pipeline already populated.
|
|
78
77
|
const routeMod = await loadModule<RouteModule>(leaf.route!);
|
|
79
78
|
const ctx: RouteContext = { req, headers: responseHeaders };
|
|
80
|
-
|
|
81
|
-
return await handleRouteRequest(routeMod, ctx);
|
|
82
|
-
} catch (error) {
|
|
83
|
-
const signalResponse = await translateApiSignal(error, req, segments, responseHeaders);
|
|
84
|
-
if (signalResponse) return signalResponse;
|
|
85
|
-
throw error;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Translate a control-flow signal thrown from access.ts or a route.ts
|
|
91
|
-
* method handler into the proper API response: DenySignal → JSON status-file
|
|
92
|
-
* chain via `renderApiDeny`, RedirectSignal → bare 3xx with Location header.
|
|
93
|
-
*
|
|
94
|
-
* For HEAD requests, strip the deny body to preserve HEAD semantics — signals
|
|
95
|
-
* bypass the HEAD path in `handleRouteRequest`, so this exit needs its own
|
|
96
|
-
* call. Shares `stripHeadBody` with that path and with the pipeline exit; the
|
|
97
|
-
* pipeline applying it again downstream is a no-op (TIM-1324).
|
|
98
|
-
*
|
|
99
|
-
* Returns `null` for non-signal errors so the caller knows to rethrow.
|
|
100
|
-
*/
|
|
101
|
-
async function translateApiSignal(
|
|
102
|
-
error: unknown,
|
|
103
|
-
req: Request,
|
|
104
|
-
segments: ManifestSegmentNode[],
|
|
105
|
-
responseHeaders: Headers
|
|
106
|
-
): Promise<Response | null> {
|
|
107
|
-
if (isDenySignal(error)) {
|
|
108
|
-
return stripHeadBody(await renderApiDeny(error, segments, responseHeaders), req.method);
|
|
109
|
-
}
|
|
110
|
-
if (isRedirectSignal(error)) {
|
|
111
|
-
responseHeaders.set('Location', error.location);
|
|
112
|
-
return new Response(null, { status: error.status, headers: responseHeaders });
|
|
113
|
-
}
|
|
114
|
-
return null;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Render a deny response for an API route (route.ts).
|
|
119
|
-
*
|
|
120
|
-
* Tries JSON status file chain first. Falls back to bare JSON response.
|
|
121
|
-
* Never renders a component — API consumers get structured JSON, not HTML.
|
|
122
|
-
* See design/10-error-handling.md §"Format Selection for deny()"
|
|
123
|
-
*/
|
|
124
|
-
async function renderApiDeny(
|
|
125
|
-
deny: DenySignal,
|
|
126
|
-
segments: ManifestSegmentNode[],
|
|
127
|
-
responseHeaders: Headers
|
|
128
|
-
): Promise<Response> {
|
|
129
|
-
const { resolveStatusFile } = await import('../status-code-resolver.ts');
|
|
130
|
-
|
|
131
|
-
const resolution = resolveStatusFile(deny.status, segments, 'json');
|
|
132
|
-
if (resolution) {
|
|
133
|
-
if (isDebug() && deny.data !== undefined) {
|
|
134
|
-
console.warn(
|
|
135
|
-
`[timber] deny(${deny.status}, data) resolved to ${resolution.file.filePath}, ` +
|
|
136
|
-
`which is a static JSON file. The data argument is dropped — JSON status files ` +
|
|
137
|
-
`are returned verbatim with no interpolation. If you need the data in the ` +
|
|
138
|
-
`response, use a route handler (route.ts) that returns Response.json() directly.`
|
|
139
|
-
);
|
|
140
|
-
}
|
|
141
|
-
const mod = await loadModule(resolution.file);
|
|
142
|
-
const jsonContent = mod.default ?? mod;
|
|
143
|
-
responseHeaders.set('content-type', 'application/json; charset=utf-8');
|
|
144
|
-
return new Response(JSON.stringify(jsonContent), {
|
|
145
|
-
status: deny.status,
|
|
146
|
-
headers: responseHeaders,
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// No JSON status file — bare JSON fallback
|
|
151
|
-
responseHeaders.set('content-type', 'application/json; charset=utf-8');
|
|
152
|
-
return new Response(JSON.stringify({ error: true, status: deny.status }), {
|
|
153
|
-
status: deny.status,
|
|
154
|
-
headers: responseHeaders,
|
|
155
|
-
});
|
|
79
|
+
return handleRouteRequest(routeMod, ctx);
|
|
156
80
|
}
|
|
@@ -1,22 +1,29 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Deny fallback renderer — renders the deny page (403.tsx, 404.tsx, etc.)
|
|
3
|
-
* for DenySignals that escape from middleware or the render phase
|
|
3
|
+
* for DenySignals that escape from proxy, middleware, or the render phase,
|
|
4
|
+
* and the 404 page for a URL no route matches.
|
|
5
|
+
*
|
|
6
|
+
* This is the one module that assembles deny pages. Renderers report a
|
|
7
|
+
* captured deny by rethrowing it; the pipeline's outcome translator calls
|
|
8
|
+
* this. See design/49-explicit-subsystem-boundaries.md §"C".
|
|
4
9
|
*
|
|
5
10
|
* Extracted from index.ts (TIM-968) as a pure move. The factory captures
|
|
6
11
|
* the root segment and client bootstrap config once at handler creation;
|
|
7
|
-
* the returned function is wired into `PipelineConfig.renderDenyFallback
|
|
8
|
-
* and reused by the action-dispatch wrapper.
|
|
12
|
+
* the returned function is wired into `PipelineConfig.renderDenyFallback`.
|
|
9
13
|
*
|
|
10
14
|
* Design docs: 04-authorization.md, 10-error-handling.md
|
|
11
15
|
*/
|
|
12
16
|
|
|
13
|
-
import
|
|
17
|
+
import { getFirstDeniedSegmentIndex } from '../deny-boundary.ts';
|
|
18
|
+
import type { DefaultPageRenderer, LayoutEntry } from '../deny-renderer.ts';
|
|
14
19
|
import { renderDenyPage, renderDenyPageAsRsc } from '../deny-renderer.ts';
|
|
15
20
|
import type { ClientBootstrapConfig } from '../html-injectors.ts';
|
|
16
|
-
import {
|
|
17
|
-
import
|
|
18
|
-
import type {
|
|
19
|
-
import {
|
|
21
|
+
import { renderJsonStatusResponse } from '../json-status-response.ts';
|
|
22
|
+
import { loadFallbackModule } from '../pipeline-helpers.ts';
|
|
23
|
+
import type { RouteMatch } from '../pipeline.ts';
|
|
24
|
+
import type { DenySignal } from '../primitives.ts';
|
|
25
|
+
import { isApiRouteChain, type ManifestSegmentNode } from '../route-matcher.ts';
|
|
26
|
+
import { rscErrorEnvelope } from '../rsc-error-envelope.ts';
|
|
20
27
|
import { isRscRequest } from '../../shared/rsc-media-type.ts';
|
|
21
28
|
import { callSsr } from './ssr-bridge.ts';
|
|
22
29
|
|
|
@@ -29,30 +36,73 @@ import { callSsr } from './ssr-bridge.ts';
|
|
|
29
36
|
* route's `401.json` are picked up. Fall back to the root chain when no
|
|
30
37
|
* match is available (e.g. proxy-stage deny before route matching).
|
|
31
38
|
* See TIM-822, design/04-authorization.md, design/10-error-handling.md.
|
|
39
|
+
*
|
|
40
|
+
* The page is clamped to the denied segment exactly as the renderer clamps a
|
|
41
|
+
* captured deny: the index an AccessGate or layout recorded in request ALS
|
|
42
|
+
* bounds the status-file walk and the layout shell, so a thrown deny never
|
|
43
|
+
* selects a status file below the denial or runs the denied segment's
|
|
44
|
+
* layout. It is read here, at call time, rather than passed by the pipeline:
|
|
45
|
+
* the store is RSC-owned and the pipeline does not know it exists.
|
|
46
|
+
*
|
|
47
|
+
* The index is a position in the matched chain, so it is applied only when
|
|
48
|
+
* there is one. A proxy-phase deny arrives with no match (root-only chain),
|
|
49
|
+
* and one thrown after `await next()` shares the request store with the
|
|
50
|
+
* render it replaced — that render's denied index describes a different
|
|
51
|
+
* deny and must not clamp this one. A middleware-phase deny runs before
|
|
52
|
+
* render, so no index has been recorded. See TIM-1525, design/49-explicit-subsystem-boundaries.md §P0.
|
|
32
53
|
*/
|
|
33
54
|
export function createDenyFallbackRenderer(options: {
|
|
34
55
|
rootSegment: ManifestSegmentNode;
|
|
35
56
|
clientBootstrap: ClientBootstrapConfig;
|
|
36
|
-
}):
|
|
57
|
+
}): DenyFallbackRenderer {
|
|
37
58
|
const { rootSegment, clientBootstrap } = options;
|
|
38
|
-
return async (deny, req, responseHeaders, matchedRoute) => {
|
|
59
|
+
return async (deny, req, responseHeaders, matchedRoute, defaultPage) => {
|
|
39
60
|
const chain: ManifestSegmentNode[] = matchedRoute ? matchedRoute.segments : [rootSegment];
|
|
61
|
+
|
|
62
|
+
// A route.ts match answers in JSON whatever the Accept header says —
|
|
63
|
+
// before the RSC dispatch below, and without loading layouts it would
|
|
64
|
+
// never render. No AccessGate runs on an API route, so there is no
|
|
65
|
+
// denied-segment index to clamp to. See design/10-error-handling.md
|
|
66
|
+
// §"Format Selection for deny()".
|
|
67
|
+
//
|
|
68
|
+
// Asked of the match, not of `chain`: with no match the chain is the
|
|
69
|
+
// root alone, and an `app/route.ts` puts `route` on the root node. An
|
|
70
|
+
// unmatched URL or a proxy-phase deny is not a request to that route.
|
|
71
|
+
if (matchedRoute && isApiRouteChain(matchedRoute.segments)) {
|
|
72
|
+
return renderJsonStatusResponse(
|
|
73
|
+
req,
|
|
74
|
+
deny.status,
|
|
75
|
+
chain,
|
|
76
|
+
responseHeaders,
|
|
77
|
+
undefined,
|
|
78
|
+
deny.data
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// A skipped segment whose access just flipped to deny marks the signal
|
|
83
|
+
// for hard-navigate: rendering a deny page here would execute the denied
|
|
84
|
+
// segment's protected layout and place it inside cached client chrome
|
|
85
|
+
// (TIM-1074). The envelope makes the client hard-navigate for a clean
|
|
86
|
+
// full render with correct deny page placement. See TIM-1363.
|
|
87
|
+
if (deny._hardNavigate && isRscRequest(req)) {
|
|
88
|
+
return rscErrorEnvelope(deny.status, responseHeaders);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// A layout that fails to import or evaluate is reported, and the page is
|
|
92
|
+
// wrapped in the layouts above it: a partial chain is acceptable, a deny
|
|
93
|
+
// page taken down by its layout is not. Nothing below the failure is
|
|
94
|
+
// wrapped, so a deeper layout never renders without its parent.
|
|
40
95
|
const layoutComponents: LayoutEntry[] = [];
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
96
|
+
for (const segment of chain) {
|
|
97
|
+
if (!segment.layout) continue;
|
|
98
|
+
const mod = await loadFallbackModule(segment.layout, req, chain);
|
|
99
|
+
if (!mod) break;
|
|
100
|
+
if (mod.default) {
|
|
101
|
+
layoutComponents.push({
|
|
102
|
+
component: mod.default as (...args: unknown[]) => unknown,
|
|
103
|
+
segment,
|
|
104
|
+
});
|
|
51
105
|
}
|
|
52
|
-
} catch (layoutError) {
|
|
53
|
-
// Layout failed to load — proceed without it. Partial layout chains
|
|
54
|
-
// are acceptable; the deny renderer wraps in whatever loaded.
|
|
55
|
-
logRenderError({ method: req.method, path: new URL(req.url).pathname, error: layoutError });
|
|
56
106
|
}
|
|
57
107
|
// Reuse the matched route's params/middleware metadata when present so
|
|
58
108
|
// downstream rendering sees the real route shape. Otherwise synthesise
|
|
@@ -60,6 +110,7 @@ export function createDenyFallbackRenderer(options: {
|
|
|
60
110
|
const match: RouteMatch = matchedRoute ?? {
|
|
61
111
|
segments: chain,
|
|
62
112
|
segmentParams: {},
|
|
113
|
+
rawSegmentParams: {},
|
|
63
114
|
middlewareChain: [],
|
|
64
115
|
};
|
|
65
116
|
// For client navigation (Accept: text/x-component), the timber router
|
|
@@ -67,8 +118,9 @@ export function createDenyFallbackRenderer(options: {
|
|
|
67
118
|
// decoder breaks navigation, so dispatch to the RSC renderer when the
|
|
68
119
|
// request is an RSC payload request — mirroring the normal render path.
|
|
69
120
|
// See design/19-client-navigation.md §"RSC Payload Handling" and TIM-823.
|
|
121
|
+
const deniedIndex = matchedRoute ? getFirstDeniedSegmentIndex() : Infinity;
|
|
70
122
|
if (isRscRequest(req)) {
|
|
71
|
-
return renderDenyPageAsRsc(deny, chain, layoutComponents, req, responseHeaders);
|
|
123
|
+
return renderDenyPageAsRsc(deny, chain, layoutComponents, req, responseHeaders, deniedIndex);
|
|
72
124
|
}
|
|
73
125
|
return renderDenyPage(
|
|
74
126
|
deny,
|
|
@@ -78,7 +130,22 @@ export function createDenyFallbackRenderer(options: {
|
|
|
78
130
|
match,
|
|
79
131
|
responseHeaders,
|
|
80
132
|
clientBootstrap,
|
|
81
|
-
callSsr
|
|
133
|
+
callSsr,
|
|
134
|
+
defaultPage,
|
|
135
|
+
deniedIndex
|
|
82
136
|
);
|
|
83
137
|
};
|
|
84
138
|
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* The deny fallback. `defaultPage` replaces the framework default status
|
|
142
|
+
* page when no status file answers — the dev 404 route listing for an
|
|
143
|
+
* unmatched URL.
|
|
144
|
+
*/
|
|
145
|
+
export type DenyFallbackRenderer = (
|
|
146
|
+
deny: DenySignal,
|
|
147
|
+
req: Request,
|
|
148
|
+
responseHeaders: Headers,
|
|
149
|
+
matchedRoute?: RouteMatch,
|
|
150
|
+
defaultPage?: DefaultPageRenderer
|
|
151
|
+
) => Promise<Response>;
|