@timber-js/app 0.2.0-alpha.196 → 0.2.0-alpha.198
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-CWYtq6ii.js → actions-BS-m5SLv.js} +3 -3
- package/dist/_chunks/{actions-CWYtq6ii.js.map → actions-BS-m5SLv.js.map} +1 -1
- package/dist/_chunks/als-registry-C6kcfprT.js.map +1 -1
- package/dist/_chunks/{build-manifest-DWppEdLB.js → build-manifest-DTmSGLRz.js} +51 -2
- package/dist/_chunks/build-manifest-DTmSGLRz.js.map +1 -0
- package/dist/_chunks/{cache-api-CQeYzA5g.js → cache-api-DqzgTEqk.js} +4 -49
- package/dist/_chunks/cache-api-DqzgTEqk.js.map +1 -0
- package/dist/_chunks/{chains-h7EO-u3n.js → chains-CZG7E5zg.js} +2 -2
- package/dist/_chunks/{chains-h7EO-u3n.js.map → chains-CZG7E5zg.js.map} +1 -1
- package/dist/_chunks/{cli-check-BVthpfLS.js → cli-check-dVDi1GQz.js} +3 -3
- package/dist/_chunks/{cli-check-BVthpfLS.js.map → cli-check-dVDi1GQz.js.map} +1 -1
- package/dist/_chunks/{cli-schema-sync-3Wutm8pH.js → cli-schema-sync-DTy_-Msq.js} +2 -2
- package/dist/_chunks/{cli-schema-sync-3Wutm8pH.js.map → cli-schema-sync-DTy_-Msq.js.map} +1 -1
- package/dist/_chunks/{cloudflare-BKJC3SC_.js → cloudflare-BFb__LYG.js} +2 -2
- package/dist/_chunks/{cloudflare-BKJC3SC_.js.map → cloudflare-BFb__LYG.js.map} +1 -1
- package/dist/_chunks/{convention-lint-DO10_pVl.js → convention-lint-Ph6luW4c.js} +4 -2
- package/dist/_chunks/convention-lint-Ph6luW4c.js.map +1 -0
- package/dist/_chunks/{error-boundary-D-lkwyaD.js → error-boundary-BvRCCmbN.js} +3 -3
- package/dist/_chunks/{error-boundary-D-lkwyaD.js.map → error-boundary-BvRCCmbN.js.map} +1 -1
- package/dist/_chunks/{href-validation-CMc5JRls.js → href-validation-BIrxavIy.js} +74 -2
- package/dist/_chunks/href-validation-BIrxavIy.js.map +1 -0
- package/dist/_chunks/{live-graph-Bx4HodF1.js → live-graph-BXDsdzBv.js} +3 -3
- package/dist/_chunks/{live-graph-Bx4HodF1.js.map → live-graph-BXDsdzBv.js.map} +1 -1
- package/dist/_chunks/{logger-pumCm3Il.js → logger-DDirEsn7.js} +3 -4
- package/dist/_chunks/{logger-pumCm3Il.js.map → logger-DDirEsn7.js.map} +1 -1
- package/dist/_chunks/navigation-root-B00jjGd5.js +233 -0
- package/dist/_chunks/navigation-root-B00jjGd5.js.map +1 -0
- package/dist/_chunks/{segment-context-CjOlyB8Y.js → param-value-C8TNYchQ.js} +2 -33
- package/dist/_chunks/param-value-C8TNYchQ.js.map +1 -0
- package/dist/_chunks/{poison-scan-BAxfTT5L.js → poison-scan-BoDLgbix.js} +2 -2
- package/dist/_chunks/{poison-scan-BAxfTT5L.js.map → poison-scan-BoDLgbix.js.map} +1 -1
- package/dist/_chunks/{router-ref-BzqbPwYC.js → router-ref-8gr8qsxN.js} +2 -2
- package/dist/_chunks/{router-ref-BzqbPwYC.js.map → router-ref-8gr8qsxN.js.map} +1 -1
- package/dist/_chunks/{rsc-cache-key-DD0fl_-s.js → rsc-cache-key-ClUiXQnK.js} +2 -2
- package/dist/_chunks/{rsc-cache-key-DD0fl_-s.js.map → rsc-cache-key-ClUiXQnK.js.map} +1 -1
- package/dist/_chunks/{scanner-BRIOmHE2.js → scanner-tdFPvDYi.js} +174 -7
- package/dist/_chunks/scanner-tdFPvDYi.js.map +1 -0
- package/dist/_chunks/segment-context-D9_89u34.js +34 -0
- package/dist/_chunks/segment-context-D9_89u34.js.map +1 -0
- package/dist/_chunks/singleflight-2lUWfcAk.js +54 -0
- package/dist/_chunks/singleflight-2lUWfcAk.js.map +1 -0
- package/dist/_chunks/{ssr-data-Ya2HJPFp.js → ssr-data-BQGhTPAK.js} +2 -17
- package/dist/_chunks/ssr-data-BQGhTPAK.js.map +1 -0
- package/dist/_chunks/{walkers-BU6z9xRV.js → walkers-DNX05dC0.js} +2 -2
- package/dist/_chunks/{walkers-BU6z9xRV.js.map → walkers-DNX05dC0.js.map} +1 -1
- package/dist/adapters/cloudflare-dev.js +1 -1
- package/dist/adapters/cloudflare-kv-cache.js +1 -1
- package/dist/adapters/cloudflare.js +1 -1
- package/dist/adapters/nitro.d.ts +1 -1
- package/dist/adapters/nitro.d.ts.map +1 -1
- package/dist/adapters/nitro.js.map +1 -1
- package/dist/analyze/crawl-entry.js +2 -2
- package/dist/analyze/graph-command.js +2 -2
- package/dist/cache/index.js +1 -1
- package/dist/cache/singleflight.d.ts +2 -0
- package/dist/cache/singleflight.d.ts.map +1 -1
- package/dist/cli.js +2 -2
- package/dist/client/browser-entry/hydrate.d.ts +21 -15
- package/dist/client/browser-entry/hydrate.d.ts.map +1 -1
- package/dist/client/browser-entry/index.d.ts +4 -3
- package/dist/client/browser-entry/index.d.ts.map +1 -1
- package/dist/client/browser-entry/post-hydration.d.ts.map +1 -1
- package/dist/client/browser-entry/router-init.d.ts +17 -1
- package/dist/client/browser-entry/router-init.d.ts.map +1 -1
- package/dist/client/error-boundary.js +1 -1
- package/dist/client/global-context.d.ts +15 -0
- package/dist/client/global-context.d.ts.map +1 -0
- package/dist/client/index.js +138 -35
- package/dist/client/index.js.map +1 -1
- package/dist/client/internal.d.ts +0 -1
- package/dist/client/internal.d.ts.map +1 -1
- package/dist/client/internal.js +206 -55
- package/dist/client/internal.js.map +1 -1
- package/dist/client/link.d.ts.map +1 -1
- package/dist/client/location-search.d.ts +12 -0
- package/dist/client/location-search.d.ts.map +1 -0
- package/dist/client/navigation-api.d.ts.map +1 -1
- package/dist/client/navigation-commit.d.ts +18 -0
- package/dist/client/navigation-commit.d.ts.map +1 -1
- package/dist/client/navigation-context.d.ts +13 -11
- package/dist/client/navigation-context.d.ts.map +1 -1
- package/dist/client/navigation-root.d.ts +47 -108
- package/dist/client/navigation-root.d.ts.map +1 -1
- package/dist/client/navigation-transition.d.ts +136 -0
- package/dist/client/navigation-transition.d.ts.map +1 -0
- package/dist/client/nuqs-adapter.d.ts.map +1 -1
- package/dist/client/params-context.d.ts +4 -5
- package/dist/client/params-context.d.ts.map +1 -1
- package/dist/client/react-root.d.ts +44 -0
- package/dist/client/react-root.d.ts.map +1 -0
- package/dist/client/router-pipeline.d.ts +2 -2
- package/dist/client/router-pipeline.d.ts.map +1 -1
- package/dist/client/router-types.d.ts +12 -2
- package/dist/client/router-types.d.ts.map +1 -1
- package/dist/client/router.d.ts.map +1 -1
- package/dist/client/segment-cache.d.ts +39 -0
- package/dist/client/segment-cache.d.ts.map +1 -1
- package/dist/client/segment-context.d.ts.map +1 -1
- package/dist/client/segment-outlet.d.ts +25 -14
- package/dist/client/segment-outlet.d.ts.map +1 -1
- package/dist/client/segment-update-context.d.ts +3 -9
- package/dist/client/segment-update-context.d.ts.map +1 -1
- package/dist/client/slot-content-cache-context.d.ts +35 -0
- package/dist/client/slot-content-cache-context.d.ts.map +1 -0
- package/dist/client/ssr-data.d.ts +8 -2
- package/dist/client/ssr-data.d.ts.map +1 -1
- package/dist/client/state.d.ts +0 -15
- package/dist/client/state.d.ts.map +1 -1
- package/dist/client/use-pathname.d.ts +13 -11
- package/dist/client/use-pathname.d.ts.map +1 -1
- package/dist/client/use-search-params.d.ts +13 -13
- package/dist/client/use-search-params.d.ts.map +1 -1
- package/dist/client/use-segment-params.d.ts +18 -68
- package/dist/client/use-segment-params.d.ts.map +1 -1
- package/dist/config-types.d.ts +17 -0
- 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/holding-server.d.ts +15 -10
- package/dist/dev-tools/holding-server.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +44 -43
- package/dist/index.js.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/shims.d.ts.map +1 -1
- package/dist/plugins/static-build.d.ts +2 -2
- package/dist/plugins/static-build.d.ts.map +1 -1
- package/dist/routing/codegen-write.d.ts.map +1 -1
- package/dist/routing/index.js +2 -2
- package/dist/routing/interception-overlap.d.ts +35 -0
- package/dist/routing/interception-overlap.d.ts.map +1 -0
- package/dist/routing/interception.d.ts.map +1 -1
- package/dist/rsc-runtime/ssr.d.ts +3 -1
- package/dist/rsc-runtime/ssr.d.ts.map +1 -1
- package/dist/server/als-registry.d.ts +6 -0
- package/dist/server/als-registry.d.ts.map +1 -1
- package/dist/server/csp-nonce.d.ts +45 -0
- package/dist/server/csp-nonce.d.ts.map +1 -0
- package/dist/server/default-status-page.d.ts.map +1 -1
- package/dist/server/deny-renderer.d.ts.map +1 -1
- package/dist/server/flight-scripts.d.ts +5 -2
- package/dist/server/flight-scripts.d.ts.map +1 -1
- package/dist/server/html-injector-core.d.ts +17 -2
- package/dist/server/html-injector-core.d.ts.map +1 -1
- package/dist/server/html-injectors.d.ts +3 -2
- package/dist/server/html-injectors.d.ts.map +1 -1
- package/dist/server/index.js +2 -2
- package/dist/server/internal.js +86 -37
- package/dist/server/internal.js.map +1 -1
- package/dist/server/metadata-render.d.ts.map +1 -1
- package/dist/server/node-stream-transforms.d.ts +3 -17
- package/dist/server/node-stream-transforms.d.ts.map +1 -1
- package/dist/server/nuqs-ssr-provider.d.ts +7 -3
- package/dist/server/nuqs-ssr-provider.d.ts.map +1 -1
- package/dist/server/pipeline-phases.d.ts.map +1 -1
- package/dist/server/prebuilt/key-discipline.d.ts +32 -3
- package/dist/server/prebuilt/key-discipline.d.ts.map +1 -1
- package/dist/server/primitives.d.ts.map +1 -1
- package/dist/server/render-utils.d.ts +4 -3
- package/dist/server/render-utils.d.ts.map +1 -1
- package/dist/server/rsc-entry/action-middleware-runner.d.ts.map +1 -1
- package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/index.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
- package/dist/server/ssr-bridge-types.d.ts +22 -2
- 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-render.d.ts +5 -1
- package/dist/server/ssr-render.d.ts.map +1 -1
- package/dist/server/ssr-wrappers.d.ts +59 -27
- package/dist/server/ssr-wrappers.d.ts.map +1 -1
- package/dist/server/types.d.ts +10 -0
- package/dist/server/types.d.ts.map +1 -1
- package/dist/shims/navigation-rsc.d.ts +21 -0
- package/dist/shims/navigation-rsc.d.ts.map +1 -0
- package/docs/api/30-api-server.mdx +1 -0
- package/docs/api/35-api-typescript.mdx +4 -83
- package/docs/learn/03-fetching-data.mdx +1 -1
- package/docs/learn/{03b-access-control.mdx → 04-access-control.mdx} +2 -17
- package/docs/learn/05-the-flush-point.mdx +175 -0
- package/docs/learn/{05-typed-params.mdx → 06-typed-params.mdx} +1 -1
- package/docs/learn/07-typed-routes.mdx +25 -49
- package/docs/learn/{08-streaming.mdx → 09-streaming.mdx} +1 -7
- package/docs/learn/{10-middleware.mdx → 11-middleware.mdx} +1 -0
- package/package.json +3 -3
- package/src/adapters/nitro.ts +7 -7
- package/src/cache/singleflight.ts +5 -0
- package/src/client/browser-entry/hydrate.ts +54 -104
- package/src/client/browser-entry/index.ts +16 -6
- package/src/client/browser-entry/post-hydration.ts +3 -2
- package/src/client/browser-entry/router-init.ts +84 -33
- package/src/client/global-context.ts +31 -0
- package/src/client/internal.ts +1 -2
- package/src/client/link.tsx +18 -18
- package/src/client/location-search.ts +15 -0
- package/src/client/navigation-api.ts +4 -2
- package/src/client/navigation-commit.ts +48 -2
- package/src/client/navigation-context.ts +25 -37
- package/src/client/navigation-root.tsx +55 -411
- package/src/client/navigation-transition.ts +278 -0
- package/src/client/nuqs-adapter.tsx +4 -5
- package/src/client/params-context.ts +13 -18
- package/src/client/react-root.ts +72 -0
- package/src/client/router-lifecycle.ts +1 -1
- package/src/client/router-pipeline.ts +96 -22
- package/src/client/router-types.ts +12 -2
- package/src/client/router.ts +48 -36
- package/src/client/segment-cache.ts +70 -2
- package/src/client/segment-context.ts +7 -4
- package/src/client/segment-outlet.tsx +41 -86
- package/src/client/segment-update-context.ts +7 -26
- package/src/client/slot-content-cache-context.ts +43 -0
- package/src/client/ssr-data.ts +8 -2
- package/src/client/state.ts +0 -26
- package/src/client/use-pathname.ts +21 -31
- package/src/client/use-search-params.ts +31 -29
- package/src/client/use-segment-params.ts +27 -126
- package/src/config-types.ts +17 -0
- package/src/config-validation.ts +17 -0
- package/src/dev-tools/holding-server.ts +23 -12
- package/src/index.ts +26 -11
- package/src/plugins/dev-server.ts +9 -12
- package/src/plugins/entries.ts +3 -0
- package/src/plugins/shims.ts +8 -7
- package/src/plugins/static-build.ts +9 -5
- package/src/react-canary.d.ts +2 -0
- package/src/routing/codegen-write.ts +2 -0
- package/src/routing/interception-overlap.ts +141 -0
- package/src/routing/interception.ts +118 -5
- package/src/rsc-runtime/ssr.ts +3 -2
- package/src/server/als-registry.ts +6 -0
- package/src/server/csp-nonce.ts +70 -0
- package/src/server/default-status-page.ts +1 -0
- package/src/server/deny-renderer.ts +7 -3
- package/src/server/flight-scripts.ts +9 -4
- package/src/server/html-injector-core.ts +26 -9
- package/src/server/html-injectors.ts +8 -8
- package/src/server/metadata-render.ts +26 -4
- package/src/server/node-stream-transforms.ts +7 -20
- package/src/server/nuqs-ssr-provider.tsx +8 -7
- package/src/server/pipeline-phases.ts +5 -0
- package/src/server/prebuilt/key-discipline.ts +82 -13
- package/src/server/prebuilt-runtime.ts +2 -2
- package/src/server/primitives.ts +4 -4
- package/src/server/render-utils.ts +8 -4
- package/src/server/rsc-entry/action-middleware-runner.ts +7 -0
- package/src/server/rsc-entry/error-renderer.ts +5 -2
- package/src/server/rsc-entry/index.ts +8 -0
- package/src/server/rsc-entry/ssr-renderer.ts +11 -4
- package/src/server/ssr-bridge-types.ts +22 -2
- package/src/server/ssr-entry.ts +35 -28
- package/src/server/ssr-render.ts +13 -4
- package/src/server/ssr-wrappers.tsx +81 -61
- package/src/server/types.ts +10 -0
- package/src/shared/slot-params.ts +3 -4
- package/src/shims/navigation-rsc.ts +47 -0
- package/dist/_chunks/build-manifest-DWppEdLB.js.map +0 -1
- package/dist/_chunks/cache-api-CQeYzA5g.js.map +0 -1
- package/dist/_chunks/convention-lint-DO10_pVl.js.map +0 -1
- package/dist/_chunks/href-validation-CMc5JRls.js.map +0 -1
- package/dist/_chunks/scanner-BRIOmHE2.js.map +0 -1
- package/dist/_chunks/segment-context-CjOlyB8Y.js.map +0 -1
- package/dist/_chunks/slot-params-BCTmZkQB.js +0 -76
- package/dist/_chunks/slot-params-BCTmZkQB.js.map +0 -1
- package/dist/_chunks/ssr-data-Ya2HJPFp.js.map +0 -1
- package/dist/_chunks/use-segment-params-DzTBpkvj.js +0 -398
- package/dist/_chunks/use-segment-params-DzTBpkvj.js.map +0 -1
- package/docs/learn/04-loading-states.mdx +0 -67
- package/docs/learn/04b-the-flush-point.mdx +0 -115
- package/docs/learn/12-client-navigation.mdx +0 -176
- package/docs/learn/13-configuration.mdx +0 -166
- package/docs/more/01-advanced-routing.mdx +0 -344
- package/docs/more/02-advanced-forms.mdx +0 -137
- package/docs/more/03-coming-from-nextjs.mdx +0 -186
- package/docs/more/04-metadata-and-fonts.mdx +0 -193
- package/docs/more/04b-mdx.mdx +0 -229
- package/docs/more/05-content-collections.mdx +0 -90
- package/docs/more/06-instrumentation.mdx +0 -214
- package/docs/more/07-security.mdx +0 -129
- package/docs/more/08-developer-experience.mdx +0 -134
- package/docs/more/40-why-timber.mdx +0 -50
- package/docs/more/41-timber-vs-nextjs.mdx +0 -81
- package/docs/more/42-timber-vs-others.mdx +0 -68
- package/docs/more/50-ai-agent-instructions.mdx +0 -171
- /package/docs/learn/{06-forms-and-actions.mdx → 08-forms-and-actions.mdx} +0 -0
- /package/docs/learn/{09-caching.mdx → 10-caching.mdx} +0 -0
- /package/docs/learn/{11-error-handling.mdx → 12-error-handling.mdx} +0 -0
- /package/docs/learn/{14-deploying.mdx → 13-deploying.mdx} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"singleflight.d.ts","sourceRoot":"","sources":["../../src/cache/singleflight.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,mBAAmB;IAClC,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"singleflight.d.ts","sourceRoot":"","sources":["../../src/cache/singleflight.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,mBAAmB;IAClC,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACxE,oEAAoE;IACpE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,SAAS,CAAC;CAChD;AAED;;;GAGG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;IACjD,YAAY,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAGzC;CACF;AAED,wBAAgB,kBAAkB,CAAC,IAAI,CAAC,EAAE,mBAAmB,GAAG,YAAY,CAqD3E"}
|
package/dist/cli.js
CHANGED
|
@@ -136,7 +136,7 @@ async function runPreview(options, _deps) {
|
|
|
136
136
|
* `--project` names the tsconfig handed to tsgo.
|
|
137
137
|
*/
|
|
138
138
|
async function runCheck(options, _deps) {
|
|
139
|
-
const { checkRoutes, runTypeCheck } = await import("./_chunks/cli-check-
|
|
139
|
+
const { checkRoutes, runTypeCheck } = await import("./_chunks/cli-check-dVDi1GQz.js");
|
|
140
140
|
const { root } = await checkRoutes({ viteConfigFile: options.config }, _deps);
|
|
141
141
|
await runTypeCheck({
|
|
142
142
|
root,
|
|
@@ -152,7 +152,7 @@ async function runCheck(options, _deps) {
|
|
|
152
152
|
async function runSchema(args) {
|
|
153
153
|
const subcommand = args[0];
|
|
154
154
|
if (subcommand !== "sync") throw new Error(`Unknown schema subcommand: ${subcommand ?? "(none)"}. Usage: timber schema sync`);
|
|
155
|
-
const { runSchemaSync, defaultCodecForSegment } = await import("./_chunks/cli-schema-sync-
|
|
155
|
+
const { runSchemaSync, defaultCodecForSegment } = await import("./_chunks/cli-schema-sync-DTy_-Msq.js").then((n) => n.t);
|
|
156
156
|
const result = runSchemaSync(process.cwd());
|
|
157
157
|
if (result.filesystemSegments.length === 0) {
|
|
158
158
|
console.log("[timber] No dynamic segments found in app/.");
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Hydration — pre-hydration sequence and React root
|
|
2
|
+
* Hydration — pre-hydration sequence and hydrating the React root.
|
|
3
3
|
*
|
|
4
4
|
* Handles two paths:
|
|
5
|
-
* 1. RSC payload available:
|
|
6
|
-
* 2. No RSC payload:
|
|
5
|
+
* 1. RSC payload available: hydrate the router's React root with the payload
|
|
6
|
+
* 2. No RSC payload: nothing — the root is created by the first render
|
|
7
|
+
* (client/react-root.ts)
|
|
7
8
|
*
|
|
8
9
|
* Pre-hydration ordering contract (MUST execute in this order):
|
|
9
10
|
* 1. initRouter() — creates the global router so useRouter()
|
|
@@ -20,15 +21,16 @@
|
|
|
20
21
|
*
|
|
21
22
|
* See design/19-client-navigation.md §"NavigationContext"
|
|
22
23
|
*/
|
|
23
|
-
import type {
|
|
24
|
+
import type { ReactRootHost } from '../react-root.ts';
|
|
24
25
|
import type { RscStreamResult } from './rsc-stream.ts';
|
|
26
|
+
import type { RouterInitResult } from './router-init.ts';
|
|
25
27
|
interface HydrateOptions {
|
|
26
28
|
/** RSC stream result (null if no inlined payload) */
|
|
27
29
|
rscResult: RscStreamResult | null;
|
|
28
|
-
/**
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
/** The router's React root — the one every navigation renders through. */
|
|
31
|
+
reactRoot: ReactRootHost;
|
|
32
|
+
/** The router's wrapper chain — see `RouterInitResult.renderTree`. */
|
|
33
|
+
renderTree: RouterInitResult['renderTree'];
|
|
32
34
|
}
|
|
33
35
|
/**
|
|
34
36
|
* Run the pre-hydration sequence: set navigation state from the address bar.
|
|
@@ -43,15 +45,19 @@ interface HydrateOptions {
|
|
|
43
45
|
*/
|
|
44
46
|
export declare function runPreHydration(): void;
|
|
45
47
|
/**
|
|
46
|
-
* Hydrate the React tree
|
|
48
|
+
* Hydrate the React tree when an RSC payload is available.
|
|
47
49
|
*
|
|
48
|
-
*
|
|
49
|
-
* TimberNuqsAdapter
|
|
50
|
-
* document.
|
|
50
|
+
* Wraps the payload with the router's chain (NavigationProvider,
|
|
51
|
+
* TimberNuqsAdapter, the slot content cache, ...) and hydrates the router's
|
|
52
|
+
* React root with it, on the document.
|
|
51
53
|
*
|
|
52
|
-
* When no RSC payload is available (JS-only client)
|
|
53
|
-
*
|
|
54
|
+
* When no RSC payload is available (JS-only client) there is nothing to
|
|
55
|
+
* hydrate and nothing to do: the root must not be created at bootstrap —
|
|
56
|
+
* `createRoot(document).render()` would take React ownership of the entire
|
|
57
|
+
* document and blank the SSR HTML — so the router's first render, i.e. the
|
|
58
|
+
* first navigation or revalidation, creates it with the tree it renders
|
|
59
|
+
* (`createReactRoot`, TIM-600 / TIM-580).
|
|
54
60
|
*/
|
|
55
|
-
export declare function hydrateApp({ rscResult,
|
|
61
|
+
export declare function hydrateApp({ rscResult, reactRoot, renderTree }: HydrateOptions): void;
|
|
56
62
|
export {};
|
|
57
63
|
//# sourceMappingURL=hydrate.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hydrate.d.ts","sourceRoot":"","sources":["../../../src/client/browser-entry/hydrate.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"hydrate.d.ts","sourceRoot":"","sources":["../../../src/client/browser-entry/hydrate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAMH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAwCzD,UAAU,cAAc;IACtB,qDAAqD;IACrD,SAAS,EAAE,eAAe,GAAG,IAAI,CAAC;IAClC,0EAA0E;IAC1E,SAAS,EAAE,aAAa,CAAC;IACzB,sEAAsE;IACtE,UAAU,EAAE,gBAAgB,CAAC,YAAY,CAAC,CAAC;CAC5C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAKtC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,EAAE,cAAc,GAAG,IAAI,CAmCrF"}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* action-dispatch.ts — server action callServer callback
|
|
8
8
|
* rsc-stream.ts — __timber_f chunk handling + ReadableStream
|
|
9
9
|
* router-init.ts — createRouter + Navigation API setup
|
|
10
|
-
* hydrate.ts — pre-hydration sequence +
|
|
10
|
+
* hydrate.ts — pre-hydration sequence + hydrating the root
|
|
11
11
|
* post-hydration.ts — history stack, segment cache, popstate, scroll
|
|
12
12
|
* hmr.ts — dev-only HMR + error forwarding
|
|
13
13
|
* scroll.ts — getScrollY helper
|
|
@@ -16,9 +16,10 @@
|
|
|
16
16
|
*
|
|
17
17
|
* 1. setupServerActions() — register callServer (independent)
|
|
18
18
|
* 2. createRscPayloadStream() — decode inlined RSC payload
|
|
19
|
-
* 3.
|
|
19
|
+
* 3. createReactRoot() + — the root host the router renders through,
|
|
20
|
+
* createTimberRouter() then the router + Navigation API
|
|
20
21
|
* 4. runPreHydration() — set params + navigation state
|
|
21
|
-
* 5. hydrateApp() —
|
|
22
|
+
* 5. hydrateApp() — hydrate the root (no-op without a payload)
|
|
22
23
|
* 6. setupPostHydration() — history stack, popstate, scroll
|
|
23
24
|
* 7. setupHmr() — dev-only HMR wiring
|
|
24
25
|
* 8. timber-ready signal — E2E test readiness indicator
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/browser-entry/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/browser-entry/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"post-hydration.d.ts","sourceRoot":"","sources":["../../../src/client/browser-entry/post-hydration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAEpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"post-hydration.d.ts","sourceRoot":"","sources":["../../../src/client/browser-entry/post-hydration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAEpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAGjE,UAAU,oBAAoB;IAC5B,MAAM,EAAE,cAAc,CAAC;IACvB,gBAAgB,EAAE,uBAAuB,GAAG,IAAI,CAAC;IACjD,oEAAoE;IACpE,cAAc,EAAE,OAAO,CAAC;IACxB,+DAA+D;IAC/D,aAAa,EAAE,YAAY,CAAC;CAC7B;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,MAAM,EACN,gBAAgB,EAChB,cAAc,EACd,aAAa,GACd,EAAE,oBAAoB,GAAG,IAAI,CAqF7B"}
|
|
@@ -8,8 +8,16 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { type ParamsSource } from '../../shared/payload-root.ts';
|
|
10
10
|
import type { RouterInstance } from '#client-internal';
|
|
11
|
+
import type { NavigationState } from '#client-internal';
|
|
12
|
+
import type { NavigationRender } from '../navigation-root.tsx';
|
|
11
13
|
import { type NavigationApiController } from '../navigation-api.ts';
|
|
12
14
|
export interface RouterInitOptions {
|
|
15
|
+
/**
|
|
16
|
+
* The router's React root (`createReactRoot().render`). Every path that puts
|
|
17
|
+
* a page on screen renders through it — it is the synchronous transition
|
|
18
|
+
* around `root.render`, and the `publish` it takes runs on React's commit.
|
|
19
|
+
*/
|
|
20
|
+
render: NavigationRender;
|
|
13
21
|
initialElement?: unknown;
|
|
14
22
|
/** The params the hydration payload published, beside `initialElement`. */
|
|
15
23
|
initialParams?: ParamsSource;
|
|
@@ -18,6 +26,14 @@ export interface RouterInitOptions {
|
|
|
18
26
|
export interface RouterInitResult {
|
|
19
27
|
router: RouterInstance;
|
|
20
28
|
navApiController: NavigationApiController | null;
|
|
29
|
+
/**
|
|
30
|
+
* The client's wrapper chain around a tree — the one every navigation
|
|
31
|
+
* renders through. Hydration builds its root with this too, so the
|
|
32
|
+
* hydrated tree and the first navigated tree cannot differ in shape
|
|
33
|
+
* (a type present on one and absent on the other remounts everything
|
|
34
|
+
* below it) and share the router's slot content cache.
|
|
35
|
+
*/
|
|
36
|
+
renderTree: (tree: unknown, navState: NavigationState, params: ParamsSource) => React.ReactElement;
|
|
21
37
|
}
|
|
22
38
|
/**
|
|
23
39
|
* Create and register the global timber router.
|
|
@@ -26,5 +42,5 @@ export interface RouterInitResult {
|
|
|
26
42
|
* the initial render (methods lazily resolve the router at invocation,
|
|
27
43
|
* not render time, but initRouter must still run first).
|
|
28
44
|
*/
|
|
29
|
-
export declare function createTimberRouter(options
|
|
45
|
+
export declare function createTimberRouter(options: RouterInitOptions): RouterInitResult;
|
|
30
46
|
//# sourceMappingURL=router-init.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router-init.d.ts","sourceRoot":"","sources":["../../../src/client/browser-entry/router-init.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAEtF,OAAO,KAAK,EAAc,cAAc,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"router-init.d.ts","sourceRoot":"","sources":["../../../src/client/browser-entry/router-init.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAEtF,OAAO,KAAK,EAAc,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAQxD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG/D,OAAO,EAGL,KAAK,uBAAuB,EAC7B,MAAM,sBAAsB,CAAC;AAK9B,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,MAAM,EAAE,gBAAgB,CAAC;IACzB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,2EAA2E;IAC3E,aAAa,CAAC,EAAE,YAAY,CAAC;IAC7B,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,cAAc,CAAC;IACvB,gBAAgB,EAAE,uBAAuB,GAAG,IAAI,CAAC;IACjD;;;;;;OAMG;IACH,UAAU,EAAE,CACV,IAAI,EAAE,OAAO,EACb,QAAQ,EAAE,eAAe,EACzB,MAAM,EAAE,YAAY,KACjB,KAAK,CAAC,YAAY,CAAC;CACzB;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,iBAAiB,GAAG,gBAAgB,CAgU/E"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* createGlobalContext — a React context with a process-wide singleton identity.
|
|
3
|
+
*
|
|
4
|
+
* SINGLETON GUARANTEE: Uses globalThis + Symbol.for — same pattern as
|
|
5
|
+
* NavigationContext. The RSC client bundler can duplicate a module across
|
|
6
|
+
* chunks (browser-entry graph + client-reference graph). With ESM output,
|
|
7
|
+
* each chunk gets its own module scope — a bare createContext at module
|
|
8
|
+
* level would create separate instances per chunk. globalThis guarantees a
|
|
9
|
+
* single instance regardless of duplication.
|
|
10
|
+
*
|
|
11
|
+
* See design/19-client-navigation.md §"Singleton Guarantee via globalThis"
|
|
12
|
+
*/
|
|
13
|
+
import React from 'react';
|
|
14
|
+
export declare function createGlobalContext<T>(key: string, defaultValue: T): React.Context<T>;
|
|
15
|
+
//# sourceMappingURL=global-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"global-context.d.ts","sourceRoot":"","sources":["../../src/client/global-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAarF"}
|
package/dist/client/index.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { n as classifyUrlSegment } from "../_chunks/segment-classify-C539Pa2O.js";
|
|
3
|
-
import {
|
|
4
|
-
import { n as
|
|
5
|
-
import { n as
|
|
6
|
-
import { n as
|
|
3
|
+
import { c as stripRscCacheKey } from "../_chunks/rsc-cache-key-ClUiXQnK.js";
|
|
4
|
+
import { a as mergePreservedSearchParams, i as validateNavigationHref, n as isInternalHref, o as resolveSegmentParams } from "../_chunks/href-validation-BIrxavIy.js";
|
|
5
|
+
import { n as getSsrData } from "../_chunks/ssr-data-BQGhTPAK.js";
|
|
6
|
+
import { n as getRouterOrNull } from "../_chunks/router-ref-8gr8qsxN.js";
|
|
7
|
+
import "../_chunks/param-value-C8TNYchQ.js";
|
|
8
|
+
import { n as useSegmentContext } from "../_chunks/segment-context-D9_89u34.js";
|
|
7
9
|
import { t as getLinkCodec } from "../_chunks/codec-registry-oOUxugz3.js";
|
|
8
|
-
import {
|
|
10
|
+
import { a as useNavigationContext, o as usePendingNavigation } from "../_chunks/navigation-root-B00jjGd5.js";
|
|
9
11
|
import { n as useQueryStates } from "../_chunks/use-query-states-I3JMng6J.js";
|
|
10
|
-
import { createContext, startTransition, useActionState as useActionState$1, useContext, useRef, useState, useTransition } from "react";
|
|
12
|
+
import React, { createContext, startTransition, useActionState as useActionState$1, useContext, useRef, useState, useTransition } from "react";
|
|
11
13
|
import { jsx } from "react/jsx-runtime";
|
|
12
14
|
//#region src/client/use-link-status.ts
|
|
13
15
|
/**
|
|
@@ -44,20 +46,35 @@ function useLinkStatus() {
|
|
|
44
46
|
return useContext(LinkStatusContext);
|
|
45
47
|
}
|
|
46
48
|
//#endregion
|
|
49
|
+
//#region src/client/location-search.ts
|
|
50
|
+
/**
|
|
51
|
+
* The app-visible search string from the address bar.
|
|
52
|
+
*
|
|
53
|
+
* Mirrors what `appVisibleSearch()` does on the server: strips key-shaped
|
|
54
|
+
* `_rsc` values so the client and server agree on search state regardless
|
|
55
|
+
* of whether the document URL itself carries a payload cache key (a user
|
|
56
|
+
* pasting/sharing an RSC payload URL). Non-key-shaped `_rsc` values — an
|
|
57
|
+
* application legitimately owning that name — survive, using the same
|
|
58
|
+
* `isRscCacheKeyShape` predicate the server uses.
|
|
59
|
+
*/
|
|
60
|
+
function locationSearch() {
|
|
61
|
+
return stripRscCacheKey(window.location.search);
|
|
62
|
+
}
|
|
63
|
+
//#endregion
|
|
47
64
|
//#region src/client/link.tsx
|
|
48
65
|
var LINK_PENDING = { isPending: true };
|
|
49
66
|
var LINK_IDLE = { isPending: false };
|
|
50
67
|
/**
|
|
51
68
|
* Read the current URL's search string without requiring a React hook.
|
|
52
|
-
* On the client, reads window.location.search. During SSR, reads
|
|
53
|
-
* the request context (getSsrData)
|
|
69
|
+
* On the client, reads window.location.search. During SSR, reads the raw
|
|
70
|
+
* query string from the request context (getSsrData) — the same `''` or
|
|
71
|
+
* `?…` shape, preserving repeated keys (`?tag=a&tag=b`) so the
|
|
72
|
+
* server-rendered href matches what the hydrated client rebuilds from the
|
|
73
|
+
* address bar (TIM-1428). Returns empty string if unavailable.
|
|
54
74
|
*/
|
|
55
75
|
function getCurrentSearch() {
|
|
56
|
-
if (typeof window !== "undefined") return
|
|
57
|
-
|
|
58
|
-
if (!data) return "";
|
|
59
|
-
const str = new URLSearchParams(data.searchParams).toString();
|
|
60
|
-
return str ? `?${str}` : "";
|
|
76
|
+
if (typeof window !== "undefined") return locationSearch();
|
|
77
|
+
return getSsrData()?.search ?? "";
|
|
61
78
|
}
|
|
62
79
|
/**
|
|
63
80
|
* Interpolate dynamic segments in a route pattern with actual values.
|
|
@@ -253,10 +270,10 @@ var Link = function LinkImpl(props) {
|
|
|
253
270
|
if (!router) return;
|
|
254
271
|
const navHref = preserveSearchParams ? mergePreservedSearchParams(baseHref, getCurrentSearch(), preserveSearchParams) : resolvedHref;
|
|
255
272
|
const resolved = new URL(navHref, window.location.href);
|
|
256
|
-
if (resolved.pathname === window.location.pathname && resolved.search ===
|
|
273
|
+
if (resolved.pathname === window.location.pathname && stripRscCacheKey(resolved.search) === locationSearch() && resolved.hash) return;
|
|
257
274
|
event.preventDefault();
|
|
258
275
|
const shouldScroll = scroll !== false;
|
|
259
|
-
const absoluteHref = resolved.pathname + resolved.search + resolved.hash;
|
|
276
|
+
const absoluteHref = resolved.pathname + stripRscCacheKey(resolved.search) + resolved.hash;
|
|
260
277
|
const seq = ++clickSeq.current;
|
|
261
278
|
const settle = () => {
|
|
262
279
|
if (clickSeq.current === seq) startTransition(() => setIsPending(false));
|
|
@@ -273,7 +290,7 @@ var Link = function LinkImpl(props) {
|
|
|
273
290
|
if (router) {
|
|
274
291
|
const prefetchHref = preserveSearchParams ? mergePreservedSearchParams(baseHref, getCurrentSearch(), preserveSearchParams) : resolvedHref;
|
|
275
292
|
const resolved = new URL(prefetchHref, window.location.href);
|
|
276
|
-
router.prefetch(resolved.pathname + resolved.search);
|
|
293
|
+
router.prefetch(resolved.pathname + stripRscCacheKey(resolved.search));
|
|
277
294
|
}
|
|
278
295
|
} : userOnMouseEnter;
|
|
279
296
|
return /* @__PURE__ */ jsx("a", {
|
|
@@ -382,34 +399,31 @@ function useRouter() {
|
|
|
382
399
|
* Returns the pathname portion of the current URL (e.g. '/dashboard/settings').
|
|
383
400
|
* Updates when client-side navigation changes the URL.
|
|
384
401
|
*
|
|
385
|
-
*
|
|
386
|
-
* with the RSC tree render. This replaces the previous useSyncExternalStore
|
|
387
|
-
* approach which only subscribed to popstate events — meaning usePathname()
|
|
388
|
-
* did NOT re-render on forward navigation (pushState). The context approach
|
|
389
|
-
* fixes this: pathname updates in the same render pass as the new tree.
|
|
402
|
+
* One unconditional read of NavigationContext, on every side (TIM-1425):
|
|
390
403
|
*
|
|
391
|
-
*
|
|
392
|
-
*
|
|
404
|
+
* - In the browser, the provider wraps the RSC payload in renderRoot(), so
|
|
405
|
+
* the pathname updates in the same render pass as the new tree.
|
|
406
|
+
* - During SSR, the wrapper chain mounts the same provider with the request's
|
|
407
|
+
* pathname (TIM-1424), so this is the identical code path — no ALS read,
|
|
408
|
+
* no fallback tiers.
|
|
409
|
+
* - In the RSC environment, this module is never evaluated — the shims plugin
|
|
410
|
+
* resolves next/navigation to navigation-rsc.ts, which has a throwing stub
|
|
411
|
+
* (TIM-1420).
|
|
412
|
+
* - Called outside a component entirely, React itself throws its
|
|
413
|
+
* invalid-hook-call error — loud, not guessed-at from window.location.
|
|
393
414
|
*
|
|
394
415
|
* Compatible with Next.js's `usePathname()` from `next/navigation`.
|
|
395
416
|
*/
|
|
396
417
|
/**
|
|
397
418
|
* Read the current URL pathname.
|
|
398
419
|
*
|
|
399
|
-
*
|
|
400
|
-
*
|
|
401
|
-
* ALS-backed SSR data context. Falls back to window.location.pathname
|
|
402
|
-
* when called outside a React component (e.g., in tests).
|
|
420
|
+
* Throws when no NavigationProvider is above the caller (a component rendered
|
|
421
|
+
* outside the timber app — in tests, render inside the timber providers).
|
|
403
422
|
*/
|
|
404
423
|
function usePathname() {
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
} catch {}
|
|
409
|
-
const ssrData = getSsrData();
|
|
410
|
-
if (ssrData) return ssrData.pathname ?? "/";
|
|
411
|
-
if (typeof window !== "undefined") return window.location.pathname;
|
|
412
|
-
return "/";
|
|
424
|
+
const nav = useNavigationContext();
|
|
425
|
+
if (nav === null) throw new Error("[timber] usePathname() was called outside the timber app tree (no NavigationProvider found). In tests, render the component inside the timber providers.");
|
|
426
|
+
return nav.pathname;
|
|
413
427
|
}
|
|
414
428
|
//#endregion
|
|
415
429
|
//#region src/client/navigation-api.ts
|
|
@@ -641,6 +655,95 @@ function deriveFormErrors(result) {
|
|
|
641
655
|
};
|
|
642
656
|
}
|
|
643
657
|
//#endregion
|
|
658
|
+
//#region src/client/params-context.ts
|
|
659
|
+
/**
|
|
660
|
+
* Segment params context — the one channel params use to reach the browser.
|
|
661
|
+
*
|
|
662
|
+
* Params ride the RSC payload's root row as a sibling of the tree
|
|
663
|
+
* (`{ tree, params, slotParams }`), rather than in four side channels that
|
|
664
|
+
* raced to seed them: a response header, an inline script, and two build-time
|
|
665
|
+
* manifest fields all previously carried the same record, each with its own
|
|
666
|
+
* `JSON.stringify` (TIM-1294).
|
|
667
|
+
*
|
|
668
|
+
* Riding the payload is what makes them *typed*. `defineSchema` takes any
|
|
669
|
+
* `Codec<T>`, so a coerced param is whatever the codec returned — a `Date`, a
|
|
670
|
+
* `bigint` — and `JSON.stringify` either flattened it to a string or threw
|
|
671
|
+
* mid-response. React Flight carries those values natively, so the client
|
|
672
|
+
* reads the value the server produced instead of a lossy copy of it. See
|
|
673
|
+
* design/41-global-params.md §"Transport".
|
|
674
|
+
*
|
|
675
|
+
* **The client owns the provider.** There is exactly one `ParamsProvider` in
|
|
676
|
+
* the browser's tree, rendered by `PayloadRoot` above the point where a
|
|
677
|
+
* partial navigation splices the new payload into the retained tree. It has to
|
|
678
|
+
* be there and it has to be alone: a provider *inside* the payload lands below
|
|
679
|
+
* the retained region, whose own root is the departing route's provider, so
|
|
680
|
+
* every reader in a skipped layout resolves to the departing record and no
|
|
681
|
+
* amount of wrapping above it helps (TIM-1297).
|
|
682
|
+
*
|
|
683
|
+
* Ordering still holds without a bootstrap contract, for the same reason it
|
|
684
|
+
* did when the provider was in the tree: a provider renders before its own
|
|
685
|
+
* descendants by construction, so `useSegmentParams()` is correct during
|
|
686
|
+
* hydration without anything having to run before `hydrateRoot()`.
|
|
687
|
+
*/
|
|
688
|
+
/**
|
|
689
|
+
* SINGLETON GUARANTEE: globalThis + `Symbol.for`, the same pattern as
|
|
690
|
+
* `NavigationContext` and `SegmentUpdateContext`.
|
|
691
|
+
*
|
|
692
|
+
* The RSC client bundler can duplicate a module across chunks, and with ESM
|
|
693
|
+
* output each chunk gets its own module scope — so a bare `createContext` at
|
|
694
|
+
* module level yields one context per chunk. This module is now reached from
|
|
695
|
+
* *both* graphs: `PayloadRoot` is imported by the browser entry, while
|
|
696
|
+
* `useParamsContext()` arrives through the client-reference graph with the
|
|
697
|
+
* app's own components. A duplicate would put the provider on instance A and
|
|
698
|
+
* every reader on instance B, so `useContext` returns `null` and every
|
|
699
|
+
* `useSegmentParams()` call throws the outside-the-timber-app-tree error
|
|
700
|
+
* even though the provider is mounted (the module-snapshot fallback it once
|
|
701
|
+
* silently landed on was deleted in TIM-1425).
|
|
702
|
+
*
|
|
703
|
+
* This module was the one client context without the guard — harmless while
|
|
704
|
+
* the provider travelled inside the payload, in the same graph as its readers,
|
|
705
|
+
* and load-bearing the moment the client started rendering it (TIM-1297).
|
|
706
|
+
*
|
|
707
|
+
* The React APIs are reached through the namespace rather than named imports,
|
|
708
|
+
* for the same reason `segment-update-context.ts` and `navigation-context.ts`
|
|
709
|
+
* do it: React's `react-server` export provides neither `createContext` nor
|
|
710
|
+
* `useContext`, and a *named* ESM import of a missing export fails at module
|
|
711
|
+
* instantiation — before any feature check could run. This module is reachable
|
|
712
|
+
* from every entry a Server Component imports, so the named form crashed
|
|
713
|
+
* those entries outright (codex, PR #992; originally reproduced against
|
|
714
|
+
* `@timber-js/app/segment-params`, an entry point since deleted by TIM-1342 —
|
|
715
|
+
* the hazard is unchanged for the entries that remain).
|
|
716
|
+
*
|
|
717
|
+
* See design/19-client-navigation.md §"Singleton Guarantee via globalThis"
|
|
718
|
+
*/
|
|
719
|
+
var PARAMS_CTX_KEY = Symbol.for("__timber_params_ctx");
|
|
720
|
+
function getOrCreateContext() {
|
|
721
|
+
const store = globalThis;
|
|
722
|
+
const existing = store[PARAMS_CTX_KEY];
|
|
723
|
+
if (existing !== void 0) return existing;
|
|
724
|
+
if (typeof React.createContext !== "function") return;
|
|
725
|
+
const ctx = React.createContext(null);
|
|
726
|
+
store[PARAMS_CTX_KEY] = ctx;
|
|
727
|
+
return ctx;
|
|
728
|
+
}
|
|
729
|
+
var ParamsContext = getOrCreateContext();
|
|
730
|
+
/**
|
|
731
|
+
* Read the params provided by the tree. Returns null only when no provider
|
|
732
|
+
* is above the caller — a component rendered outside a timber route. During
|
|
733
|
+
* SSR the wrapper chain mounts `PayloadRoot` too (TIM-1424), so both sides
|
|
734
|
+
* resolve through this context.
|
|
735
|
+
*/
|
|
736
|
+
function useParamsContext() {
|
|
737
|
+
return React.useContext(ParamsContext);
|
|
738
|
+
}
|
|
739
|
+
//#endregion
|
|
740
|
+
//#region src/client/use-segment-params.ts
|
|
741
|
+
function useSegmentParams(segmentPath) {
|
|
742
|
+
const paramsContext = useParamsContext();
|
|
743
|
+
if (paramsContext === null) throw new Error("[timber] useSegmentParams() was called outside the timber app tree (no params provider found). In tests, render the component inside the timber providers.");
|
|
744
|
+
return resolveSegmentParams(paramsContext.params, paramsContext.slotParams, segmentPath);
|
|
745
|
+
}
|
|
746
|
+
//#endregion
|
|
644
747
|
export { Link, LinkStatusContext, buildLinkProps, interpolateParams, mergePreservedSearchParams, replaceUrl, resolveHref, useActionState, useFormAction, useLinkStatus, usePathname, usePendingNavigation, useQueryStates, useRouter, useSegmentParams, useSelectedLayoutSegment, useSelectedLayoutSegments, validateNavigationHref as validateLinkHref };
|
|
645
748
|
|
|
646
749
|
//# sourceMappingURL=index.js.map
|