@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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createContext, createElement, useContext } from "react";
|
|
1
|
+
import { createContext, createElement, useContext, useMemo } from "react";
|
|
2
2
|
//#region src/client/navigation-context.ts
|
|
3
3
|
/**
|
|
4
4
|
* NavigationContext — React context for navigation state.
|
|
@@ -12,8 +12,8 @@ import { createContext, createElement, useContext } from "react";
|
|
|
12
12
|
*
|
|
13
13
|
* Segment params are NOT here — see the note on NavigationState below.
|
|
14
14
|
*
|
|
15
|
-
* By wrapping the RSC payload element in NavigationProvider inside
|
|
16
|
-
*
|
|
15
|
+
* By wrapping the RSC payload element in NavigationProvider inside the
|
|
16
|
+
* router's `renderTree` (browser-entry/router-init.ts), the context value and the element tree are passed to
|
|
17
17
|
* reactRoot.render() in the same call — atomic by construction.
|
|
18
18
|
* All consumers (usePathname, useSearchParams) see the new values in the
|
|
19
19
|
* same render pass as the new tree.
|
|
@@ -76,41 +76,13 @@ function useNavigationContext() {
|
|
|
76
76
|
/**
|
|
77
77
|
* Wraps children with NavigationContext.Provider.
|
|
78
78
|
*
|
|
79
|
-
* Used in browser-entry.ts
|
|
79
|
+
* Used in browser-entry/router-init.ts `renderTree` to wrap the RSC payload element
|
|
80
80
|
* so that navigation state updates atomically with the tree render.
|
|
81
81
|
*/
|
|
82
82
|
function NavigationProvider({ value, children }) {
|
|
83
83
|
return createElement(getOrCreateContext().Provider, { value }, children);
|
|
84
84
|
}
|
|
85
85
|
/**
|
|
86
|
-
* Navigation state communicated between the router and renderRoot.
|
|
87
|
-
*
|
|
88
|
-
* The router calls setNavigationState() before renderRoot(). The
|
|
89
|
-
* renderRoot callback reads via getNavigationState() to create the
|
|
90
|
-
* NavigationProvider with the correct params/pathname.
|
|
91
|
-
*
|
|
92
|
-
* This is NOT used by hooks directly — hooks read from React context.
|
|
93
|
-
*
|
|
94
|
-
* Stored on globalThis (like the context instances above) because the
|
|
95
|
-
* router lives in one chunk while renderRoot lives in another. Module-
|
|
96
|
-
* level variables would be separate per chunk.
|
|
97
|
-
*/
|
|
98
|
-
var NAV_STATE_KEY = Symbol.for("__timber_nav_state");
|
|
99
|
-
function _getNavStateStore() {
|
|
100
|
-
const g = globalThis;
|
|
101
|
-
if (!g[NAV_STATE_KEY]) g[NAV_STATE_KEY] = { current: {
|
|
102
|
-
pathname: "/",
|
|
103
|
-
search: ""
|
|
104
|
-
} };
|
|
105
|
-
return g[NAV_STATE_KEY];
|
|
106
|
-
}
|
|
107
|
-
function setNavigationState(state) {
|
|
108
|
-
_getNavStateStore().current = state;
|
|
109
|
-
}
|
|
110
|
-
function getNavigationState() {
|
|
111
|
-
return _getNavStateStore().current;
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
86
|
* There was a second React context here — `PendingNavigationContext`, holding
|
|
115
87
|
* the in-flight navigation URL, provided by `NavigationRoot` out of a
|
|
116
88
|
* `useState` — plus a `usePendingNavigationUrl()` reader for it. Both are gone
|
|
@@ -130,6 +102,36 @@ function getNavigationState() {
|
|
|
130
102
|
* design/19-client-navigation.md §"How Pending State Works".
|
|
131
103
|
*/
|
|
132
104
|
//#endregion
|
|
133
|
-
|
|
105
|
+
//#region src/client/segment-context.ts
|
|
106
|
+
/**
|
|
107
|
+
* Segment Context — provides layout segment position for useSelectedLayoutSegment hooks.
|
|
108
|
+
*
|
|
109
|
+
* Each layout in the segment tree is wrapped with a SegmentProvider that stores
|
|
110
|
+
* the URL segments from root to the current layout level. The hooks read this
|
|
111
|
+
* context to determine which child segments are active below the calling layout.
|
|
112
|
+
*
|
|
113
|
+
* The context value is intentionally minimal: just the segment path array and
|
|
114
|
+
* parallel route keys. No internal cache details are exposed.
|
|
115
|
+
*
|
|
116
|
+
* Design docs: design/19-client-navigation.md, design/14-ecosystem.md
|
|
117
|
+
*/
|
|
118
|
+
var SegmentContext = createContext(null);
|
|
119
|
+
/** Read the segment context. Returns null if no provider is above this component. */
|
|
120
|
+
function useSegmentContext() {
|
|
121
|
+
return useContext(SegmentContext);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Wraps each layout to provide segment position context.
|
|
125
|
+
* Injected by rsc-entry.ts during element tree construction.
|
|
126
|
+
*/
|
|
127
|
+
function SegmentProvider({ segments, segmentId: _segmentId, parallelRouteKeys, children }) {
|
|
128
|
+
const value = useMemo(() => ({
|
|
129
|
+
segments,
|
|
130
|
+
parallelRouteKeys
|
|
131
|
+
}), [segments, parallelRouteKeys]);
|
|
132
|
+
return createElement(SegmentContext.Provider, { value }, children);
|
|
133
|
+
}
|
|
134
|
+
//#endregion
|
|
135
|
+
export { useNavigationContext as i, useSegmentContext as n, NavigationProvider as r, SegmentProvider as t };
|
|
134
136
|
|
|
135
|
-
//# sourceMappingURL=
|
|
137
|
+
//# sourceMappingURL=segment-context-xtPUGfdq.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"segment-context-xtPUGfdq.js","names":[],"sources":["../../src/client/navigation-context.ts","../../src/client/segment-context.ts"],"sourcesContent":["'use client';\n\n/**\n * NavigationContext — React context for navigation state.\n *\n * Holds the current pathname and search, updated atomically with the RSC\n * tree on each navigation. This replaces the previous useSyncExternalStore\n * approach for usePathname() and useSearchParams(), which suffered from a\n * timing gap: the new tree could commit before the external store\n * re-renders fired, causing a frame where both old and new active states\n * were visible simultaneously.\n *\n * Segment params are NOT here — see the note on NavigationState below.\n *\n * By wrapping the RSC payload element in NavigationProvider inside the\n * router's `renderTree` (browser-entry/router-init.ts), the context value and the element tree are passed to\n * reactRoot.render() in the same call — atomic by construction.\n * All consumers (usePathname, useSearchParams) see the new values in the\n * same render pass as the new tree.\n *\n * During SSR, the wrapper chain mounts this same provider with the\n * request's pathname and raw search string (TIM-1424), so the hooks\n * resolve through the identical code path on both sides. Per-request\n * isolation is by construction — the value is part of the request's\n * element tree.\n *\n * This module is `'use client'` and is never evaluated in the RSC\n * environment. The shims plugin resolves next/navigation to\n * navigation-rsc.ts in RSC, which has throwing stubs (TIM-1420).\n *\n * SINGLETON GUARANTEE: All shared mutable state uses globalThis via\n * Symbol.for keys. The RSC client bundler can duplicate this module\n * across chunks (browser-entry graph + client-reference graph). With\n * ESM output, each chunk gets its own module scope — module-level\n * variables would create separate singleton instances per chunk.\n * globalThis guarantees a single instance regardless of duplication.\n *\n * This workaround will be removed when Rolldown ships `format: 'app'`\n * (module registry format that deduplicates like webpack/Turbopack).\n * See design/27-chunking-strategy.md.\n *\n * See design/19-client-navigation.md §\"NavigationContext\"\n */\n\nimport { createContext, useContext, createElement, type ReactNode } from 'react';\n\n// ---------------------------------------------------------------------------\n// Context type\n// ---------------------------------------------------------------------------\n\n/**\n * What the browser knows about the current location.\n *\n * Params are deliberately absent: they are a property of the tree the server\n * rendered, not of the address bar, and they now travel inside the payload as\n * the payload root. Keeping a copy here meant the router had to thread\n * the record from a response header into context on every path — navigation,\n * traversal, prefetch, revalidation — and each of those was a place to drop it\n * (TIM-1294).\n */\nexport interface NavigationState {\n pathname: string;\n search: string;\n}\n\n// ---------------------------------------------------------------------------\n// Lazy context initialization\n// ---------------------------------------------------------------------------\n\n/**\n * Context instances are stored on globalThis (NOT in module-level\n * variables) because the ESM bundler can duplicate this module across\n * chunks. Module-level variables would create separate instances per\n * chunk — the provider in NavigationRoot (index chunk) would use\n * context A while the consumer in usePendingNavigation (shared chunk)\n * reads from context B. globalThis guarantees a single instance.\n *\n * This module is `'use client'` so it is never evaluated in the RSC\n * environment — `createContext` and `useContext` are always available.\n * The shims plugin resolves next/navigation to navigation-rsc.ts in RSC,\n * which has throwing stubs for the hooks (TIM-1420).\n *\n * See design/27-chunking-strategy.md §\"Singleton Safety\"\n */\n\nconst NAV_CTX_KEY = Symbol.for('__timber_nav_ctx');\n\nfunction getOrCreateContext(): import('react').Context<NavigationState | null> {\n const existing = (globalThis as Record<symbol, unknown>)[NAV_CTX_KEY] as\n | import('react').Context<NavigationState | null>\n | undefined;\n if (existing !== undefined) return existing;\n const ctx = createContext<NavigationState | null>(null);\n (globalThis as Record<symbol, unknown>)[NAV_CTX_KEY] = ctx;\n return ctx;\n}\n\n/**\n * Read the navigation context. Returns null only when no provider is above\n * the caller — a component rendered outside the timber app.\n *\n * Internal — used by usePathname() and useSearchParams().\n */\nexport function useNavigationContext(): NavigationState | null {\n return useContext(getOrCreateContext());\n}\n\n// ---------------------------------------------------------------------------\n// Provider component\n// ---------------------------------------------------------------------------\n\nexport interface NavigationProviderProps {\n value: NavigationState;\n children?: ReactNode;\n}\n\n/**\n * Wraps children with NavigationContext.Provider.\n *\n * Used in browser-entry/router-init.ts `renderTree` to wrap the RSC payload element\n * so that navigation state updates atomically with the tree render.\n */\nexport function NavigationProvider({\n value,\n children,\n}: NavigationProviderProps): import('react').ReactElement {\n return createElement(getOrCreateContext().Provider, { value }, children);\n}\n\n// ---------------------------------------------------------------------------\n// Pending navigation state lives in the router, not here\n// ---------------------------------------------------------------------------\n\n/**\n * There was a second React context here — `PendingNavigationContext`, holding\n * the in-flight navigation URL, provided by `NavigationRoot` out of a\n * `useState` — plus a `usePendingNavigationUrl()` reader for it. Both are gone\n * (TIM-1307).\n *\n * Nothing read them. `usePendingNavigation()` (use-pending-navigation.ts) and\n * `TopLoader` both subscribe to the router's external pending store via\n * `useSyncExternalStore`: sync priority, immune to transition entanglement,\n * and cleared by `runNavigation`'s supersession-guarded `finally` (TIM-1034).\n * The context was a parallel representation of the same fact that no consumer\n * ever migrated to, and one that could not even agree with the store — a\n * navigation superseded by a cached popstate replay left its URL set until the\n * next full navigation, because the staleness guard skipped the clear and no\n * other path touched it.\n *\n * One representation, and it is the router's. See\n * design/19-client-navigation.md §\"How Pending State Works\".\n */\n","/**\n * Segment Context — provides layout segment position for useSelectedLayoutSegment hooks.\n *\n * Each layout in the segment tree is wrapped with a SegmentProvider that stores\n * the URL segments from root to the current layout level. The hooks read this\n * context to determine which child segments are active below the calling layout.\n *\n * The context value is intentionally minimal: just the segment path array and\n * parallel route keys. No internal cache details are exposed.\n *\n * Design docs: design/19-client-navigation.md, design/14-ecosystem.md\n */\n\n'use client';\n\nimport { createContext, useContext, createElement, useMemo } from 'react';\n\n// ─── Types ───────────────────────────────────────────────────────\n\nexport interface SegmentContextValue {\n /** URL segments from root to this layout (e.g. ['', 'dashboard', 'settings']) */\n segments: string[];\n /** Parallel route slot keys available at this layout level (e.g. ['sidebar', 'modal']) */\n parallelRouteKeys: string[];\n}\n\n// ─── Context ─────────────────────────────────────────────────────\n\nconst SegmentContext = createContext<SegmentContextValue | null>(null);\n\n/** Read the segment context. Returns null if no provider is above this component. */\nexport function useSegmentContext(): SegmentContextValue | null {\n return useContext(SegmentContext);\n}\n\n// ─── Provider ────────────────────────────────────────────────────\n\ninterface SegmentProviderProps {\n segments: string[];\n /**\n * Unique identifier for this segment, used by the client-side segment\n * merger for element caching. For route groups this includes the group\n * name (e.g., \"/(marketing)\") since groups share their parent's urlPath.\n * Falls back to the reconstructed path from `segments` if not provided.\n */\n segmentId?: string;\n parallelRouteKeys: string[];\n children: React.ReactNode;\n}\n\n/**\n * Wraps each layout to provide segment position context.\n * Injected by rsc-entry.ts during element tree construction.\n */\nexport function SegmentProvider({\n segments,\n segmentId: _segmentId,\n parallelRouteKeys,\n children,\n}: SegmentProviderProps) {\n const value = useMemo(\n () => ({ segments, parallelRouteKeys }),\n // segments and parallelRouteKeys are static per layout — the layout's\n // position in the tree is fixed. The arrays are used directly as deps\n // (React Compiler requires simple expressions here). Referential stability\n // of the context value doesn't matter: every consumer\n // (useSelectedLayoutSegment/useSelectedLayoutSegments) also calls\n // usePathname(), so it re-renders on every navigation regardless.\n [segments, parallelRouteKeys]\n );\n return createElement(SegmentContext.Provider, { value }, children);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqFA,IAAM,cAAc,OAAO,IAAI,kBAAkB;AAEjD,SAAS,qBAAsE;CAC7E,MAAM,WAAY,WAAuC;CAGzD,IAAI,aAAa,KAAA,GAAW,OAAO;CACnC,MAAM,MAAM,cAAsC,IAAI;CACtD,WAAwC,eAAe;CACvD,OAAO;AACT;;;;;;;AAQA,SAAgB,uBAA+C;CAC7D,OAAO,WAAW,mBAAmB,CAAC;AACxC;;;;;;;AAiBA,SAAgB,mBAAmB,EACjC,OACA,YACwD;CACxD,OAAO,cAAc,mBAAmB,CAAC,CAAC,UAAU,EAAE,MAAM,GAAG,QAAQ;AACzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACnGA,IAAM,iBAAiB,cAA0C,IAAI;;AAGrE,SAAgB,oBAAgD;CAC9D,OAAO,WAAW,cAAc;AAClC;;;;;AAqBA,SAAgB,gBAAgB,EAC9B,UACA,WAAW,YACX,mBACA,YACuB;CACvB,MAAM,QAAQ,eACL;EAAE;EAAU;CAAkB,IAOrC,CAAC,UAAU,iBAAiB,CAC9B;CACA,OAAO,cAAc,eAAe,UAAU,EAAE,MAAM,GAAG,QAAQ;AACnE"}
|
|
@@ -20,8 +20,9 @@ function createSingleflight(opts) {
|
|
|
20
20
|
let promise;
|
|
21
21
|
if (timeoutMs != null && timeoutMs > 0) promise = new Promise((resolve, reject) => {
|
|
22
22
|
const timer = setTimeout(() => {
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
const timeout = new SingleflightTimeoutError(key, timeoutMs);
|
|
24
|
+
ac.abort(timeout);
|
|
25
|
+
reject(timeout);
|
|
25
26
|
}, timeoutMs);
|
|
26
27
|
try {
|
|
27
28
|
fn(ac.signal).then((value) => {
|
|
@@ -51,4 +52,4 @@ function createSingleflight(opts) {
|
|
|
51
52
|
//#endregion
|
|
52
53
|
export { createSingleflight as n, SingleflightTimeoutError as t };
|
|
53
54
|
|
|
54
|
-
//# sourceMappingURL=singleflight-
|
|
55
|
+
//# sourceMappingURL=singleflight-BeVMMKi0.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"singleflight-
|
|
1
|
+
{"version":3,"file":"singleflight-BeVMMKi0.js","names":[],"sources":["../../src/cache/singleflight.ts"],"sourcesContent":["/**\n * Singleflight coalesces concurrent calls with the same key into a single\n * execution. All callers receive the same result (or error).\n *\n * Per-process, in-memory. Each process coalesces independently.\n *\n * An optional `timeoutMs` prevents hung `fn()` calls from permanently\n * blocking all future callers for that key. When set, `fn()` is raced\n * against a timeout — if the timeout fires first, the promise rejects\n * with `SingleflightTimeoutError`, `finally` cleans up the key, and\n * subsequent callers can retry. See TIM-518.\n */\n\nexport interface SingleflightOptions {\n /** Maximum time (ms) a coalesced call may run before being rejected. */\n timeoutMs?: number;\n}\n\nexport interface Singleflight {\n do<T>(key: string, fn: (signal: AbortSignal) => Promise<T>): Promise<T>;\n /** Return the in-flight promise for a key, or undefined if none. */\n get(key: string): Promise<unknown> | undefined;\n}\n\n/**\n * Error thrown when a singleflight call exceeds `timeoutMs`.\n * Exported so callers can distinguish timeout from other errors.\n */\nexport class SingleflightTimeoutError extends Error {\n constructor(key: string, timeoutMs: number) {\n super(`Singleflight timeout: key \"${key}\" exceeded ${timeoutMs}ms`);\n this.name = 'SingleflightTimeoutError';\n }\n}\n\nexport function createSingleflight(opts?: SingleflightOptions): Singleflight {\n const inflight = new Map<string, Promise<unknown>>();\n const timeoutMs = opts?.timeoutMs;\n\n return {\n do<T>(key: string, fn: (signal: AbortSignal) => Promise<T>): Promise<T> {\n const existing = inflight.get(key);\n if (existing) return existing as Promise<T>;\n\n const ac = new AbortController();\n let promise: Promise<T>;\n\n if (timeoutMs != null && timeoutMs > 0) {\n // Race fn() against a timeout to prevent hung calls from\n // permanently blocking the key. See TIM-518.\n // Abort the signal on timeout so the callback can skip\n // side effects (e.g. cache writes). See TIM-1092.\n promise = new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => {\n // The timeout error is also the signal's reason, so the body\n // can tell why it was aborted (runBackgroundFlight reports it).\n const timeout = new SingleflightTimeoutError(key, timeoutMs);\n ac.abort(timeout);\n reject(timeout);\n }, timeoutMs);\n try {\n fn(ac.signal).then(\n (value) => {\n clearTimeout(timer);\n resolve(value);\n },\n (err) => {\n clearTimeout(timer);\n reject(err);\n }\n );\n } catch (err) {\n clearTimeout(timer);\n reject(err);\n }\n });\n } else {\n promise = fn(ac.signal);\n }\n\n const tracked = promise.finally(() => {\n inflight.delete(key);\n });\n\n inflight.set(key, tracked);\n return tracked as Promise<T>;\n },\n get(key: string): Promise<unknown> | undefined {\n return inflight.get(key);\n },\n };\n}\n"],"mappings":";;;;;AA4BA,IAAa,2BAAb,cAA8C,MAAM;CAClD,YAAY,KAAa,WAAmB;EAC1C,MAAM,8BAA8B,IAAI,aAAa,UAAU,GAAG;EAClE,KAAK,OAAO;CACd;AACF;AAEA,SAAgB,mBAAmB,MAA0C;CAC3E,MAAM,2BAAW,IAAI,IAA8B;CACnD,MAAM,YAAY,MAAM;CAExB,OAAO;EACL,GAAM,KAAa,IAAqD;GACtE,MAAM,WAAW,SAAS,IAAI,GAAG;GACjC,IAAI,UAAU,OAAO;GAErB,MAAM,KAAK,IAAI,gBAAgB;GAC/B,IAAI;GAEJ,IAAI,aAAa,QAAQ,YAAY,GAKnC,UAAU,IAAI,SAAY,SAAS,WAAW;IAC5C,MAAM,QAAQ,iBAAiB;KAG7B,MAAM,UAAU,IAAI,yBAAyB,KAAK,SAAS;KAC3D,GAAG,MAAM,OAAO;KAChB,OAAO,OAAO;IAChB,GAAG,SAAS;IACZ,IAAI;KACF,GAAG,GAAG,MAAM,CAAC,CAAC,MACX,UAAU;MACT,aAAa,KAAK;MAClB,QAAQ,KAAK;KACf,IACC,QAAQ;MACP,aAAa,KAAK;MAClB,OAAO,GAAG;KACZ,CACF;IACF,SAAS,KAAK;KACZ,aAAa,KAAK;KAClB,OAAO,GAAG;IACZ;GACF,CAAC;QAED,UAAU,GAAG,GAAG,MAAM;GAGxB,MAAM,UAAU,QAAQ,cAAc;IACpC,SAAS,OAAO,GAAG;GACrB,CAAC;GAED,SAAS,IAAI,KAAK,OAAO;GACzB,OAAO;EACT;EACA,IAAI,KAA2C;GAC7C,OAAO,SAAS,IAAI,GAAG;EACzB;CACF;AACF"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { _ as swallow } from "./logger-DiDt5ppH.js";
|
|
1
2
|
//#region src/cache/sizeof.ts
|
|
2
3
|
/**
|
|
3
4
|
* Lightweight byte-size estimation for cache entries.
|
|
@@ -25,11 +26,11 @@ function estimateByteSize(value) {
|
|
|
25
26
|
if (json === void 0) return 0;
|
|
26
27
|
return json.length * 2;
|
|
27
28
|
} catch (e) {
|
|
28
|
-
|
|
29
|
+
swallow(e, "sizeof estimation failed", { level: "debug" });
|
|
29
30
|
return 0;
|
|
30
31
|
}
|
|
31
32
|
}
|
|
32
33
|
//#endregion
|
|
33
34
|
export { estimateByteSize as t };
|
|
34
35
|
|
|
35
|
-
//# sourceMappingURL=sizeof-
|
|
36
|
+
//# sourceMappingURL=sizeof-UwzwB1uM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sizeof-UwzwB1uM.js","names":[],"sources":["../../src/cache/sizeof.ts"],"sourcesContent":["/**\n * Lightweight byte-size estimation for cache entries.\n *\n * Estimates the in-memory byte cost of a JavaScript value using\n * JSON.stringify().length * 2 (UTF-16 char width). This is a rough\n * approximation — it doesn't account for V8 object overhead, Map\n * metadata, or non-serializable values — but it's fast and good\n * enough for cache budget enforcement.\n *\n * Values that fail JSON serialization (circular references, BigInt,\n * etc.) return 0, allowing the entry to be cached without counting\n * toward the byte budget. This is a conservative choice: it's better\n * to cache and undercount than to reject the entry.\n */\n\nimport { swallow } from '../server/logger.ts';\n\n/**\n * Estimate the byte size of a value.\n *\n * Uses `JSON.stringify(value).length * 2` to approximate UTF-16\n * in-memory size. Returns 0 if the value is not serializable.\n */\nexport function estimateByteSize(value: unknown): number {\n try {\n const json = JSON.stringify(value);\n if (json === undefined) return 0;\n // Each JS string character is 2 bytes (UTF-16)\n return json.length * 2;\n } catch (e) {\n // Circular reference or non-serializable value\n swallow(e, 'sizeof estimation failed', { level: 'debug' });\n return 0;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAuBA,SAAgB,iBAAiB,OAAwB;CACvD,IAAI;EACF,MAAM,OAAO,KAAK,UAAU,KAAK;EACjC,IAAI,SAAS,KAAA,GAAW,OAAO;EAE/B,OAAO,KAAK,SAAS;CACvB,SAAS,GAAG;EAEV,QAAQ,GAAG,4BAA4B,EAAE,OAAO,QAAQ,CAAC;EACzD,OAAO;CACT;AACF"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { d as ssrDataProvider, i as _setSsrDataProvider } from "./state-BhNGPsdi.js";
|
|
2
|
+
//#region src/client/ssr-data.ts
|
|
3
|
+
/**
|
|
4
|
+
* SSR Data — per-request state for client hooks during server-side rendering.
|
|
5
|
+
*
|
|
6
|
+
* `useCookie()` and `<Link preserveSearchParams>` have no React context to
|
|
7
|
+
* read their request values from during SSR, so the SSR entry hands them
|
|
8
|
+
* the request's cookies and search string through this module.
|
|
9
|
+
* `useSearchParams()` reads NavigationContext and uses getSsrData() only to
|
|
10
|
+
* detect that it is rendering on the server. Route
|
|
11
|
+
* params do not travel here — client components read them from
|
|
12
|
+
* `ParamsContext`, decoded from the payload root.
|
|
13
|
+
*
|
|
14
|
+
* Request isolation: ssr-entry.ts registers an ALS-backed provider via
|
|
15
|
+
* registerSsrDataProvider(), so getSsrData() reads the current request's
|
|
16
|
+
* store even when Suspense boundaries resolve asynchronously across
|
|
17
|
+
* concurrent requests. There is no module-level fallback: outside an SSR
|
|
18
|
+
* render (in the browser, or before the provider is registered) there is no
|
|
19
|
+
* request, and getSsrData() returns undefined.
|
|
20
|
+
*
|
|
21
|
+
* IMPORTANT: This module must NOT import node:async_hooks or any Node.js-only
|
|
22
|
+
* APIs, as it's imported by 'use client' hooks that are bundled for the browser.
|
|
23
|
+
* The ALS instance lives in ssr-entry.ts (server-only); this module only holds
|
|
24
|
+
* a reference to the provider function.
|
|
25
|
+
*
|
|
26
|
+
* All mutable state is delegated to client/state.ts for singleton guarantees.
|
|
27
|
+
* See design/18-build-system.md §"Singleton State Registry"
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* Register the SSR data provider. Called once at module load by
|
|
31
|
+
* ssr-entry.ts to wire up per-request data via AsyncLocalStorage; tests
|
|
32
|
+
* register their own provider (and `undefined` to reset).
|
|
33
|
+
*/
|
|
34
|
+
function registerSsrDataProvider(provider) {
|
|
35
|
+
_setSsrDataProvider(provider);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Read the current request's SSR data. Returns undefined when called
|
|
39
|
+
* outside an SSR render (i.e. on the client after hydration).
|
|
40
|
+
*
|
|
41
|
+
* Used by client hooks' server snapshot functions.
|
|
42
|
+
*/
|
|
43
|
+
function getSsrData() {
|
|
44
|
+
return ssrDataProvider?.();
|
|
45
|
+
}
|
|
46
|
+
//#endregion
|
|
47
|
+
export { registerSsrDataProvider as n, getSsrData as t };
|
|
48
|
+
|
|
49
|
+
//# sourceMappingURL=ssr-data-nA3I70_n.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssr-data-nA3I70_n.js","names":[],"sources":["../../src/client/ssr-data.ts"],"sourcesContent":["/**\n * SSR Data — per-request state for client hooks during server-side rendering.\n *\n * `useCookie()` and `<Link preserveSearchParams>` have no React context to\n * read their request values from during SSR, so the SSR entry hands them\n * the request's cookies and search string through this module.\n * `useSearchParams()` reads NavigationContext and uses getSsrData() only to\n * detect that it is rendering on the server. Route\n * params do not travel here — client components read them from\n * `ParamsContext`, decoded from the payload root.\n *\n * Request isolation: ssr-entry.ts registers an ALS-backed provider via\n * registerSsrDataProvider(), so getSsrData() reads the current request's\n * store even when Suspense boundaries resolve asynchronously across\n * concurrent requests. There is no module-level fallback: outside an SSR\n * render (in the browser, or before the provider is registered) there is no\n * request, and getSsrData() returns undefined.\n *\n * IMPORTANT: This module must NOT import node:async_hooks or any Node.js-only\n * APIs, as it's imported by 'use client' hooks that are bundled for the browser.\n * The ALS instance lives in ssr-entry.ts (server-only); this module only holds\n * a reference to the provider function.\n *\n * All mutable state is delegated to client/state.ts for singleton guarantees.\n * See design/18-build-system.md §\"Singleton State Registry\"\n */\n\nimport { ssrDataProvider, _setSsrDataProvider } from './state.ts';\n\n// ─── Types ────────────────────────────────────────────────────────\n\nexport interface SsrData {\n /**\n * The request's raw app-visible query string (`''` or `?…`), matching what\n * `window.location.search` will hold after hydration. The raw string is\n * the only representation carried here: it preserves repeated keys\n * (`?tag=a&tag=b`), which a collapsed `Record<string, string>` cannot\n * (TIM-1428). Parse with `new URLSearchParams(search)` where needed.\n */\n search: string;\n /** The request's cookies as name→value pairs */\n cookies: Map<string, string>;\n}\n\n// ─── ALS-Backed Provider ─────────────────────────────────────────\n//\n// Server-side code (ssr-entry.ts) registers a provider that reads\n// from AsyncLocalStorage. This avoids importing node:async_hooks\n// in this browser-bundled module.\n//\n// Module singleton guarantee: In Vite's SSR environment, both\n// ssr-entry.ts (via #/client/ssr-data.js) and client component hooks\n// (via @timber-js/app/client) must resolve to the SAME module instance\n// of this file. The timber-shims plugin ensures this by remapping\n// @timber-js/app/client → src/client/index.ts in the SSR environment.\n// Without this remap, @timber-js/app/client resolves to dist/ (via\n// package.json exports), creating a split where registerSsrDataProvider\n// writes to one instance but getSsrData reads from another.\n// See timber-shims plugin resolveId for details.\n\n/**\n * Register the SSR data provider. Called once at module load by\n * ssr-entry.ts to wire up per-request data via AsyncLocalStorage; tests\n * register their own provider (and `undefined` to reset).\n */\nexport function registerSsrDataProvider(provider: (() => SsrData | undefined) | undefined): void {\n _setSsrDataProvider(provider);\n}\n\n/**\n * Read the current request's SSR data. Returns undefined when called\n * outside an SSR render (i.e. on the client after hydration).\n *\n * Used by client hooks' server snapshot functions.\n */\nexport function getSsrData(): SsrData | undefined {\n return ssrDataProvider?.();\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiEA,SAAgB,wBAAwB,UAAyD;CAC/F,oBAAoB,QAAQ;AAC9B;;;;;;;AAQA,SAAgB,aAAkC;CAChD,OAAO,kBAAkB;AAC3B"}
|
|
@@ -5,14 +5,12 @@ function _setGlobalRouter(router) {
|
|
|
5
5
|
globalRouter = router;
|
|
6
6
|
}
|
|
7
7
|
/**
|
|
8
|
-
* ALS-backed SSR data provider
|
|
9
|
-
*
|
|
8
|
+
* ALS-backed SSR data provider, registered by the SSR entry. getSsrData()
|
|
9
|
+
* reads through it; unset in the browser.
|
|
10
10
|
*/
|
|
11
11
|
var ssrDataProvider;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
function _setCurrentSsrData(data) {
|
|
15
|
-
currentSsrData = data;
|
|
12
|
+
function _setSsrDataProvider(provider) {
|
|
13
|
+
ssrDataProvider = provider;
|
|
16
14
|
}
|
|
17
15
|
/** Cached search string — avoids reparsing when URL hasn't changed. */
|
|
18
16
|
var cachedSearch = "";
|
|
@@ -47,6 +45,6 @@ function _setOnStatusPageRendered(handler) {
|
|
|
47
45
|
onStatusPageRendered = handler;
|
|
48
46
|
}
|
|
49
47
|
//#endregion
|
|
50
|
-
export { _setStatusPageRendered as a, cachedSearchParams as c,
|
|
48
|
+
export { _setStatusPageRendered as a, cachedSearchParams as c, ssrDataProvider as d, statusPageRendered as f, _setSsrDataProvider as i, globalRouter as l, _setGlobalRouter as n, _setUnloading as o, unloading as p, _setOnStatusPageRendered as r, cachedSearch as s, _setCachedSearch as t, onStatusPageRendered as u };
|
|
51
49
|
|
|
52
|
-
//# sourceMappingURL=state-
|
|
50
|
+
//# sourceMappingURL=state-BhNGPsdi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-BhNGPsdi.js","names":[],"sources":["../../src/client/state.ts"],"sourcesContent":["/**\n * Centralized client singleton state registry.\n *\n * ALL mutable module-level state that must have singleton semantics across\n * the client bundle lives here. Individual modules (router-ref.ts, ssr-data.ts,\n * use-segment-params.ts, use-search-params.ts, unload-guard.ts) import from this file\n * and re-export thin wrapper functions.\n *\n * Why: In Vite dev, a module is instantiated separately if reached via different\n * import paths (e.g., relative `./foo.js` vs barrel `@timber-js/app/client`).\n * By centralizing all mutable state in a single module that is always reached\n * through the same dependency chain (barrel → wrapper → state.ts), we guarantee\n * a single instance of every piece of shared state.\n *\n * DO NOT import this file from outside client/. Server code must never depend\n * on client state. The barrel (client/index.ts) is the public entry point.\n *\n * See design/18-build-system.md §\"Module Singleton Strategy\" and\n * §\"Singleton State Registry\".\n */\n\nimport type { RouterInstance } from './router-types.ts';\nimport type { SsrData } from './ssr-data.ts';\n\n// ─── Router (from router-ref.ts) ──────────────────────────────────────────\n\n/** The global router singleton — set once during bootstrap. */\nexport let globalRouter: RouterInstance | null = null;\n\nexport function _setGlobalRouter(router: RouterInstance | null): void {\n globalRouter = router;\n}\n\n// ─── SSR Data Provider (from ssr-data.ts) ──────────────────────────────────\n\n/**\n * ALS-backed SSR data provider, registered by the SSR entry. getSsrData()\n * reads through it; unset in the browser.\n */\nexport let ssrDataProvider: (() => SsrData | undefined) | undefined;\n\nexport function _setSsrDataProvider(provider: (() => SsrData | undefined) | undefined): void {\n ssrDataProvider = provider;\n}\n\n// ─── Search Params Cache (from use-search-params.ts) ────────────────────────\n\n/** Cached search string — avoids reparsing when URL hasn't changed. */\nexport let cachedSearch = '';\nexport let cachedSearchParams = new URLSearchParams();\n\nexport function _setCachedSearch(search: string, params: URLSearchParams): void {\n cachedSearch = search;\n cachedSearchParams = params;\n}\n\n// ─── Unload Guard (from unload-guard.ts) ─────────────────────────────────────\n\n/** Whether the page is currently being unloaded. */\nexport let unloading = false;\n\nexport function _setUnloading(value: boolean): void {\n unloading = value;\n}\n\n// ─── Status Page Commit Flag (from navigation-commit.ts) ────────────────────\n\n/**\n * Whether a status page for the main route has rendered since the last\n * navigation was prepared. Raised by `StatusPageMarker`, consumed by the\n * navigation's commit. See navigation-commit.ts §\"What a status page\n * teaches the cache\".\n */\nexport let statusPageRendered = false;\n\nexport function _setStatusPageRendered(value: boolean): void {\n statusPageRendered = value;\n}\n\n/**\n * What a status page report does beyond raising the flag: registered by the\n * router's committer so the report can clear the segment cache at once, for\n * the commits no navigation consumes (a row arriving inside Suspense after\n * its navigation published, a status document being hydrated).\n */\nexport let onStatusPageRendered: (() => void) | undefined;\n\nexport function _setOnStatusPageRendered(handler: (() => void) | undefined): void {\n onStatusPageRendered = handler;\n}\n"],"mappings":";;AA2BA,IAAW,eAAsC;AAEjD,SAAgB,iBAAiB,QAAqC;CACpE,eAAe;AACjB;;;;;AAQA,IAAW;AAEX,SAAgB,oBAAoB,UAAyD;CAC3F,kBAAkB;AACpB;;AAKA,IAAW,eAAe;AAC1B,IAAW,qBAAqB,IAAI,gBAAgB;AAEpD,SAAgB,iBAAiB,QAAgB,QAA+B;CAC9E,eAAe;CACf,qBAAqB;AACvB;;AAKA,IAAW,YAAY;AAEvB,SAAgB,cAAc,OAAsB;CAClD,YAAY;AACd;;;;;;;AAUA,IAAW,qBAAqB;AAEhC,SAAgB,uBAAuB,OAAsB;CAC3D,qBAAqB;AACvB;;;;;;;AAQA,IAAW;AAEX,SAAgB,yBAAyB,SAAyC;CAChF,uBAAuB;AACzB"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { n as createSingleflight } from "./singleflight-
|
|
2
|
-
import { r as
|
|
3
|
-
import { a as _setStatusPageRendered, d as onStatusPageRendered, i as _setOnStatusPageRendered, p as statusPageRendered } from "./state-FippDgxN.js";
|
|
1
|
+
import { n as createSingleflight } from "./singleflight-BeVMMKi0.js";
|
|
2
|
+
import { a as _setStatusPageRendered, f as statusPageRendered, r as _setOnStatusPageRendered, u as onStatusPageRendered } from "./state-BhNGPsdi.js";
|
|
4
3
|
import { useLayoutEffect } from "react";
|
|
5
4
|
//#region src/shared/rsc-error-envelope.ts
|
|
6
5
|
/**
|
|
@@ -27,6 +26,16 @@ var TIMBER_ERROR_HEADER = "X-Timber-Error";
|
|
|
27
26
|
*/
|
|
28
27
|
var SegmentCache = class {
|
|
29
28
|
root;
|
|
29
|
+
/**
|
|
30
|
+
* Monotonic counter. Bumped by `invalidateReuse()` (TIM-1466).
|
|
31
|
+
* `serializeStateTree` suppresses `segments` and `slots` when
|
|
32
|
+
* `reuseInvalidatedAt > reuseRestoredAt`. Only `restoreReuse()`
|
|
33
|
+
* advances `reuseRestoredAt` — `set()` does not, because a
|
|
34
|
+
* pre-invalidation navigation's commit thunk would lift suppression
|
|
35
|
+
* before a post-invalidation request has been sent (codex on #1167).
|
|
36
|
+
*/
|
|
37
|
+
reuseInvalidatedAt = 0;
|
|
38
|
+
reuseRestoredAt = 0;
|
|
30
39
|
get(segment) {
|
|
31
40
|
if (segment === "/" || segment === this.root?.segment) return this.root;
|
|
32
41
|
}
|
|
@@ -35,6 +44,30 @@ var SegmentCache = class {
|
|
|
35
44
|
}
|
|
36
45
|
clear() {
|
|
37
46
|
this.root = void 0;
|
|
47
|
+
this.reuseRestoredAt = this.reuseInvalidatedAt;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Suppress segment and slot reuse without destroying the tree
|
|
51
|
+
* structure (TIM-1466). `serializeStateTree` sends empty
|
|
52
|
+
* `segments`/`slots` (forcing a full render) while `treePaths`
|
|
53
|
+
* still reflects the mounted tree for interception scoping.
|
|
54
|
+
* Call `restoreReuse()` once post-invalidation data has been
|
|
55
|
+
* fetched and committed.
|
|
56
|
+
*/
|
|
57
|
+
invalidateReuse() {
|
|
58
|
+
this.reuseInvalidatedAt++;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Lift reuse suppression. Called after the segment cache has been
|
|
62
|
+
* rebuilt from a response that was fetched with suppression active
|
|
63
|
+
* (i.e. the server sent a full render). Safe to call idempotently.
|
|
64
|
+
*/
|
|
65
|
+
restoreReuse() {
|
|
66
|
+
this.reuseRestoredAt = this.reuseInvalidatedAt;
|
|
67
|
+
}
|
|
68
|
+
/** Whether segment/slot reuse is currently suppressed (TIM-1466). */
|
|
69
|
+
isReuseSuppressed() {
|
|
70
|
+
return this.reuseInvalidatedAt > this.reuseRestoredAt;
|
|
38
71
|
}
|
|
39
72
|
/**
|
|
40
73
|
* Serialize the mounted segment tree for the X-Timber-State-Tree header.
|
|
@@ -60,9 +93,12 @@ var SegmentCache = class {
|
|
|
60
93
|
const segments = [];
|
|
61
94
|
const slots = [];
|
|
62
95
|
const treePaths = [];
|
|
96
|
+
const suppressed = this.reuseInvalidatedAt > this.reuseRestoredAt;
|
|
63
97
|
if (this.root) {
|
|
64
|
-
|
|
65
|
-
|
|
98
|
+
if (!suppressed) {
|
|
99
|
+
collectSyncSegments(this.root, segments, mergeableFilter);
|
|
100
|
+
collectSyncSlots(this.root, slots);
|
|
101
|
+
}
|
|
66
102
|
collectTreePaths(this.root, treePaths);
|
|
67
103
|
}
|
|
68
104
|
const tree = { segments };
|
|
@@ -171,6 +207,22 @@ function prefetchMapKey(key) {
|
|
|
171
207
|
return `${key.from.length}:${key.from}:${key.scope.length}:${key.scope}:${key.url}`;
|
|
172
208
|
}
|
|
173
209
|
/**
|
|
210
|
+
* Extract the destination URL from a length-prefixed map key.
|
|
211
|
+
* Key format: `${from.length}:${from}:${scope.length}:${scope}:${url}`
|
|
212
|
+
*/
|
|
213
|
+
function extractUrlFromMapKey(mapKey) {
|
|
214
|
+
const firstColon = mapKey.indexOf(":");
|
|
215
|
+
if (firstColon === -1) return null;
|
|
216
|
+
const fromLen = parseInt(mapKey.slice(0, firstColon), 10);
|
|
217
|
+
if (Number.isNaN(fromLen)) return null;
|
|
218
|
+
const scopeStart = firstColon + 1 + fromLen + 1;
|
|
219
|
+
const secondColon = mapKey.indexOf(":", scopeStart);
|
|
220
|
+
if (secondColon === -1) return null;
|
|
221
|
+
const scopeLen = parseInt(mapKey.slice(scopeStart, secondColon), 10);
|
|
222
|
+
if (Number.isNaN(scopeLen)) return null;
|
|
223
|
+
return mapKey.slice(secondColon + 1 + scopeLen + 1);
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
174
226
|
* The `scope` half of a `PrefetchKey`, derived from the state tree that will
|
|
175
227
|
* actually be sent. Taking it from the header value rather than re-walking the
|
|
176
228
|
* cache is the point: the key varies by exactly what the request varies by.
|
|
@@ -244,12 +296,16 @@ var PrefetchCache = class PrefetchCache {
|
|
|
244
296
|
if (!signal.aborted && this.evictionGen === genAtStart) this.set(key, result);
|
|
245
297
|
return {
|
|
246
298
|
kind: "ready",
|
|
247
|
-
result
|
|
299
|
+
result,
|
|
300
|
+
startGen: genAtStart
|
|
248
301
|
};
|
|
249
302
|
} catch (err) {
|
|
250
303
|
if (isNonRoute(err)) {
|
|
251
304
|
if (!signal.aborted && this.evictionGen === genAtStart) this.setNegative(key);
|
|
252
|
-
return {
|
|
305
|
+
return {
|
|
306
|
+
kind: "non-route",
|
|
307
|
+
startGen: genAtStart
|
|
308
|
+
};
|
|
253
309
|
}
|
|
254
310
|
throw err;
|
|
255
311
|
}
|
|
@@ -281,12 +337,32 @@ var PrefetchCache = class PrefetchCache {
|
|
|
281
337
|
return this.get(key) === NEGATIVE_ENTRY;
|
|
282
338
|
}
|
|
283
339
|
/**
|
|
284
|
-
* Invalidate
|
|
285
|
-
*
|
|
286
|
-
*
|
|
340
|
+
* Invalidate entries whose destination URL matches (TIM-1454).
|
|
341
|
+
*
|
|
342
|
+
* When `url` has no search string, evicts all entries sharing that
|
|
343
|
+
* pathname — `/products` evicts `/products?page=1` too, because
|
|
344
|
+
* `revalidatePath('/products')` invalidates the route regardless of
|
|
345
|
+
* query (TIM-1465).
|
|
346
|
+
*
|
|
347
|
+
* When `url` has a search string, only the exact URL is evicted.
|
|
348
|
+
*
|
|
349
|
+
* Also bumps the eviction generation so in-flight singleflight
|
|
350
|
+
* flights for the invalidated URL(s) discard their results on
|
|
351
|
+
* completion (TIM-1464).
|
|
287
352
|
*/
|
|
288
353
|
invalidateUrl(url) {
|
|
289
|
-
|
|
354
|
+
const hasSearch = url.includes("?");
|
|
355
|
+
const pathname = hasSearch ? null : url;
|
|
356
|
+
for (const [mapKey] of this.entries) if (hasSearch) {
|
|
357
|
+
if (mapKey.endsWith(":" + url)) this.entries.delete(mapKey);
|
|
358
|
+
} else {
|
|
359
|
+
const entryUrl = extractUrlFromMapKey(mapKey);
|
|
360
|
+
if (entryUrl !== null) {
|
|
361
|
+
const qIndex = entryUrl.indexOf("?");
|
|
362
|
+
if ((qIndex === -1 ? entryUrl : entryUrl.slice(0, qIndex)) === pathname) this.entries.delete(mapKey);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
this.evictionGen++;
|
|
290
366
|
}
|
|
291
367
|
/**
|
|
292
368
|
* Evict all ready entries and fence in-flight singleflights (TIM-1476).
|
|
@@ -311,6 +387,37 @@ var PrefetchCache = class PrefetchCache {
|
|
|
311
387
|
}
|
|
312
388
|
};
|
|
313
389
|
//#endregion
|
|
390
|
+
//#region src/client/router-url.ts
|
|
391
|
+
/**
|
|
392
|
+
* How the client router reads the URLs it is handed.
|
|
393
|
+
*
|
|
394
|
+
* One parser, so the places that key or compare by URL — the history stack,
|
|
395
|
+
* the navigation state a page renders with, the departing page sent as
|
|
396
|
+
* `X-Timber-URL` — cannot disagree about what a URL says. They did: a
|
|
397
|
+
* history entry stored under `navigate('/café')`'s spelling was looked up
|
|
398
|
+
* under the address bar's `/caf%C3%A9`, and missed (TIM-1541).
|
|
399
|
+
*/
|
|
400
|
+
var BASE = "http://localhost";
|
|
401
|
+
/**
|
|
402
|
+
* Parse a router URL. A URL that starts with "/" is a path — including one
|
|
403
|
+
* that starts with "//": that is the pathname a document at
|
|
404
|
+
* `https://host//a/b` reports, and resolved against a base it would parse as
|
|
405
|
+
* a scheme-relative reference to host `a`. Anything else resolves against a
|
|
406
|
+
* placeholder origin, so an absolute URL keeps its own.
|
|
407
|
+
*/
|
|
408
|
+
function parseRouterUrl(url) {
|
|
409
|
+
return url.startsWith("/") ? new URL(BASE + url) : new URL(url, BASE);
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* The spelling a URL is stored and looked up under: the browser's own
|
|
413
|
+
* pathname + search, so `/a?` and `/a`, `/café` and `/caf%C3%A9`, are one
|
|
414
|
+
* key. The fragment is dropped — it is client-only.
|
|
415
|
+
*/
|
|
416
|
+
function routerUrlKey(url) {
|
|
417
|
+
const parsed = parseRouterUrl(url);
|
|
418
|
+
return parsed.pathname + parsed.search;
|
|
419
|
+
}
|
|
420
|
+
//#endregion
|
|
314
421
|
//#region src/client/navigation-commit.ts
|
|
315
422
|
/**
|
|
316
423
|
* What it means for a page to be "current" on the client.
|
|
@@ -348,10 +455,11 @@ function hasSkippedSlot(segmentInfo) {
|
|
|
348
455
|
return segmentInfo?.some((s) => s.slot && s.skipped) ?? false;
|
|
349
456
|
}
|
|
350
457
|
/**
|
|
351
|
-
* The metadata a history entry
|
|
352
|
-
*
|
|
353
|
-
*
|
|
354
|
-
*
|
|
458
|
+
* The metadata a committed page keeps — on its history entry, and as the
|
|
459
|
+
* current page's `committedSegmentInfo()`. `skipped` describes the
|
|
460
|
+
* *response* — "this slot's content was omitted" — and neither stores such
|
|
461
|
+
* a payload (the entry stores null). Kept, the flag outlives the response:
|
|
462
|
+
* `applyActionResult()` reuses the current page's metadata beside a full
|
|
355
463
|
* re-render and would have that judged non-replayable too.
|
|
356
464
|
*/
|
|
357
465
|
function storedSegmentInfo(segmentInfo) {
|
|
@@ -361,14 +469,12 @@ function storedSegmentInfo(segmentInfo) {
|
|
|
361
469
|
/**
|
|
362
470
|
* Derive the navigation state (pathname + search) a URL renders with.
|
|
363
471
|
*
|
|
364
|
-
* Pure
|
|
365
|
-
*
|
|
366
|
-
*
|
|
367
|
-
* explicitly to renderRoot/wrapPayload, so a render never depends on the
|
|
368
|
-
* publish having happened first.
|
|
472
|
+
* Pure. The value travels with the tree it describes — callers pass it to
|
|
473
|
+
* `wrapPayload`, and the router's record of the displayed tree keeps it
|
|
474
|
+
* beside that tree — so there is no store to publish it to (TIM-1541).
|
|
369
475
|
*/
|
|
370
476
|
function deriveNavigationState(url) {
|
|
371
|
-
const parsed =
|
|
477
|
+
const parsed = parseRouterUrl(url);
|
|
372
478
|
return {
|
|
373
479
|
pathname: parsed.pathname || "/",
|
|
374
480
|
search: parsed.search
|
|
@@ -376,6 +482,7 @@ function deriveNavigationState(url) {
|
|
|
376
482
|
}
|
|
377
483
|
function createNavigationCommitter(deps) {
|
|
378
484
|
const { segmentCache, historyStack } = deps;
|
|
485
|
+
let committedSegmentInfo = null;
|
|
379
486
|
_setOnStatusPageRendered(() => segmentCache.clear());
|
|
380
487
|
/**
|
|
381
488
|
* Update the segment cache from server-provided segment metadata.
|
|
@@ -386,12 +493,13 @@ function createNavigationCommitter(deps) {
|
|
|
386
493
|
* `currentStateTree`.
|
|
387
494
|
*/
|
|
388
495
|
function updateSegmentCache(segmentInfo) {
|
|
389
|
-
if (!segmentInfo || segmentInfo.length === 0) return;
|
|
390
496
|
const tree = buildSegmentTree(segmentInfo);
|
|
391
497
|
if (tree) segmentCache.set("/", tree);
|
|
392
498
|
}
|
|
393
499
|
return {
|
|
394
|
-
|
|
500
|
+
committedSegmentInfo: () => committedSegmentInfo,
|
|
501
|
+
isSegmentReuseSuppressed: () => segmentCache.isReuseSuppressed(),
|
|
502
|
+
restoreSegmentReuse: () => segmentCache.restoreReuse(),
|
|
395
503
|
/**
|
|
396
504
|
* The X-Timber-State-Tree to send with the next RSC request.
|
|
397
505
|
*
|
|
@@ -424,9 +532,13 @@ function createNavigationCommitter(deps) {
|
|
|
424
532
|
* the URL and is what the incoming tree is *rendered* with, plus a
|
|
425
533
|
* `commit` thunk that performs the writes that make a page current:
|
|
426
534
|
* 1. Segment cache — update from server-provided segment metadata
|
|
427
|
-
* 2.
|
|
535
|
+
* 2. The current page's segment metadata (`committedSegmentInfo`)
|
|
428
536
|
* 3. History stack — store the payload for instant back/forward replay
|
|
429
537
|
*
|
|
538
|
+
* Pathname and search are not written here: they are the returned
|
|
539
|
+
* `navState`, which the tree renders with and the router's record of the
|
|
540
|
+
* displayed tree keeps (browser-entry/router-init.ts `publishTree`).
|
|
541
|
+
*
|
|
430
542
|
* Nothing is written until `commit()` runs, and on a transitioned
|
|
431
543
|
* navigation it runs only once the transition is known to have won — see
|
|
432
544
|
* `renderViaTransition` and `NavigationRoot`. A navigation superseded
|
|
@@ -451,11 +563,11 @@ function createNavigationCommitter(deps) {
|
|
|
451
563
|
const segmentInfo = cacheable ? opts.segmentInfo : [];
|
|
452
564
|
if (segmentInfo && segmentInfo.length > 0) updateSegmentCache(segmentInfo);
|
|
453
565
|
else if (segmentInfo?.length === 0 || opts.clearSegmentCacheOnEmpty) segmentCache.clear();
|
|
454
|
-
|
|
566
|
+
committedSegmentInfo = storedSegmentInfo(segmentInfo) ?? null;
|
|
455
567
|
historyStack.push(url, {
|
|
456
568
|
payload,
|
|
457
569
|
params: opts.params,
|
|
458
|
-
segmentInfo:
|
|
570
|
+
segmentInfo: committedSegmentInfo
|
|
459
571
|
});
|
|
460
572
|
}
|
|
461
573
|
};
|
|
@@ -491,6 +603,6 @@ function StatusPageMarker({ children }) {
|
|
|
491
603
|
return children;
|
|
492
604
|
}
|
|
493
605
|
//#endregion
|
|
494
|
-
export {
|
|
606
|
+
export { routerUrlKey as a, prefetchScopeOf as c, parseRouterUrl as i, TIMBER_ERROR_HEADER as l, createNavigationCommitter as n, PrefetchCache as o, isPartialNavigation as r, SegmentCache as s, StatusPageMarker as t };
|
|
495
607
|
|
|
496
|
-
//# sourceMappingURL=status-page-marker-
|
|
608
|
+
//# sourceMappingURL=status-page-marker-gaihi0KZ.js.map
|