@timber-js/app 0.2.0-alpha.185 → 0.2.0-alpha.186
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/{actions-O_LsyCE4.js → actions-C-Rw9vPc.js} +3 -3
- package/dist/_chunks/{actions-O_LsyCE4.js.map → actions-C-Rw9vPc.js.map} +1 -1
- package/dist/_chunks/als-slots-mFweg276.js +27 -0
- package/dist/_chunks/als-slots-mFweg276.js.map +1 -0
- package/dist/_chunks/base-path-DaQrzbez.js +80 -0
- package/dist/_chunks/base-path-DaQrzbez.js.map +1 -0
- package/dist/_chunks/build-manifest-DWppEdLB.js +86 -0
- package/dist/_chunks/build-manifest-DWppEdLB.js.map +1 -0
- package/dist/_chunks/build-output-helper-C3DrfzZR.js +369 -0
- package/dist/_chunks/build-output-helper-C3DrfzZR.js.map +1 -0
- package/dist/_chunks/{cache-api-B-lhk9p4.js → cache-api-Cd0VZ_Pd.js} +3 -3
- package/dist/_chunks/{cache-api-B-lhk9p4.js.map → cache-api-Cd0VZ_Pd.js.map} +1 -1
- package/dist/_chunks/cli-schema-sync-CKgHC2MB.js +1857 -0
- package/dist/_chunks/cli-schema-sync-CKgHC2MB.js.map +1 -0
- package/dist/_chunks/{cloudflare-CnT5Lr7U.js → cloudflare-Cs0uZXea.js} +89 -12
- package/dist/_chunks/{cloudflare-CnT5Lr7U.js.map → cloudflare-Cs0uZXea.js.map} +1 -1
- package/dist/_chunks/error-boundary-DpYRI_I1.js +330 -0
- package/dist/_chunks/error-boundary-DpYRI_I1.js.map +1 -0
- package/dist/_chunks/{fast-hash-D6hIVt1Y.js → fast-hash-C-tVYrLb.js} +6 -1
- package/dist/_chunks/fast-hash-C-tVYrLb.js.map +1 -0
- package/dist/_chunks/fs-identity-D7vb6GdI.js +208 -0
- package/dist/_chunks/fs-identity-D7vb6GdI.js.map +1 -0
- package/dist/_chunks/{logger-AWfuX-KJ.js → logger-N7e5auP0.js} +9 -13
- package/dist/_chunks/logger-N7e5auP0.js.map +1 -0
- package/dist/_chunks/navigation-root-B29qg0_T.js +274 -0
- package/dist/_chunks/navigation-root-B29qg0_T.js.map +1 -0
- package/dist/_chunks/param-value-C8TNYchQ.js +66 -0
- package/dist/_chunks/param-value-C8TNYchQ.js.map +1 -0
- package/dist/_chunks/{plugin-context---kTF5v8.js → plugin-context-DEGLSJs3.js} +2 -1
- package/dist/_chunks/plugin-context-DEGLSJs3.js.map +1 -0
- package/dist/_chunks/{router-ref-CtmF-aPv.js → router-ref-DuYuV_0Q.js} +2 -2
- package/dist/_chunks/router-ref-DuYuV_0Q.js.map +1 -0
- package/dist/_chunks/rsc-cache-key-DD0fl_-s.js +243 -0
- package/dist/_chunks/rsc-cache-key-DD0fl_-s.js.map +1 -0
- package/dist/_chunks/rsc-error-envelope-tT5PJs4q.js +40 -0
- package/dist/_chunks/rsc-error-envelope-tT5PJs4q.js.map +1 -0
- package/dist/_chunks/rsc-payload-path-B_LBodc2.js +48 -0
- package/dist/_chunks/rsc-payload-path-B_LBodc2.js.map +1 -0
- package/dist/_chunks/{segment-classify-Byy425ng.js → segment-classify-C539Pa2O.js} +23 -2
- package/dist/_chunks/{segment-classify-Byy425ng.js.map → segment-classify-C539Pa2O.js.map} +1 -1
- package/dist/_chunks/{canonicalize-DQHyFClh.js → segment-keys-BawYuNFO.js} +61 -2
- package/dist/_chunks/segment-keys-BawYuNFO.js.map +1 -0
- package/dist/_chunks/slot-params-BCTmZkQB.js +76 -0
- package/dist/_chunks/slot-params-BCTmZkQB.js.map +1 -0
- package/dist/_chunks/{ssr-data-BOWsq18U.js → ssr-data-14MXm7Pj.js} +17 -2
- package/dist/_chunks/ssr-data-14MXm7Pj.js.map +1 -0
- package/dist/_chunks/use-segment-params-ClyUNq4d.js +128 -0
- package/dist/_chunks/use-segment-params-ClyUNq4d.js.map +1 -0
- package/dist/_chunks/{walkers-_6zKFlch.js → walkers-BhhwI9TD.js} +21 -87
- package/dist/_chunks/walkers-BhhwI9TD.js.map +1 -0
- package/dist/adapters/build-output-helper.d.ts +37 -0
- package/dist/adapters/build-output-helper.d.ts.map +1 -1
- package/dist/adapters/cloudflare-dev.js +1 -1
- package/dist/adapters/cloudflare-kv-cache.js +1 -1
- package/dist/adapters/cloudflare.d.ts.map +1 -1
- package/dist/adapters/cloudflare.js +1 -1
- package/dist/adapters/fs-identity.d.ts +64 -0
- package/dist/adapters/fs-identity.d.ts.map +1 -0
- package/dist/adapters/nitro.d.ts.map +1 -1
- package/dist/adapters/nitro.js +2 -3
- package/dist/adapters/nitro.js.map +1 -1
- package/dist/adapters/shared.d.ts +57 -1
- package/dist/adapters/shared.d.ts.map +1 -1
- package/dist/adapters/types.d.ts +13 -1
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/cache/fast-hash.d.ts +5 -0
- package/dist/cache/fast-hash.d.ts.map +1 -1
- package/dist/cache/index.js +1 -1
- package/dist/cli.js +2 -2
- package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -1
- package/dist/client/browser-entry/hydrate.d.ts +20 -9
- package/dist/client/browser-entry/hydrate.d.ts.map +1 -1
- package/dist/client/browser-entry/post-hydration.d.ts +4 -1
- package/dist/client/browser-entry/post-hydration.d.ts.map +1 -1
- package/dist/client/browser-entry/router-init.d.ts +3 -0
- package/dist/client/browser-entry/router-init.d.ts.map +1 -1
- package/dist/client/browser-entry/rsc-stream.d.ts +8 -0
- package/dist/client/browser-entry/rsc-stream.d.ts.map +1 -1
- package/dist/client/error-boundary.d.ts +1 -0
- package/dist/client/error-boundary.d.ts.map +1 -1
- package/dist/client/error-boundary.js +1 -162
- package/dist/client/history.d.ts +13 -6
- package/dist/client/history.d.ts.map +1 -1
- package/dist/client/index.js +18 -11
- package/dist/client/index.js.map +1 -1
- package/dist/client/internal.d.ts +4 -3
- package/dist/client/internal.d.ts.map +1 -1
- package/dist/client/internal.js +865 -306
- package/dist/client/internal.js.map +1 -1
- package/dist/client/link.d.ts.map +1 -1
- package/dist/client/navigation-api.d.ts +2 -2
- package/dist/client/navigation-commit.d.ts +71 -0
- package/dist/client/navigation-commit.d.ts.map +1 -0
- package/dist/client/navigation-context.d.ts +37 -20
- package/dist/client/navigation-context.d.ts.map +1 -1
- package/dist/client/navigation-root.d.ts +63 -23
- package/dist/client/navigation-root.d.ts.map +1 -1
- package/dist/client/params-context.d.ts +81 -0
- package/dist/client/params-context.d.ts.map +1 -0
- package/dist/client/router-effects.d.ts +129 -0
- package/dist/client/router-effects.d.ts.map +1 -0
- package/dist/client/router-lifecycle.d.ts +55 -0
- package/dist/client/router-lifecycle.d.ts.map +1 -0
- package/dist/client/router-pipeline.d.ts +84 -0
- package/dist/client/router-pipeline.d.ts.map +1 -0
- package/dist/client/router-ref.d.ts +1 -1
- package/dist/client/router-ref.d.ts.map +1 -1
- package/dist/client/router-skew.d.ts +21 -0
- package/dist/client/router-skew.d.ts.map +1 -0
- package/dist/client/router-types.d.ts +207 -0
- package/dist/client/router-types.d.ts.map +1 -0
- package/dist/client/router.d.ts +1 -182
- package/dist/client/router.d.ts.map +1 -1
- package/dist/client/rsc-fetch.d.ts +38 -25
- package/dist/client/rsc-fetch.d.ts.map +1 -1
- package/dist/client/segment-cache.d.ts +79 -34
- package/dist/client/segment-cache.d.ts.map +1 -1
- package/dist/client/ssr-data.d.ts +6 -0
- package/dist/client/ssr-data.d.ts.map +1 -1
- package/dist/client/stale-client.d.ts +69 -0
- package/dist/client/stale-client.d.ts.map +1 -0
- package/dist/client/state.d.ts +10 -1
- package/dist/client/state.d.ts.map +1 -1
- package/dist/client/top-loader.d.ts +2 -1
- package/dist/client/top-loader.d.ts.map +1 -1
- package/dist/client/unload-guard.d.ts +5 -0
- package/dist/client/unload-guard.d.ts.map +1 -1
- package/dist/client/use-cookie.d.ts.map +1 -1
- package/dist/client/use-router.d.ts +1 -1
- package/dist/client/use-segment-params.d.ts +18 -8
- package/dist/client/use-segment-params.d.ts.map +1 -1
- package/dist/cookies/index.js +3 -3
- package/dist/cookies/index.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +906 -321
- package/dist/index.js.map +1 -1
- package/dist/plugin-context.d.ts +31 -0
- package/dist/plugin-context.d.ts.map +1 -1
- package/dist/plugins/adapter-build.d.ts.map +1 -1
- package/dist/plugins/build-manifest.d.ts +1 -1
- package/dist/plugins/build-manifest.d.ts.map +1 -1
- package/dist/plugins/entries.d.ts.map +1 -1
- package/dist/plugins/fonts.d.ts.map +1 -1
- package/dist/plugins/request-dep/analysis.d.ts +106 -0
- package/dist/plugins/request-dep/analysis.d.ts.map +1 -0
- package/dist/plugins/request-dep/index.d.ts +75 -0
- package/dist/plugins/request-dep/index.d.ts.map +1 -0
- package/dist/plugins/request-dep/origin.d.ts +61 -0
- package/dist/plugins/request-dep/origin.d.ts.map +1 -0
- package/dist/plugins/routing.d.ts +9 -0
- package/dist/plugins/routing.d.ts.map +1 -1
- package/dist/plugins/static-build.d.ts +136 -8
- package/dist/plugins/static-build.d.ts.map +1 -1
- package/dist/routing/codegen-types.d.ts +18 -0
- package/dist/routing/codegen-types.d.ts.map +1 -1
- package/dist/routing/codegen.d.ts.map +1 -1
- package/dist/routing/collision-probe.d.ts +104 -0
- package/dist/routing/collision-probe.d.ts.map +1 -0
- package/dist/routing/collision-spaces.d.ts +26 -0
- package/dist/routing/collision-spaces.d.ts.map +1 -0
- package/dist/routing/index.js +3 -3
- package/dist/routing/interception.d.ts +235 -6
- package/dist/routing/interception.d.ts.map +1 -1
- package/dist/routing/manifest-codegen.d.ts.map +1 -1
- package/dist/routing/scanner.d.ts.map +1 -1
- package/dist/routing/segment-classify.d.ts +33 -0
- package/dist/routing/segment-classify.d.ts.map +1 -1
- package/dist/routing/segment-keys.d.ts +95 -0
- package/dist/routing/segment-keys.d.ts.map +1 -0
- package/dist/routing/slot-placement.d.ts +48 -0
- package/dist/routing/slot-placement.d.ts.map +1 -0
- package/dist/routing/walkers.d.ts +6 -0
- package/dist/routing/walkers.d.ts.map +1 -1
- package/dist/search-params/define.d.ts +0 -6
- package/dist/search-params/define.d.ts.map +1 -1
- package/dist/search-params/index.js +176 -2
- package/dist/search-params/index.js.map +1 -1
- package/dist/segment-params/define.d.ts +0 -6
- package/dist/segment-params/define.d.ts.map +1 -1
- package/dist/segment-params/index.js +69 -1
- package/dist/segment-params/index.js.map +1 -0
- package/dist/server/actions.d.ts +6 -3
- package/dist/server/actions.d.ts.map +1 -1
- package/dist/server/als-registry.d.ts +2 -1
- package/dist/server/als-registry.d.ts.map +1 -1
- package/dist/server/build-manifest.d.ts +13 -1
- package/dist/server/build-manifest.d.ts.map +1 -1
- package/dist/server/chain-url-parts.d.ts +82 -0
- package/dist/server/chain-url-parts.d.ts.map +1 -0
- package/dist/server/children-interception.d.ts +49 -0
- package/dist/server/children-interception.d.ts.map +1 -0
- package/dist/server/default-status-page.d.ts +45 -0
- package/dist/server/default-status-page.d.ts.map +1 -0
- package/dist/server/deny-renderer.d.ts +14 -3
- package/dist/server/deny-renderer.d.ts.map +1 -1
- package/dist/server/head-response.d.ts +35 -0
- package/dist/server/head-response.d.ts.map +1 -0
- package/dist/server/index.js +2 -2
- package/dist/server/internal.js +393 -212
- package/dist/server/internal.js.map +1 -1
- package/dist/server/param-coercion.d.ts +10 -1
- package/dist/server/param-coercion.d.ts.map +1 -1
- package/dist/server/pipeline-helpers.d.ts +0 -18
- package/dist/server/pipeline-helpers.d.ts.map +1 -1
- package/dist/server/pipeline-interception.d.ts +59 -9
- package/dist/server/pipeline-interception.d.ts.map +1 -1
- package/dist/server/pipeline-outcome.d.ts.map +1 -1
- package/dist/server/pipeline-phases.d.ts.map +1 -1
- package/dist/server/pipeline.d.ts +11 -0
- package/dist/server/pipeline.d.ts.map +1 -1
- package/dist/server/publish-params.d.ts +33 -0
- package/dist/server/publish-params.d.ts.map +1 -0
- package/dist/server/request-context.d.ts +48 -0
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/route-element-builder.d.ts +32 -2
- 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 +13 -0
- package/dist/server/route-matcher.d.ts.map +1 -1
- package/dist/server/rsc-cache-key-guard.d.ts +78 -0
- package/dist/server/rsc-cache-key-guard.d.ts.map +1 -0
- package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
- package/dist/server/rsc-entry/error-renderer.d.ts +14 -2
- package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/helpers.d.ts +2 -10
- package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
- package/dist/server/rsc-entry/index.d.ts.map +1 -1
- package/dist/server/rsc-entry/render-route.d.ts.map +1 -1
- package/dist/server/rsc-entry/rsc-payload.d.ts +3 -2
- package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
- package/dist/server/rsc-entry/rsc-stream.d.ts +3 -2
- package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-renderer.d.ts +2 -0
- package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
- package/dist/server/skippable-prefix.d.ts +23 -0
- package/dist/server/skippable-prefix.d.ts.map +1 -0
- package/dist/server/slot-interception.d.ts +80 -0
- package/dist/server/slot-interception.d.ts.map +1 -0
- package/dist/server/slot-resolver.d.ts +70 -8
- package/dist/server/slot-resolver.d.ts.map +1 -1
- package/dist/server/ssr-bridge-types.d.ts +6 -0
- package/dist/server/ssr-bridge-types.d.ts.map +1 -1
- package/dist/server/ssr-entry.d.ts.map +1 -1
- package/dist/server/ssr-wrappers.d.ts +24 -13
- package/dist/server/ssr-wrappers.d.ts.map +1 -1
- package/dist/server/state-tree-diff.d.ts +6 -27
- package/dist/server/state-tree-diff.d.ts.map +1 -1
- package/dist/server/static-generator.d.ts +6 -0
- package/dist/server/static-generator.d.ts.map +1 -1
- package/dist/server/static-not-found.d.ts +52 -0
- package/dist/server/static-not-found.d.ts.map +1 -0
- package/dist/shared/als-slots.d.ts +41 -0
- package/dist/shared/als-slots.d.ts.map +1 -0
- package/dist/shared/base-path.d.ts +56 -0
- package/dist/shared/base-path.d.ts.map +1 -0
- package/dist/shared/param-value.d.ts +80 -0
- package/dist/shared/param-value.d.ts.map +1 -0
- package/dist/shared/payload-root.d.ts +108 -0
- package/dist/shared/payload-root.d.ts.map +1 -0
- package/dist/shared/rsc-cache-key.d.ts +163 -0
- package/dist/shared/rsc-cache-key.d.ts.map +1 -0
- package/dist/shared/rsc-error-envelope.d.ts +25 -0
- package/dist/shared/rsc-error-envelope.d.ts.map +1 -0
- package/dist/shared/rsc-manifest.d.ts +28 -0
- package/dist/shared/rsc-manifest.d.ts.map +1 -0
- package/dist/shared/rsc-payload-path.d.ts +42 -0
- package/dist/shared/rsc-payload-path.d.ts.map +1 -0
- package/dist/shared/segment-info.d.ts +59 -0
- package/dist/shared/segment-info.d.ts.map +1 -0
- package/dist/shared/slot-params.d.ts +51 -0
- package/dist/shared/slot-params.d.ts.map +1 -0
- package/dist/shared/static-platform-files.d.ts +71 -0
- package/dist/shared/static-platform-files.d.ts.map +1 -0
- package/docs/api/31-api-client.mdx +4 -2
- package/docs/learn/02-pages-and-layouts.mdx +1 -1
- package/docs/learn/11-error-handling.mdx +2 -0
- package/docs/learn/12-client-navigation.mdx +2 -2
- package/docs/learn/14-deploying.mdx +23 -0
- package/docs/more/01-advanced-routing.mdx +172 -2
- package/docs/more/04-metadata-and-fonts.mdx +1 -1
- package/package.json +2 -2
- package/src/adapters/build-output-helper.ts +116 -3
- package/src/adapters/cloudflare.ts +86 -11
- package/src/adapters/fs-identity.ts +156 -0
- package/src/adapters/nitro.ts +6 -6
- package/src/adapters/shared.ts +196 -21
- package/src/adapters/types.ts +13 -1
- package/src/cache/fast-hash.ts +5 -0
- package/src/client/browser-entry/action-dispatch.ts +9 -4
- package/src/client/browser-entry/hydrate.ts +40 -29
- package/src/client/browser-entry/index.ts +15 -1
- package/src/client/browser-entry/post-hydration.ts +10 -9
- package/src/client/browser-entry/router-init.ts +104 -48
- package/src/client/browser-entry/rsc-stream.ts +11 -2
- package/src/client/error-boundary.tsx +20 -15
- package/src/client/history.ts +13 -6
- package/src/client/internal.ts +4 -3
- package/src/client/link.tsx +55 -8
- package/src/client/navigation-api.ts +3 -3
- package/src/client/navigation-commit.ts +174 -0
- package/src/client/navigation-context.ts +40 -67
- package/src/client/navigation-root.tsx +326 -101
- package/src/client/params-context.ts +192 -0
- package/src/client/router-effects.ts +231 -0
- package/src/client/router-lifecycle.ts +288 -0
- package/src/client/router-pipeline.ts +389 -0
- package/src/client/router-ref.ts +1 -1
- package/src/client/router-skew.ts +30 -0
- package/src/client/router-types.ts +230 -0
- package/src/client/router.ts +242 -707
- package/src/client/rsc-fetch.ts +169 -102
- package/src/client/segment-cache.ts +121 -44
- package/src/client/ssr-data.ts +6 -0
- package/src/client/stale-client.ts +191 -0
- package/src/client/state.ts +14 -1
- package/src/client/top-loader.tsx +2 -1
- package/src/client/unload-guard.ts +34 -2
- package/src/client/use-cookie.ts +9 -2
- package/src/client/use-router.ts +1 -1
- package/src/client/use-segment-params.ts +41 -18
- package/src/index.ts +5 -1
- package/src/plugin-context.ts +32 -0
- package/src/plugins/adapter-build.ts +4 -0
- package/src/plugins/build-manifest.ts +34 -13
- package/src/plugins/entries.ts +4 -0
- package/src/plugins/fonts.ts +11 -8
- package/src/plugins/request-dep/analysis.ts +447 -0
- package/src/plugins/request-dep/index.ts +376 -0
- package/src/plugins/request-dep/origin.ts +310 -0
- package/src/plugins/routing.ts +59 -2
- package/src/plugins/static-build.ts +315 -73
- package/src/routing/codegen-types.ts +18 -0
- package/src/routing/codegen.ts +50 -10
- package/src/routing/collision-probe.ts +438 -0
- package/src/routing/collision-spaces.ts +281 -0
- package/src/routing/interception.ts +896 -50
- package/src/routing/manifest-codegen.ts +5 -3
- package/src/routing/scanner.ts +114 -89
- package/src/routing/segment-classify.ts +57 -0
- package/src/routing/segment-keys.ts +146 -0
- package/src/routing/slot-placement.ts +97 -0
- package/src/routing/walkers.ts +8 -0
- package/src/search-params/define.ts +6 -29
- package/src/segment-params/define.ts +4 -27
- package/src/server/action-handler.ts +3 -1
- package/src/server/actions.ts +6 -3
- package/src/server/als-registry.ts +2 -1
- package/src/server/build-manifest.ts +14 -1
- package/src/server/chain-url-parts.ts +163 -0
- package/src/server/children-interception.ts +115 -0
- package/src/server/default-status-page.ts +127 -0
- package/src/server/deny-renderer.ts +81 -20
- package/src/server/head-response.ts +54 -0
- package/src/server/param-coercion.ts +48 -18
- package/src/server/pipeline-helpers.ts +0 -45
- package/src/server/pipeline-interception.ts +81 -32
- package/src/server/pipeline-outcome.ts +2 -4
- package/src/server/pipeline-phases.ts +68 -16
- package/src/server/pipeline.ts +57 -10
- package/src/server/prebuilt-runtime.ts +4 -4
- package/src/server/publish-params.ts +42 -0
- package/src/server/request-context.ts +97 -18
- package/src/server/route-element-builder.ts +89 -98
- package/src/server/route-handler.ts +8 -8
- package/src/server/route-matcher.ts +21 -9
- package/src/server/rsc-cache-key-guard.ts +170 -0
- package/src/server/rsc-entry/api-handler.ts +6 -8
- package/src/server/rsc-entry/error-renderer.ts +64 -25
- package/src/server/rsc-entry/helpers.ts +31 -16
- package/src/server/rsc-entry/index.ts +36 -28
- package/src/server/rsc-entry/render-route.ts +9 -4
- package/src/server/rsc-entry/revalidate-renderer.ts +1 -1
- package/src/server/rsc-entry/rsc-payload.ts +14 -25
- package/src/server/rsc-entry/rsc-stream.ts +4 -3
- package/src/server/rsc-entry/ssr-renderer.ts +13 -9
- package/src/server/skippable-prefix.ts +92 -0
- package/src/server/slot-interception.ts +168 -0
- package/src/server/slot-resolver.ts +253 -156
- package/src/server/ssr-bridge-types.ts +6 -0
- package/src/server/ssr-entry.ts +12 -4
- package/src/server/ssr-wrappers.tsx +33 -32
- package/src/server/state-tree-diff.ts +14 -55
- package/src/server/static-generator.ts +65 -27
- package/src/server/static-not-found.ts +134 -0
- package/src/shared/als-slots.ts +72 -0
- package/src/shared/base-path.ts +80 -0
- package/src/shared/param-value.ts +244 -0
- package/src/shared/payload-root.ts +151 -0
- package/src/shared/rsc-cache-key.ts +269 -0
- package/src/shared/rsc-error-envelope.ts +31 -0
- package/src/shared/rsc-manifest.ts +29 -0
- package/src/shared/rsc-payload-path.ts +45 -0
- package/src/shared/segment-info.ts +60 -0
- package/src/shared/slot-params.ts +111 -0
- package/src/shared/static-platform-files.ts +75 -0
- package/dist/_chunks/build-output-helper-DOGYFb_X.js +0 -196
- package/dist/_chunks/build-output-helper-DOGYFb_X.js.map +0 -1
- package/dist/_chunks/canonicalize-DQHyFClh.js.map +0 -1
- package/dist/_chunks/cli-schema-sync-BTWEKJXo.js +0 -668
- package/dist/_chunks/cli-schema-sync-BTWEKJXo.js.map +0 -1
- package/dist/_chunks/define-COtkxMRT.js +0 -191
- package/dist/_chunks/define-COtkxMRT.js.map +0 -1
- package/dist/_chunks/define-c4au4I9R.js +0 -82
- package/dist/_chunks/define-c4au4I9R.js.map +0 -1
- package/dist/_chunks/fast-hash-D6hIVt1Y.js.map +0 -1
- package/dist/_chunks/logger-AWfuX-KJ.js.map +0 -1
- package/dist/_chunks/navigation-root-bUDZLw74.js +0 -124
- package/dist/_chunks/navigation-root-bUDZLw74.js.map +0 -1
- package/dist/_chunks/plugin-context---kTF5v8.js.map +0 -1
- package/dist/_chunks/router-ref-CtmF-aPv.js.map +0 -1
- package/dist/_chunks/ssr-data-BOWsq18U.js.map +0 -1
- package/dist/_chunks/use-segment-params-D1CzlgBo.js +0 -151
- package/dist/_chunks/use-segment-params-D1CzlgBo.js.map +0 -1
- package/dist/_chunks/walkers-_6zKFlch.js.map +0 -1
- package/dist/client/error-boundary.js.map +0 -1
- package/dist/plugins/request-dep.d.ts +0 -32
- package/dist/plugins/request-dep.d.ts.map +0 -1
- package/src/plugins/request-dep.ts +0 -499
package/src/client/rsc-fetch.ts
CHANGED
|
@@ -11,14 +11,40 @@
|
|
|
11
11
|
* See design/19-client-navigation.md §"RSC Payload Handling"
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import
|
|
15
|
-
|
|
14
|
+
import {
|
|
15
|
+
rscCacheKey,
|
|
16
|
+
recordLookup,
|
|
17
|
+
randomRscCacheKey,
|
|
18
|
+
RSC_KEY_PARAM,
|
|
19
|
+
} from '../shared/rsc-cache-key.js';
|
|
20
|
+
import type { RscManifest, RscManifestEntry } from '../shared/rsc-manifest.js';
|
|
21
|
+
import {
|
|
22
|
+
splitPayloadRoot,
|
|
23
|
+
readPublishedParams,
|
|
24
|
+
type PublishedParams,
|
|
25
|
+
} from '../shared/payload-root.js';
|
|
26
|
+
import { normalizeBasePath, stripBasePath, withBasePath } from '../shared/base-path.js';
|
|
27
|
+
import { rscPayloadPath } from '../shared/rsc-payload-path.js';
|
|
28
|
+
import type { SegmentInfo, StateTree } from '../shared/segment-info.js';
|
|
29
|
+
import { TIMBER_ERROR_HEADER } from '../shared/rsc-error-envelope.js';
|
|
30
|
+
import type { RouterDeps } from './router-types.js';
|
|
16
31
|
|
|
17
32
|
// ─── Types ───────────────────────────────────────────────────────
|
|
18
33
|
|
|
19
34
|
/** Result of fetching an RSC payload — includes segment metadata. */
|
|
20
35
|
export interface FetchResult {
|
|
36
|
+
/** The renderable tree, split off the payload root. */
|
|
21
37
|
payload: unknown;
|
|
38
|
+
/**
|
|
39
|
+
* The params the same payload published beside that tree.
|
|
40
|
+
*
|
|
41
|
+
* Not a separate channel: both fields come out of one `splitPayloadRoot`
|
|
42
|
+
* call on one decoded root, so a response cannot deliver a tree and another
|
|
43
|
+
* route's params. They used to arrive on their own header, which is how a
|
|
44
|
+
* navigation could render one route and publish another's (TIM-1285,
|
|
45
|
+
* TIM-1294).
|
|
46
|
+
*/
|
|
47
|
+
params: PublishedParams | Promise<PublishedParams>;
|
|
22
48
|
/**
|
|
23
49
|
* Promise that settles when the RSC decode completes or fails.
|
|
24
50
|
* The payload thenable is NOT awaited before returning (for streaming),
|
|
@@ -29,8 +55,6 @@ export interface FetchResult {
|
|
|
29
55
|
decodePromise: Promise<void> | null;
|
|
30
56
|
/** Segment metadata from X-Timber-Segments header for populating the segment cache. */
|
|
31
57
|
segmentInfo: SegmentInfo[] | null;
|
|
32
|
-
/** Route params from X-Timber-Params header for populating useSegmentParams(). */
|
|
33
|
-
params: Record<string, string | string[]> | null;
|
|
34
58
|
/** Segment paths that were skipped by the server (for client-side merging). */
|
|
35
59
|
skippedSegments: string[] | null;
|
|
36
60
|
}
|
|
@@ -42,31 +66,39 @@ export const RSC_CONTENT_TYPE = 'text/x-component';
|
|
|
42
66
|
// ─── URL Helpers ─────────────────────────────────────────────────
|
|
43
67
|
|
|
44
68
|
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
69
|
+
* Append a `_rsc=<key>` query parameter to the URL (TIM-1268).
|
|
70
|
+
*
|
|
71
|
+
* The key is a deterministic hash of the RSC request headers, so identical
|
|
72
|
+
* requests share a URL and the payload becomes cacheable. It also keeps the
|
|
73
|
+
* document and the payload on different URLs, so a shared cache cannot
|
|
74
|
+
* return HTML for an RSC request (or vice versa) even where `Vary` is
|
|
75
|
+
* opt-in configuration rather than default behaviour — Cloudflare and
|
|
76
|
+
* CloudFront both. See GHSA-wfc6-r584-vfw7, design/13-security.md.
|
|
77
|
+
*
|
|
78
|
+
* The origin recomputes this key from the received headers and refuses to
|
|
79
|
+
* let a mismatched response be shared-cached, so a caller cannot claim
|
|
80
|
+
* another client's key while sending its own headers.
|
|
81
|
+
*
|
|
82
|
+
* Falls back to a random value when no key can be derived — `crypto.subtle`
|
|
83
|
+
* is absent in non-secure browsing contexts (plain `http://` on a LAN
|
|
84
|
+
* address). Dropping the parameter instead would put the payload back on
|
|
85
|
+
* the document URL, where a query-keyed cache that ignores `Vary` could
|
|
86
|
+
* store a Flight response under `/about` and serve it to an HTML
|
|
87
|
+
* navigation. The random parameter this feature replaced did separate those
|
|
88
|
+
* representations, and the fallback must not be worse than what it
|
|
89
|
+
* replaced. The origin cannot verify a random key, so it refuses to
|
|
90
|
+
* share-cache the response — which is exactly the old behaviour, where a
|
|
91
|
+
* unique URL was never a cache hit anyway.
|
|
61
92
|
*
|
|
62
93
|
* Strips any #fragment before appending — fragments are client-only and
|
|
63
94
|
* fetch() discards them, so _rsc would land inside the hash and be lost.
|
|
64
95
|
*/
|
|
65
|
-
function appendRscParam(url: string): string {
|
|
96
|
+
async function appendRscParam(url: string, headers: Record<string, string>): Promise<string> {
|
|
66
97
|
const hashIndex = url.indexOf('#');
|
|
67
98
|
const urlWithoutHash = hashIndex === -1 ? url : url.slice(0, hashIndex);
|
|
99
|
+
const key = (await rscCacheKey(recordLookup(headers))) ?? randomRscCacheKey();
|
|
68
100
|
const separator = urlWithoutHash.includes('?') ? '&' : '?';
|
|
69
|
-
return `${urlWithoutHash}${separator}
|
|
101
|
+
return `${urlWithoutHash}${separator}${RSC_KEY_PARAM}=${key}`;
|
|
70
102
|
}
|
|
71
103
|
|
|
72
104
|
// ─── Deployment ID ───────────────────────────────────────────────
|
|
@@ -88,6 +120,30 @@ export function getClientDeploymentId(): string | null {
|
|
|
88
120
|
return clientDeploymentId;
|
|
89
121
|
}
|
|
90
122
|
|
|
123
|
+
// ─── Base Path ───────────────────────────────────────────────────
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* The deployment base path (Vite's resolved `base`), normalized.
|
|
127
|
+
* Set at bootstrap from `virtual:timber-config`; `'/'` unless the app is
|
|
128
|
+
* deployed under a sub-path. See design/11-platform.md, TIM-1261.
|
|
129
|
+
*
|
|
130
|
+
* **The base is applied in exactly one place: at fetch time**
|
|
131
|
+
* (`toStaticRscUrl`). The static build writes the RSC manifest with
|
|
132
|
+
* root-relative keys *and* root-relative URLs, so the generated site stays
|
|
133
|
+
* relocatable and there is no second copy of the base to drift from this one.
|
|
134
|
+
*/
|
|
135
|
+
let basePath = '/';
|
|
136
|
+
|
|
137
|
+
/** Set the deployment base path. Called once at bootstrap. */
|
|
138
|
+
export function setBasePath(base: string | undefined): void {
|
|
139
|
+
basePath = normalizeBasePath(base);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** Get the normalized deployment base path. @internal Exported for testing. */
|
|
143
|
+
export function getBasePath(): string {
|
|
144
|
+
return basePath;
|
|
145
|
+
}
|
|
146
|
+
|
|
91
147
|
// ─── Static Mode ────────────────────────────────────────────────
|
|
92
148
|
|
|
93
149
|
/**
|
|
@@ -107,20 +163,10 @@ export function isStaticMode(): boolean {
|
|
|
107
163
|
}
|
|
108
164
|
|
|
109
165
|
/**
|
|
110
|
-
* RSC manifest
|
|
111
|
-
*
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
url: string;
|
|
115
|
-
params?: Record<string, string | string[]>;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
type RscManifest = Record<string, RscManifestEntry>;
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* RSC manifest mapping unhashed → hashed URLs + params. Populated from
|
|
122
|
-
* `window.__TIMBER_RSC_MANIFEST__` (injected into HTML during
|
|
123
|
-
* static generation). See TIM-1254, TIM-1255.
|
|
166
|
+
* RSC manifest mapping unhashed → content-hashed `.rsc` URLs. Populated from
|
|
167
|
+
* `window.__TIMBER_RSC_MANIFEST__` (injected into HTML during static
|
|
168
|
+
* generation). Shape shared with the static build that writes it — see
|
|
169
|
+
* `shared/rsc-manifest.ts`. See TIM-1254.
|
|
124
170
|
*/
|
|
125
171
|
let rscManifest: RscManifest | null = null;
|
|
126
172
|
|
|
@@ -137,24 +183,45 @@ export function setRscManifest(manifest: RscManifest | null): void {
|
|
|
137
183
|
rscManifest = manifest;
|
|
138
184
|
}
|
|
139
185
|
|
|
186
|
+
/** A resolved static payload target: the URL to fetch, and how it was resolved. */
|
|
187
|
+
interface StaticRscTarget {
|
|
188
|
+
/** Fetchable URL — base-prefixed. */
|
|
189
|
+
url: string;
|
|
190
|
+
/**
|
|
191
|
+
* True when the RSC manifest supplied a content-hashed filename. The hash
|
|
192
|
+
* guarantees freshness, so no `_rsc` cache key is appended (TIM-1254).
|
|
193
|
+
*/
|
|
194
|
+
hashed: boolean;
|
|
195
|
+
}
|
|
196
|
+
|
|
140
197
|
/**
|
|
141
|
-
*
|
|
142
|
-
*
|
|
198
|
+
* Resolve a route URL to the `_rsc/*.rsc` file to fetch. The naming rule is
|
|
199
|
+
* `shared/rsc-payload-path.ts`, shared with the build that writes the files.
|
|
143
200
|
*
|
|
144
201
|
* When an RSC manifest is available (hashed filenames from TIM-1254),
|
|
145
202
|
* the manifest is consulted to resolve to the hashed path.
|
|
146
203
|
*
|
|
147
204
|
* / → /_rsc/index.rsc (or /_rsc/index-B7YxEKdN.rsc with manifest)
|
|
148
|
-
* /about → /_rsc/about.rsc (or /_rsc/about-C8ZzFLfO.rsc
|
|
149
|
-
* /blog/hello → /_rsc/blog/hello.rsc
|
|
205
|
+
* /about → /_rsc/about/index.rsc (or /_rsc/about/index-C8ZzFLfO.rsc)
|
|
206
|
+
* /blog/hello → /_rsc/blog/hello/index.rsc
|
|
207
|
+
*
|
|
208
|
+
* The manifest is written and read in route space (no base prefix), so the
|
|
209
|
+
* base is applied here — once, on the way out. See client/base-path.ts.
|
|
150
210
|
*/
|
|
151
|
-
function toStaticRscUrl(url: string):
|
|
211
|
+
function toStaticRscUrl(url: string): StaticRscTarget {
|
|
152
212
|
const unhashed = toUnhashedRscUrl(url);
|
|
153
|
-
|
|
213
|
+
const hashedUrl = manifestLookup(unhashed);
|
|
214
|
+
return { url: withBasePath(basePath, hashedUrl ?? unhashed), hashed: hashedUrl !== null };
|
|
154
215
|
}
|
|
155
216
|
|
|
156
217
|
/**
|
|
157
|
-
* Compute the unhashed _rsc/*.rsc
|
|
218
|
+
* Compute the unhashed `_rsc/*.rsc` path for a route URL.
|
|
219
|
+
*
|
|
220
|
+
* Returns a **route-space** path: the deployment base is stripped from the
|
|
221
|
+
* incoming URL and is NOT re-applied, because this value doubles as the RSC
|
|
222
|
+
* manifest key, and the manifest is base-less. `toStaticRscUrl` applies the
|
|
223
|
+
* base to whatever is actually fetched.
|
|
224
|
+
*
|
|
158
225
|
* @internal Exported for testing.
|
|
159
226
|
*/
|
|
160
227
|
export function toUnhashedRscUrl(url: string): string {
|
|
@@ -163,13 +230,12 @@ export function toUnhashedRscUrl(url: string): string {
|
|
|
163
230
|
const hashEnd = hashIndex === -1 ? url.length : hashIndex;
|
|
164
231
|
const queryEnd = queryIndex === -1 ? url.length : queryIndex;
|
|
165
232
|
const end = Math.min(hashEnd, queryEnd);
|
|
166
|
-
let pathname = url.slice(0, end);
|
|
233
|
+
let pathname = stripBasePath(basePath, url.slice(0, end));
|
|
167
234
|
// Strip trailing slash (unless root) to match static build output naming
|
|
168
235
|
if (pathname.length > 1 && pathname.endsWith('/')) {
|
|
169
236
|
pathname = pathname.slice(0, -1);
|
|
170
237
|
}
|
|
171
|
-
|
|
172
|
-
return `/_rsc${rscPath}.rsc`;
|
|
238
|
+
return rscPayloadPath(pathname);
|
|
173
239
|
}
|
|
174
240
|
|
|
175
241
|
/**
|
|
@@ -196,13 +262,11 @@ function manifestLookup(key: string): string | null {
|
|
|
196
262
|
return manifestEntry(key)?.url ?? null;
|
|
197
263
|
}
|
|
198
264
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
return manifestEntry(key)?.params ?? null;
|
|
205
|
-
}
|
|
265
|
+
// The manifest used to inline each route's params, because a generated
|
|
266
|
+
// `.rsc` file carries no response headers and the header channel therefore
|
|
267
|
+
// did not exist on the static path (TIM-1255, TIM-1285). The `.rsc` file now
|
|
268
|
+
// carries them itself — they are props inside the payload — so the static
|
|
269
|
+
// path needs no special case at all.
|
|
206
270
|
|
|
207
271
|
// ─── Reload Signal ───────────────────────────────────────────────
|
|
208
272
|
|
|
@@ -222,8 +286,19 @@ export function checkReloadSignal(response: Response): boolean {
|
|
|
222
286
|
|
|
223
287
|
// ─── Header Builder ──────────────────────────────────────────────
|
|
224
288
|
|
|
289
|
+
/**
|
|
290
|
+
* Build the headers for an RSC payload request.
|
|
291
|
+
*
|
|
292
|
+
* **Every header added here is hashed into the payload URL** as the `_rsc`
|
|
293
|
+
* cache key (see `rscCacheKey`), and URLs are logged by proxies, CDNs, and
|
|
294
|
+
* origin access logs. So: no credentials, no session identifiers, no
|
|
295
|
+
* user-supplied content. `fnv1aHash` is a cache-key hash, not a KDF — a
|
|
296
|
+
* low-entropy secret would be recoverable from the URL by brute force.
|
|
297
|
+
* Authentication already travels on cookies, which are not part of this
|
|
298
|
+
* object and never enter the key.
|
|
299
|
+
*/
|
|
225
300
|
export function buildRscHeaders(
|
|
226
|
-
stateTree:
|
|
301
|
+
stateTree: StateTree | undefined,
|
|
227
302
|
currentUrl?: string
|
|
228
303
|
): Record<string, string> {
|
|
229
304
|
const headers: Record<string, string> = {
|
|
@@ -301,23 +376,6 @@ export function extractSkippedSegments(response: Response): string[] | null {
|
|
|
301
376
|
}
|
|
302
377
|
}
|
|
303
378
|
|
|
304
|
-
/**
|
|
305
|
-
* Extract route params from the X-Timber-Params response header.
|
|
306
|
-
* Returns null if the header is missing or malformed.
|
|
307
|
-
*
|
|
308
|
-
* Used to populate useSegmentParams() after client-side navigation.
|
|
309
|
-
*/
|
|
310
|
-
export function extractParams(response: Response): Record<string, string | string[]> | null {
|
|
311
|
-
const header = response.headers.get('X-Timber-Params');
|
|
312
|
-
if (!header) return null;
|
|
313
|
-
try {
|
|
314
|
-
return JSON.parse(header);
|
|
315
|
-
} catch {
|
|
316
|
-
warnMalformedHeader('X-Timber-Params', header);
|
|
317
|
-
return null;
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
|
|
321
379
|
// ─── Redirect Error ──────────────────────────────────────────────
|
|
322
380
|
|
|
323
381
|
/**
|
|
@@ -388,9 +446,10 @@ export class NonRscResponse extends Error {
|
|
|
388
446
|
* a `done` promise that resolves when the last chunk is read (or
|
|
389
447
|
* rejects if the stream errors).
|
|
390
448
|
*
|
|
391
|
-
*
|
|
392
|
-
*
|
|
393
|
-
*
|
|
449
|
+
* createFromFetch's thenable resolves on shell arrival, but callers need to
|
|
450
|
+
* know when the stream is fully decoded: that is what `navigateTransition`'s
|
|
451
|
+
* returned promise means, and what the router's pending store, the Navigation
|
|
452
|
+
* API deferred and `<Link>`'s `isPending` are all timed against.
|
|
394
453
|
*/
|
|
395
454
|
function trackStreamCompletion(body: ReadableStream<Uint8Array>): {
|
|
396
455
|
body: ReadableStream<Uint8Array>;
|
|
@@ -445,13 +504,23 @@ export async function fetchRscPayload(
|
|
|
445
504
|
// In static mode, fetch the pre-generated _rsc/*.rsc file directly
|
|
446
505
|
// instead of the route URL with Accept headers. Static hosts ignore
|
|
447
506
|
// Accept headers, so the route URL would return HTML.
|
|
448
|
-
const
|
|
449
|
-
|
|
507
|
+
const staticTarget = staticMode ? toStaticRscUrl(url) : null;
|
|
508
|
+
const fetchTarget = staticTarget ? staticTarget.url : url;
|
|
509
|
+
// Static hosts resolve neither partial payloads nor intercepting routes,
|
|
510
|
+
// so neither the state tree nor the source URL is sent — and neither may
|
|
511
|
+
// fragment the cache key of a file that does not vary on them.
|
|
512
|
+
const headers = staticMode
|
|
513
|
+
? buildRscHeaders(undefined, undefined)
|
|
514
|
+
: buildRscHeaders(stateTree, currentUrl);
|
|
515
|
+
// Skip the cache key when the manifest supplies a content-hashed
|
|
450
516
|
// URL — the hash itself guarantees freshness, and the param would defeat
|
|
451
517
|
// the immutable cache headers on /_rsc/* (TIM-1254).
|
|
452
|
-
const
|
|
453
|
-
|
|
454
|
-
|
|
518
|
+
const rscUrl = staticTarget?.hashed ? fetchTarget : await appendRscParam(fetchTarget, headers);
|
|
519
|
+
// Deriving the cache key is async (SubtleCrypto), so the fetch is no
|
|
520
|
+
// longer issued in the same tick as the call. A navigation superseded
|
|
521
|
+
// during that window would otherwise still hit the network with an
|
|
522
|
+
// already-aborted signal.
|
|
523
|
+
signal?.throwIfAborted();
|
|
455
524
|
if (deps.decodeRsc) {
|
|
456
525
|
// Production path: use createFromFetch for streaming RSC decoding.
|
|
457
526
|
// createFromFetch takes a Promise<Response> and progressively parses
|
|
@@ -461,7 +530,6 @@ export async function fetchRscPayload(
|
|
|
461
530
|
// consumes the body. Reading headers does NOT consume the body stream.
|
|
462
531
|
const fetchPromise = deps.fetch(rscUrl, { headers, redirect: 'manual', signal });
|
|
463
532
|
let segmentInfo: SegmentInfo[] | null = null;
|
|
464
|
-
let params: Record<string, string | string[]> | null = null;
|
|
465
533
|
let skippedSegments: string[] | null = null;
|
|
466
534
|
// Track when the full RSC body stream is consumed (not just shell).
|
|
467
535
|
// Initialized to resolved for bodyless responses; overwritten when
|
|
@@ -489,7 +557,7 @@ export async function fetchRscPayload(
|
|
|
489
557
|
// with a JSON body instead of a broken RSC stream for any RenderError
|
|
490
558
|
// (4xx or 5xx). Hard-navigate so the server renders the error page as HTML.
|
|
491
559
|
// See design/10-error-handling.md §"Error Page Rendering for Client Navigation"
|
|
492
|
-
if (response.headers.get(
|
|
560
|
+
if (response.headers.get(TIMBER_ERROR_HEADER) === '1') {
|
|
493
561
|
throw new ServerErrorResponse(response.status, url);
|
|
494
562
|
}
|
|
495
563
|
// Content-Type guard: reject non-RSC responses before createFromFetch
|
|
@@ -517,13 +585,12 @@ export async function fetchRscPayload(
|
|
|
517
585
|
// Metadata (<title>/<meta>/<link>) now rides the RSC Flight payload
|
|
518
586
|
// as React elements — React 19 Float handles them. See TIM-1151.
|
|
519
587
|
segmentInfo = extractSegmentInfo(response);
|
|
520
|
-
params = extractParams(response);
|
|
521
588
|
skippedSegments = extractSkippedSegments(response);
|
|
522
589
|
|
|
523
590
|
// Wrap the body to track full stream consumption. createFromFetch's
|
|
524
591
|
// thenable resolves when the root model (shell) arrives, but we need
|
|
525
|
-
// to know when ALL chunks are read
|
|
526
|
-
//
|
|
592
|
+
// to know when ALL chunks are read — that is what the navigation
|
|
593
|
+
// promise resolving means, and what keeps the pending store set.
|
|
527
594
|
if (response.body) {
|
|
528
595
|
const tracked = trackStreamCompletion(response.body);
|
|
529
596
|
streamDone = tracked.done;
|
|
@@ -535,33 +602,37 @@ export async function fetchRscPayload(
|
|
|
535
602
|
}
|
|
536
603
|
return response;
|
|
537
604
|
});
|
|
538
|
-
// Await headers so segmentInfo
|
|
605
|
+
// Await headers so segmentInfo is populated.
|
|
539
606
|
await wrappedPromise;
|
|
540
|
-
// In static mode, params come from the manifest (inlined at build
|
|
541
|
-
// time) since .rsc files have no HTTP headers. TIM-1255.
|
|
542
|
-
if (staticMode && !params) {
|
|
543
|
-
params = manifestParams(url);
|
|
544
|
-
}
|
|
545
607
|
// Start decoding but do NOT await — return the in-progress thenable.
|
|
546
608
|
// React can render a Flight thenable directly: it suspends on unresolved
|
|
547
609
|
// parts and progressively renders as chunks arrive, spreading work across
|
|
548
610
|
// frames instead of blocking the main thread in one burst.
|
|
549
|
-
const
|
|
611
|
+
const root = deps.decodeRsc(wrappedPromise);
|
|
612
|
+
// One split, one root: the tree and the params it was rendered with come
|
|
613
|
+
// apart here and nowhere else, so nothing downstream has to keep them
|
|
614
|
+
// paired by hand.
|
|
615
|
+
const { tree: payload, params } = splitPayloadRoot(root);
|
|
550
616
|
// Combine stream completion with payload error propagation.
|
|
551
|
-
// streamDone
|
|
552
|
-
//
|
|
617
|
+
// streamDone marks the end of the RSC stream, which is what the
|
|
618
|
+
// navigation promise resolves on. payloadError propagates
|
|
553
619
|
// decode failures (stale client references, Flight parse errors)
|
|
554
620
|
// so the router's catch block can trigger recovery (stale reload).
|
|
555
621
|
const payloadError = new Promise<void>((_, reject) => {
|
|
556
|
-
Promise.resolve(
|
|
622
|
+
Promise.resolve(root).then(() => {}, reject);
|
|
557
623
|
});
|
|
558
624
|
payloadError.catch(() => {});
|
|
559
625
|
const decodePromise = Promise.race([streamDone, payloadError]);
|
|
626
|
+
// Mark handled, like payloadError above. The same rejection reaches the
|
|
627
|
+
// router through `payload`, and a navigation that recovers by hard
|
|
628
|
+
// navigating (version skew, non-RSC response) hangs deliberately and never
|
|
629
|
+
// awaits this one — leaving it to surface as an unhandled rejection.
|
|
630
|
+
decodePromise.catch(() => {});
|
|
560
631
|
return {
|
|
561
632
|
payload,
|
|
633
|
+
params,
|
|
562
634
|
decodePromise,
|
|
563
635
|
segmentInfo,
|
|
564
|
-
params,
|
|
565
636
|
skippedSegments,
|
|
566
637
|
};
|
|
567
638
|
}
|
|
@@ -575,7 +646,7 @@ export async function fetchRscPayload(
|
|
|
575
646
|
}
|
|
576
647
|
}
|
|
577
648
|
// Server error guard (same as production path above).
|
|
578
|
-
if (response.headers.get(
|
|
649
|
+
if (response.headers.get(TIMBER_ERROR_HEADER) === '1') {
|
|
579
650
|
throw new ServerErrorResponse(response.status, url);
|
|
580
651
|
}
|
|
581
652
|
// Content-Type guard (same as production path above). See TIM-1231, TIM-1243, TIM-1247.
|
|
@@ -599,16 +670,12 @@ export async function fetchRscPayload(
|
|
|
599
670
|
throw new NonRscResponse(url);
|
|
600
671
|
}
|
|
601
672
|
}
|
|
602
|
-
|
|
603
|
-
// In static mode, params come from the manifest. TIM-1255.
|
|
604
|
-
if (staticMode && !fallbackParams) {
|
|
605
|
-
fallbackParams = manifestParams(url);
|
|
606
|
-
}
|
|
673
|
+
// Test/fallback path: raw text carries no payload root, so no params.
|
|
607
674
|
return {
|
|
608
675
|
payload: await response.text(),
|
|
676
|
+
params: readPublishedParams(undefined),
|
|
609
677
|
decodePromise: null,
|
|
610
678
|
segmentInfo: extractSegmentInfo(response),
|
|
611
|
-
params: fallbackParams,
|
|
612
679
|
skippedSegments: extractSkippedSegments(response),
|
|
613
680
|
};
|
|
614
681
|
}
|