@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
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The order-dependence oracle shared by every route collision validator.
|
|
3
|
+
*
|
|
4
|
+
* A "collision space" is a set of pages that compete for URLs with each other:
|
|
5
|
+
* the main tree, each parallel slot, each intercepting subtree. Two pages in
|
|
6
|
+
* one space that answer the same URL are ambiguous — `matchNode` resolves the
|
|
7
|
+
* tie by whichever `children` array lists first, so which page renders is
|
|
8
|
+
* decided by filesystem enumeration order and renaming a route group can flip
|
|
9
|
+
* it. Every space rejects that shape, and they all reject it the same way,
|
|
10
|
+
* through this module.
|
|
11
|
+
*
|
|
12
|
+
* **The check asks the real matcher rather than modelling it.** For each leaf
|
|
13
|
+
* we build a URL it matches, then run `matchUrlParts` twice — once on the
|
|
14
|
+
* space, once on a clone with every `children` array reversed — and compare the
|
|
15
|
+
* winners. A URL answered by two or more candidates in the same priority tier
|
|
16
|
+
* resolves to whichever comes first in `children`, so reversing the arrays
|
|
17
|
+
* flips it; a URL with a single winner, or one settled by a higher tier, is
|
|
18
|
+
* unaffected. Order-dependence is therefore detected exactly, with no second
|
|
19
|
+
* copy of the precedence rules to drift.
|
|
20
|
+
*
|
|
21
|
+
* That drift is why this is written as an oracle. The interception validator's
|
|
22
|
+
* first version normalized each pattern into a "match shape" and compared
|
|
23
|
+
* shapes, which meant reimplementing `matchNode`'s tiers, its group flattening,
|
|
24
|
+
* and its zero-length optional-catch-all handling. Five review rounds found
|
|
25
|
+
* five divergences between the two — param spelling, a zero-length catch-all,
|
|
26
|
+
* the bracket tokens colliding with legal static directory names, a page
|
|
27
|
+
* settling a grouped catch-all, and a page settling a *direct* one (which the
|
|
28
|
+
* model could not express at all, because `matchNode` checks every route-group
|
|
29
|
+
* page before any direct optional catch-all). Each fix was locally right and
|
|
30
|
+
* the next divergence surfaced anyway. The model was the defect.
|
|
31
|
+
*
|
|
32
|
+
* **Every claim made here is existential** — "here is a URL these two contend
|
|
33
|
+
* for" — which is what a finite set of probes can actually establish. The
|
|
34
|
+
* reverse, "this page can never win any URL", is universal, and a probe's
|
|
35
|
+
* silence is not evidence for it: a leaf that loses every probe may still own
|
|
36
|
+
* URLs no probe visited. An earlier revision reported that as an
|
|
37
|
+
* unreachable-page error and produced two false build errors in one review
|
|
38
|
+
* round. Probe inadequacy must only ever cost a missed collision, never a
|
|
39
|
+
* rejected app — so nothing here may report a leaf as unreachable.
|
|
40
|
+
*
|
|
41
|
+
* See design/07-routing.md §"Comparing Routes by the URLs They Match".
|
|
42
|
+
*/
|
|
43
|
+
import type { SegmentNode } from './types.js';
|
|
44
|
+
/** One page-or-route-bearing node in a collision space. */
|
|
45
|
+
export interface ProbeLeaf {
|
|
46
|
+
/** The file that serves it — what the error message names. */
|
|
47
|
+
filePath: string;
|
|
48
|
+
/**
|
|
49
|
+
* The nodes from the space root down to this leaf that contribute URL parts
|
|
50
|
+
* — route groups excluded, since they are transparent for matching. Empty
|
|
51
|
+
* for the space root's own page: `matchUrlParts` matches parts against the
|
|
52
|
+
* root's *children*, so the root itself consumes nothing.
|
|
53
|
+
*/
|
|
54
|
+
chain: SegmentNode[];
|
|
55
|
+
}
|
|
56
|
+
/** Two files in one space that a single URL resolves to order-dependently. */
|
|
57
|
+
export interface ProbedCollision {
|
|
58
|
+
/** The contended URL, written for a human (see `describeProbeUrl`). */
|
|
59
|
+
url: string;
|
|
60
|
+
/** The file that wins in filesystem order. */
|
|
61
|
+
first: string;
|
|
62
|
+
/** The file that wins when every `children` array is reversed. */
|
|
63
|
+
second: string;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Find a URL in this collision space whose winner depends on `children` order,
|
|
67
|
+
* or null if every probed URL resolves the same way in both orderings.
|
|
68
|
+
*
|
|
69
|
+
* `spaceRoot` is the node `matchUrlParts` starts from — the app root, a slot
|
|
70
|
+
* node, or an intercepting directory. `base` is the URL that root sits at, used
|
|
71
|
+
* only to render the reported URL.
|
|
72
|
+
*/
|
|
73
|
+
export declare function findOrderDependentCollision(spaceRoot: SegmentNode, leaves: Iterable<ProbeLeaf>, base: string): ProbedCollision | null;
|
|
74
|
+
/**
|
|
75
|
+
* The values a probe's dynamic parts are tried with, in order.
|
|
76
|
+
*
|
|
77
|
+
* A probe stands in for "any value" at a dynamic position, so it is only useful
|
|
78
|
+
* if it reaches the leaf it was built for. A *static* sibling's literal name or
|
|
79
|
+
* a more specific *affixed* sibling's pattern can claim it instead, and that
|
|
80
|
+
* higher-priority segment then wins in both orderings — a genuine tie
|
|
81
|
+
* underneath goes unreported, which is safe but is the whole thing these
|
|
82
|
+
* validators are for.
|
|
83
|
+
*
|
|
84
|
+
* Which values are claimable is a question about `matchNode`'s precedence, so
|
|
85
|
+
* `probeUrlsForLeaf` asks `matchUrlParts` rather than deciding it here. This
|
|
86
|
+
* only has to offer enough shapes for the search to find one that works: an
|
|
87
|
+
* affixed sibling constrains the head of the value, its tail, or both, so head
|
|
88
|
+
* and tail are varied over an alphanumeric alphabet. The head varies fastest
|
|
89
|
+
* because a prefix is the more common affix. Exhausting the list is a missed
|
|
90
|
+
* collision like any other inadequate probe, so this is a search and not a
|
|
91
|
+
* proof — nothing downstream may treat it as one.
|
|
92
|
+
*
|
|
93
|
+
* Exported so a test that has to *name* a capturing static sibling can derive
|
|
94
|
+
* the name from this list rather than restate it — a fixture spelling the value
|
|
95
|
+
* out by hand stops being a capture the moment the list changes, and passes.
|
|
96
|
+
*
|
|
97
|
+
* Three revisions of a hand-built value each dodged one more capture and were
|
|
98
|
+
* each followed by another (avoid static names; avoid affix boundary
|
|
99
|
+
* characters; avoid re-affixed forms of static names — then a strictly more
|
|
100
|
+
* specific affixed sibling, TIM-1313). Each rule was modelling affix precedence
|
|
101
|
+
* by hand, which is what the match-shape model was deleted for.
|
|
102
|
+
*/
|
|
103
|
+
export declare function probeCandidates(minLength?: number): Generator<string>;
|
|
104
|
+
//# sourceMappingURL=collision-probe.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collision-probe.d.ts","sourceRoot":"","sources":["../../src/routing/collision-probe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAQ9C,2DAA2D;AAC3D,MAAM,WAAW,SAAS;IACxB,8DAA8D;IAC9D,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,KAAK,EAAE,WAAW,EAAE,CAAC;CACtB;AAED,8EAA8E;AAC9E,MAAM,WAAW,eAAe;IAC9B,uEAAuE;IACvE,GAAG,EAAE,MAAM,CAAC;IACZ,8CAA8C;IAC9C,KAAK,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CACzC,SAAS,EAAE,WAAW,EACtB,MAAM,EAAE,QAAQ,CAAC,SAAS,CAAC,EAC3B,IAAI,EAAE,MAAM,GACX,eAAe,GAAG,IAAI,CA4CxB;AA2CD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAiB,eAAe,CAAC,SAAS,SAAI,GAAG,SAAS,CAAC,MAAM,CAAC,CA6BjE"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Route collision spaces.
|
|
3
|
+
*
|
|
4
|
+
* A collision space is a set of routes that compete for URLs with each other,
|
|
5
|
+
* and there are three: the main tree, each parallel slot, and each intercepting
|
|
6
|
+
* subtree. This module owns the first two; `interception.ts` owns the third.
|
|
7
|
+
* All of them decide order-dependence with the one oracle in
|
|
8
|
+
* `collision-probe.ts`, so they cannot drift on what counts as two routes
|
|
9
|
+
* answering a single URL.
|
|
10
|
+
*
|
|
11
|
+
* See design/07-routing.md §"Route Collisions".
|
|
12
|
+
*/
|
|
13
|
+
import type { SegmentNode } from './types.js';
|
|
14
|
+
/**
|
|
15
|
+
* Validate that no two pages/routes in one collision space answer the same URL.
|
|
16
|
+
*
|
|
17
|
+
* Two route groups like (auth)/login/page.tsx and (marketing)/login/page.tsx both claim
|
|
18
|
+
* /login — the scanner must detect and reject this at build time.
|
|
19
|
+
*
|
|
20
|
+
* Each parallel slot is validated as its OWN collision space: a slot's pages
|
|
21
|
+
* intentionally share URL paths with the parent tree (that's the point of
|
|
22
|
+
* parallel routes), but two route groups INSIDE one slot claiming the same
|
|
23
|
+
* URL — e.g. @side/(a)/x/page.tsx + @side/(b)/x/page.tsx — still collide.
|
|
24
|
+
*/
|
|
25
|
+
export declare function validateRouteGroupCollisions(root: SegmentNode): void;
|
|
26
|
+
//# sourceMappingURL=collision-spaces.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collision-spaces.d.ts","sourceRoot":"","sources":["../../src/routing/collision-spaces.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAI9C;;;;;;;;;;GAUG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,CAEpE"}
|
package/dist/routing/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { i as
|
|
3
|
-
import {
|
|
1
|
+
import { a as collectInterceptionRewrites, i as scanRoutes } from "../_chunks/cli-schema-sync-CKgHC2MB.js";
|
|
2
|
+
import { a as INTERCEPTION_MARKERS, i as DEFAULT_PAGE_EXTENSIONS, n as classifyUrlSegment, t as classifySegment } from "../_chunks/segment-classify-C539Pa2O.js";
|
|
3
|
+
import { i as generateRouteMap, n as collectDynamicSegmentsFromTree, r as validateSchemaAgainstRoutes, t as collectLeafRoutes } from "../_chunks/walkers-BhhwI9TD.js";
|
|
4
4
|
export { DEFAULT_PAGE_EXTENSIONS, INTERCEPTION_MARKERS, classifySegment, classifyUrlSegment, collectDynamicSegmentsFromTree, collectInterceptionRewrites, collectLeafRoutes, generateRouteMap, scanRoutes, validateSchemaAgainstRoutes };
|
|
@@ -16,26 +16,255 @@
|
|
|
16
16
|
*
|
|
17
17
|
* See design/07-routing.md §"Intercepting Routes"
|
|
18
18
|
*/
|
|
19
|
-
import type { SegmentNode } from './types.js';
|
|
20
|
-
/**
|
|
21
|
-
|
|
19
|
+
import type { SegmentNode, InterceptionMarker } from './types.js';
|
|
20
|
+
/** Fields shared by both interception shapes. */
|
|
21
|
+
interface InterceptionRewriteBase {
|
|
22
22
|
/**
|
|
23
23
|
* The URL pattern that this rewrite intercepts (the target of navigation).
|
|
24
24
|
* E.g., "/photo/[id]" for a (.)photo/[id] interception.
|
|
25
25
|
*/
|
|
26
26
|
interceptedPattern: string;
|
|
27
27
|
/**
|
|
28
|
-
* The
|
|
29
|
-
*
|
|
30
|
-
*
|
|
28
|
+
* The tree path of the segment that OWNS the slot holding this
|
|
29
|
+
* intercepting route (`computeSegmentTreePaths`, e.g. "/feed",
|
|
30
|
+
* "/(browse)", "/(browse)/feed", or "/" at the app root).
|
|
31
|
+
*
|
|
32
|
+
* The rewrite only applies when the source route — the page the user is
|
|
33
|
+
* navigating FROM — passes through that directory, because only then
|
|
34
|
+
* does the slot holding the intercepting page exist in the rendered
|
|
35
|
+
* tree. The server checks this by matching X-Timber-URL and testing its
|
|
36
|
+
* segment chain's tree paths for this value.
|
|
37
|
+
*
|
|
38
|
+
* Neither of the identities already in the codebase works here:
|
|
39
|
+
*
|
|
40
|
+
* - A **URL prefix** cannot express it. Route groups contribute nothing
|
|
41
|
+
* to `urlPath`, so `(browse)/@detail/(...)x` and a genuinely
|
|
42
|
+
* root-level `@modal/(...)x` both have prefix "/" while meaning very
|
|
43
|
+
* different things.
|
|
44
|
+
* - A **state-tree key** (`computeSegmentKeys`) cannot either. It
|
|
45
|
+
* qualifies a group with its ancestry but resets to `urlPath` at the
|
|
46
|
+
* next URL-visible segment, so `(browse)/feed` and `(landing)/feed`
|
|
47
|
+
* both key as "/feed" — and a navigation inside `(landing)/feed/…`
|
|
48
|
+
* would reach `(browse)/feed`'s slot.
|
|
49
|
+
*
|
|
50
|
+
* Tree paths never reset, so two directories that render different
|
|
51
|
+
* layouts never share one. "/" as a scope means the app root, which
|
|
52
|
+
* every route passes through — preserving the intentional
|
|
53
|
+
* match-from-anywhere behavior of a root-level `(...)` interception
|
|
54
|
+
* (TIM-1006) without an exemption. See TIM-1279.
|
|
55
|
+
*/
|
|
56
|
+
interceptingScope: string;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* A conditional rewrite rule generated from an intercepting route.
|
|
60
|
+
*
|
|
61
|
+
* `mode` records which of the two shapes the directory expresses, because the
|
|
62
|
+
* two render through entirely different mechanisms and the fields they need
|
|
63
|
+
* are not the same. It is a union rather than a flag so a reader cannot
|
|
64
|
+
* re-match `interceptingPrefix` on the shape that has no such pathname.
|
|
65
|
+
*
|
|
66
|
+
* See design/07-routing.md §"Intercepting Routes".
|
|
67
|
+
*/
|
|
68
|
+
export type InterceptionRewrite = SlotInterceptionRewrite | ChildrenInterceptionRewrite;
|
|
69
|
+
/**
|
|
70
|
+
* A **modal overlay** interception — the intercepting directory is a direct
|
|
71
|
+
* child of a parallel slot (`feed/@modal/(.)photo/[id]`).
|
|
72
|
+
*
|
|
73
|
+
* The server re-matches the *source* route and the slot resolver finds the
|
|
74
|
+
* intercepting child inside the slot, so the intercepting page layers over
|
|
75
|
+
* the page the user was already on.
|
|
76
|
+
*/
|
|
77
|
+
export interface SlotInterceptionRewrite extends InterceptionRewriteBase {
|
|
78
|
+
mode: 'slot';
|
|
79
|
+
/**
|
|
80
|
+
* The pathname the server re-matches when this rewrite applies — the
|
|
81
|
+
* intercepting slot owner's URL path. E.g., "/feed" for a (.)photo/[id]
|
|
82
|
+
* inside /feed/@modal/.
|
|
83
|
+
*
|
|
84
|
+
* This is a build-time constant, never a client-supplied value: the
|
|
85
|
+
* X-Timber-URL header selects a rewrite but never becomes the rendered
|
|
86
|
+
* pathname.
|
|
31
87
|
*/
|
|
32
88
|
interceptingPrefix: string;
|
|
33
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* A **sibling layout swap** interception — the intercepting directory is a
|
|
92
|
+
* direct child of an ordinary segment or route group
|
|
93
|
+
* (`(browse)/(...)[artistSlug]/…`).
|
|
94
|
+
*
|
|
95
|
+
* There is no overlay, no slot and no `default.tsx`: the intercepting page
|
|
96
|
+
* *replaces* `children` for the owner's layout chain. Nothing is re-matched
|
|
97
|
+
* either. The server resolves the owner by `interceptingScope` — a tree path,
|
|
98
|
+
* which identifies exactly one directory — and builds the rendered chain as
|
|
99
|
+
* `[…owner ancestors, interceptingNode, …its matched descendants]`. That is an
|
|
100
|
+
* ordinary segment chain, so `tree-builder.ts` renders it with no knowledge
|
|
101
|
+
* that interception happened.
|
|
102
|
+
*
|
|
103
|
+
* Resolving the owner from the tree rather than from a URL is what makes this
|
|
104
|
+
* shape work where the modal shape cannot: `interceptingPrefix` is
|
|
105
|
+
* URL-derived, and a route group contributes nothing to `urlPath`, so an owner
|
|
106
|
+
* like `app/(browse)/` serializes to "/" and re-matching it lands in whichever
|
|
107
|
+
* group owns the canonical page. A tree path never collapses (TIM-1280).
|
|
108
|
+
*/
|
|
109
|
+
export interface ChildrenInterceptionRewrite extends InterceptionRewriteBase {
|
|
110
|
+
mode: 'children';
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* A set of sibling interceptors that compete for one URL position.
|
|
114
|
+
*
|
|
115
|
+
* `base` is the intercepted base they share — the URL their own segments sit
|
|
116
|
+
* directly under — and `anchorIndex` is how many URL parts that base spans,
|
|
117
|
+
* which is the index in a target pathname their segments are matched at.
|
|
118
|
+
* Deeper anchors are more local and are tried first.
|
|
119
|
+
*/
|
|
120
|
+
export interface InterceptorAnchorGroup<TFile> {
|
|
121
|
+
base: string;
|
|
122
|
+
anchorIndex: number;
|
|
123
|
+
interceptors: SegmentNode<TFile>[];
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Group an owner's intercepting children by the URL position they contend for.
|
|
127
|
+
*
|
|
128
|
+
* This is the definition of *which interceptors compete*, and it has exactly
|
|
129
|
+
* one caller shape on each side of the build: `findInterceptingMatch` resolves
|
|
130
|
+
* a group with one `matchUrlParts` walk, and
|
|
131
|
+
* `assertNoInterceptedPatternCollisions` validates the same group as one
|
|
132
|
+
* collision space. Written twice, the two would be free to disagree about what
|
|
133
|
+
* competes — and a resolver that walks a wider set than the validator checked
|
|
134
|
+
* is precisely the order-dependence the validator exists to reject (TIM-1310).
|
|
135
|
+
*
|
|
136
|
+
* Contention is keyed by the computed intercepted **base**, not by the marker:
|
|
137
|
+
* under an owner at `/feed`, `(..)` and `(...)` both base at `/` and are both
|
|
138
|
+
* matched at index 0, so they are one group. Different bases are different
|
|
139
|
+
* positions — a `(.)` interceptor can never claim a target that belongs to a
|
|
140
|
+
* `(..)` one beside it, because the base must also match the target's leading
|
|
141
|
+
* parts.
|
|
142
|
+
*
|
|
143
|
+
* The base is a URL *pattern*, so its length is its part count only because
|
|
144
|
+
* every pattern part stands for exactly one URL part. A catch-all in the base
|
|
145
|
+
* breaks that, and `assertInterceptedBaseIsCountable` rejects the shape at
|
|
146
|
+
* build time.
|
|
147
|
+
*
|
|
148
|
+
* A node missing either marker field is skipped, which `classifySegment` never
|
|
149
|
+
* produces — it sets both whenever it reports `'intercepting'`. Stating the
|
|
150
|
+
* filter here rather than defaulting the marker is what makes the validator and
|
|
151
|
+
* the resolver see the same set: such a node renders nothing either way, and a
|
|
152
|
+
* validator more permissive than the resolver would be checking a candidate
|
|
153
|
+
* that never competes while the resolver walks one nobody checked.
|
|
154
|
+
*
|
|
155
|
+
* `children` is read directly rather than flattened through route groups,
|
|
156
|
+
* matching both resolvers: the slot resolver reads `slotNode.children`, and an
|
|
157
|
+
* interceptor deeper inside a slot subtree is rejected by
|
|
158
|
+
* `validateInterceptionPlacement`. On the children path an interceptor under a
|
|
159
|
+
* route group is legal and the *group* is its owner, so it is grouped with that
|
|
160
|
+
* group's other interceptors — which is again exactly what the resolver walks,
|
|
161
|
+
* since it resolves the owner by tree path.
|
|
162
|
+
*/
|
|
163
|
+
export declare function groupByInterceptedAnchor<TFile>(ownerUrlPath: string, children: readonly SegmentNode<TFile>[]): InterceptorAnchorGroup<TFile>[];
|
|
34
164
|
/**
|
|
35
165
|
* Collect all interception rewrite rules from the route tree.
|
|
36
166
|
*
|
|
37
167
|
* Walks the tree recursively. For each intercepting segment, computes the
|
|
38
168
|
* intercepted URL based on the marker and the segment's position.
|
|
169
|
+
*
|
|
170
|
+
* The list is returned **deepest scope first**, which is what makes
|
|
171
|
+
* `findInterceptionMatch`'s first-match rule deterministic; see
|
|
172
|
+
* `sortByScopeDepth`.
|
|
39
173
|
*/
|
|
40
174
|
export declare function collectInterceptionRewrites(root: SegmentNode): InterceptionRewrite[];
|
|
175
|
+
/**
|
|
176
|
+
* Validate that every intercepting segment sits where it can actually render.
|
|
177
|
+
*
|
|
178
|
+
* There are exactly two positions a renderer exists for, and they are the two
|
|
179
|
+
* shapes interception has:
|
|
180
|
+
*
|
|
181
|
+
* 1. **Direct child of a parallel slot** — the modal overlay. The slot
|
|
182
|
+
* resolver scans a slot node's *direct children* for an intercepting
|
|
183
|
+
* segment (`server/slot-interception.ts`). Nothing between the slot and
|
|
184
|
+
* the intercepting directory is allowed, because nothing walks it.
|
|
185
|
+
* 2. **Direct child of an ordinary segment or route group** — the sibling
|
|
186
|
+
* layout swap (TIM-1280). The pipeline resolves the owner by tree path and
|
|
187
|
+
* builds the rendered chain through the intercepting node itself
|
|
188
|
+
* (`server/children-interception.ts`).
|
|
189
|
+
*
|
|
190
|
+
* Everywhere else, rewrite generation still emits a rewrite and nothing
|
|
191
|
+
* renders it: the rewrite matches the soft navigation, and the user is served
|
|
192
|
+
* the page they were already on under a changed URL (TIM-1278). The rejected
|
|
193
|
+
* positions are:
|
|
194
|
+
*
|
|
195
|
+
* - **Inside a slot subtree but not directly under the slot**
|
|
196
|
+
* (`@modal/(inner)/(.)photo`). Neither renderer applies: the slot resolver
|
|
197
|
+
* only reads direct children, and the children-path resolver builds a
|
|
198
|
+
* *chain*, which cannot express a descent through a slot.
|
|
199
|
+
* - **Inside another intercepting subtree** (`(.)a/(.)b`). Left unvalidated
|
|
200
|
+
* `collectLeavesWithRewrites` walks the inner one as an ordinary URL
|
|
201
|
+
* segment and emits a pattern containing a literal "(.)b".
|
|
202
|
+
*
|
|
203
|
+
* Two further shapes are rejected here (TIM-1288). Both are about a catch-all,
|
|
204
|
+
* and both are specific to interception: elsewhere in the tree the same
|
|
205
|
+
* shapes are inert or fail safely, and the general "nothing below a catch-all
|
|
206
|
+
* is reachable" rule is tracked as TIM-1286.
|
|
207
|
+
*
|
|
208
|
+
* And one is specific to the children path: an owner chain that binds params
|
|
209
|
+
* (see `assertOwnerChainBindsNoParams`).
|
|
210
|
+
*/
|
|
211
|
+
export declare function validateInterceptionPlacement(root: SegmentNode): void;
|
|
212
|
+
/**
|
|
213
|
+
* The URL-matching identity of an intercepting node, as a node.
|
|
214
|
+
*
|
|
215
|
+
* `matchUrlParts` reads `segmentType` directly and knows nothing about
|
|
216
|
+
* interception, so a marker'd directory has to be handed to it under the
|
|
217
|
+
* identity of the segment it intercepts — `(.)[id]` as `[id]`. Priority
|
|
218
|
+
* ordering, affix stripping and catch-all handling then come from the shared
|
|
219
|
+
* walker rather than from a second classifier here.
|
|
220
|
+
*
|
|
221
|
+
* Shared with `findInterceptingMatch` for the same reason the grouping is: the
|
|
222
|
+
* collision space is the resolver's synthetic anchor parent, so its children
|
|
223
|
+
* have to carry the identity the resolver gives them or the validator would be
|
|
224
|
+
* probing a tree that does not match the one served. The caller keeps its own
|
|
225
|
+
* map back to the real node — the proxy is a matching identity, not a
|
|
226
|
+
* replacement (tree paths still need the directory name).
|
|
227
|
+
*/
|
|
228
|
+
export declare function interceptorProxy<TFile>(node: SegmentNode<TFile>): SegmentNode<TFile>;
|
|
229
|
+
/**
|
|
230
|
+
* Compute the base URL that an intercepting route intercepts, given the
|
|
231
|
+
* parent's URL path and the interception marker.
|
|
232
|
+
*
|
|
233
|
+
* - (.) — same level: parent's URL path
|
|
234
|
+
* - (..) — one level up: parent's parent URL path
|
|
235
|
+
* - (...) — root level: /
|
|
236
|
+
* - (..)(..) — two levels up: parent's grandparent URL path
|
|
237
|
+
*
|
|
238
|
+
* The result is a URL **pattern**, not a URL — `parentUrlPath` carries the
|
|
239
|
+
* directory names, so a dynamic ancestor appears as `/docs/[...path]`.
|
|
240
|
+
* Rewrite generation wants exactly that. The slot resolver imports this to
|
|
241
|
+
* locate the intercepted segment in a concrete target pathname, and must
|
|
242
|
+
* therefore account for a bracket part standing for a different number of
|
|
243
|
+
* URL parts than itself (TIM-1281).
|
|
244
|
+
*
|
|
245
|
+
* Climbing past the root clamps to `/` rather than erroring, so generation
|
|
246
|
+
* and resolution never disagree about what an over-reaching marker
|
|
247
|
+
* intercepts.
|
|
248
|
+
*/
|
|
249
|
+
/**
|
|
250
|
+
* The URL pattern an intercepting directory's own page sits at — its
|
|
251
|
+
* `computeInterceptedBase` joined with the segment it intercepts.
|
|
252
|
+
*
|
|
253
|
+
* The root case is why this is a function rather than a template literal at
|
|
254
|
+
* each caller: a base of `/` must not produce `//photo`. Rewrite generation
|
|
255
|
+
* and the collision validator both start their walk from this value, so the
|
|
256
|
+
* two describe the same URLs by construction.
|
|
257
|
+
*/
|
|
258
|
+
export declare function computeInterceptedUrlBase(parentUrlPath: string, marker: InterceptionMarker, interceptedSegmentName: string): string;
|
|
259
|
+
/**
|
|
260
|
+
* An intercepted base joined with one segment beneath it.
|
|
261
|
+
*
|
|
262
|
+
* The whole content of the "function rather than a template literal" rule
|
|
263
|
+
* above: a base of `/` must not produce `//photo`. The collision validator has
|
|
264
|
+
* the base in hand already (it groups by it) and joins through this rather than
|
|
265
|
+
* re-deriving it from an owner path, so both callers spell the root case once.
|
|
266
|
+
*/
|
|
267
|
+
export declare function joinInterceptedBase(base: string, segmentName: string): string;
|
|
268
|
+
export declare function computeInterceptedBase(parentUrlPath: string, marker: InterceptionMarker): string;
|
|
269
|
+
export {};
|
|
41
270
|
//# sourceMappingURL=interception.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interception.d.ts","sourceRoot":"","sources":["../../src/routing/interception.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"interception.d.ts","sourceRoot":"","sources":["../../src/routing/interception.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAa,MAAM,YAAY,CAAC;AAQ7E,iDAAiD;AACjD,UAAU,uBAAuB;IAC/B;;;OAGG;IACH,kBAAkB,EAAE,MAAM,CAAC;IAC3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4BG;IACH,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,mBAAmB,GAAG,uBAAuB,GAAG,2BAA2B,CAAC;AAExF;;;;;;;GAOG;AACH,MAAM,WAAW,uBAAwB,SAAQ,uBAAuB;IACtE,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;;;OAQG;IACH,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,2BAA4B,SAAQ,uBAAuB;IAC1E,IAAI,EAAE,UAAU,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,sBAAsB,CAAC,KAAK;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;CACpC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAC5C,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,SAAS,WAAW,CAAC,KAAK,CAAC,EAAE,GACtC,sBAAsB,CAAC,KAAK,CAAC,EAAE,CAuBjC;AAED;;;;;;;;;GASG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,WAAW,GAAG,mBAAmB,EAAE,CAIpF;AAqDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,CAOrE;AAwPD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,IAAI,EAAE,WAAW,CAAC,KAAK,CAAC,GAAG,WAAW,CAAC,KAAK,CAAC,CAEpF;AA4WD;;;;;;;;;;;;;;;;;;;GAmBG;AACH;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CACvC,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,kBAAkB,EAC1B,sBAAsB,EAAE,MAAM,GAC7B,MAAM,CAER;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAE7E;AAED,wBAAgB,sBAAsB,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,GAAG,MAAM,CAOhG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest-codegen.d.ts","sourceRoot":"","sources":["../../src/routing/manifest-codegen.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,KAAK,EAAE,SAAS,EAA0B,MAAM,YAAY,CAAC;AAyBpE;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"manifest-codegen.d.ts","sourceRoot":"","sources":["../../src/routing/manifest-codegen.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,KAAK,EAAE,SAAS,EAA0B,MAAM,YAAY,CAAC;AAyBpE;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAiJhF;AAID;;;;GAIG;AACH,wBAAgB,kCAAkC,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAuC1E;AAQD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CA8B3D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../src/routing/scanner.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EACV,SAAS,EAIT,aAAa,EAEd,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../src/routing/scanner.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EACV,SAAS,EAIT,aAAa,EAEd,MAAM,YAAY,CAAC;AA2BpB;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,GAAE,aAAkB,GAAG,SAAS,CAsDhF"}
|
|
@@ -78,4 +78,37 @@ export interface SegmentClassification {
|
|
|
78
78
|
* If you change the directory-prefix conventions, update this function.
|
|
79
79
|
*/
|
|
80
80
|
export declare function classifySegment(dirName: string): SegmentClassification;
|
|
81
|
+
/**
|
|
82
|
+
* The URL-matching identity of a segment node.
|
|
83
|
+
*
|
|
84
|
+
* For every node except an intercepting one this is the node itself. An
|
|
85
|
+
* intercepting node is different: its directory name carries a marker
|
|
86
|
+
* (`(.)photo`, `(.)[id]`), so the node's own `segmentType` is
|
|
87
|
+
* `'intercepting'` and the bracket syntax of the segment it intercepts was
|
|
88
|
+
* never classified. Everything that has to reason about *the URL part this
|
|
89
|
+
* node stands for* — matching it, and keying its param for codec coercion —
|
|
90
|
+
* needs that classification.
|
|
91
|
+
*
|
|
92
|
+
* Deriving it here, from `interceptedSegmentName`, keeps interception out
|
|
93
|
+
* of `classifySegment`'s output and out of the serialized manifest: there
|
|
94
|
+
* is no second copy of the classification to drift from this one. The
|
|
95
|
+
* returned `segmentName` is the intercepted name (`photo`, `[id]`), NOT the
|
|
96
|
+
* node's directory name — callers that need the directory name for tree
|
|
97
|
+
* paths must keep reading the node. See TIM-1281.
|
|
98
|
+
*/
|
|
99
|
+
export interface UrlSegmentIdentity {
|
|
100
|
+
segmentName: string;
|
|
101
|
+
segmentType: SegmentType;
|
|
102
|
+
paramName?: string;
|
|
103
|
+
paramPrefix?: string;
|
|
104
|
+
paramSuffix?: string;
|
|
105
|
+
}
|
|
106
|
+
export declare function effectiveUrlSegment(node: {
|
|
107
|
+
segmentName: string;
|
|
108
|
+
segmentType: SegmentType;
|
|
109
|
+
paramName?: string;
|
|
110
|
+
paramPrefix?: string;
|
|
111
|
+
paramSuffix?: string;
|
|
112
|
+
interceptedSegmentName?: string;
|
|
113
|
+
}): UrlSegmentIdentity;
|
|
81
114
|
//# sourceMappingURL=segment-classify.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"segment-classify.d.ts","sourceRoot":"","sources":["../../src/routing/segment-classify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAGlE,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GACnE;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,oBAAoB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CA4E5D;AAID,yDAAyD;AACzD,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,qBAAqB,CAuCtE"}
|
|
1
|
+
{"version":3,"file":"segment-classify.d.ts","sourceRoot":"","sources":["../../src/routing/segment-classify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAGlE,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GACnE;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,oBAAoB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CA4E5D;AAID,yDAAyD;AACzD,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,qBAAqB,CAuCtE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,WAAW,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,WAAW,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC,GAAG,kBAAkB,CAsBrB"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Segment key computation — the stable identity of a segment in the route tree.
|
|
3
|
+
*
|
|
4
|
+
* A segment key is the string that names a segment across the RSC/SSR/client
|
|
5
|
+
* boundary: it appears in the X-Timber-State-Tree header, the X-Timber-Segments
|
|
6
|
+
* header, SegmentOutlet props, the client segment cache, and (since TIM-1279)
|
|
7
|
+
* interception scoping.
|
|
8
|
+
*
|
|
9
|
+
* This module lives in `routing/` rather than `server/` because the keys are a
|
|
10
|
+
* property of the route tree itself — both the build-time scanner tree and the
|
|
11
|
+
* runtime manifest tree produce identical keys for the same directory, which is
|
|
12
|
+
* what lets a build-time value (an interception scope) be compared against a
|
|
13
|
+
* request-time matched chain.
|
|
14
|
+
*
|
|
15
|
+
* See design/19-client-navigation.md §"X-Timber-State-Tree Header"
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Segment node shape expected by computeSegmentKeys.
|
|
19
|
+
*
|
|
20
|
+
* Structurally satisfied by both `SegmentNode` (build time) and
|
|
21
|
+
* `ManifestSegmentNode` (request time) — keys depend only on the
|
|
22
|
+
* URL path and the segment classification, never on file payloads.
|
|
23
|
+
*/
|
|
24
|
+
export interface SegmentKeyInput {
|
|
25
|
+
urlPath: string;
|
|
26
|
+
segmentName?: string;
|
|
27
|
+
segmentType?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Compute state-tree keys for a segment chain.
|
|
31
|
+
*
|
|
32
|
+
* Non-group segments use their urlPath as-is. Route groups accumulate
|
|
33
|
+
* ancestor group names to produce globally unique keys:
|
|
34
|
+
* app/(a)/(shared)/dashboard → keys: ['/', '/(a)', '/(a)/(shared)', '/dashboard']
|
|
35
|
+
*
|
|
36
|
+
* **An intercepting segment switches the chain to name accumulation for good.**
|
|
37
|
+
* A children-path interception (TIM-1280) puts an intercepting node and its
|
|
38
|
+
* descendants into the *main* rendered chain, and their `urlPath`s are not
|
|
39
|
+
* URLs: interception adds no URL depth, so `app/(browse)/(...)[artistSlug]/[year]`
|
|
40
|
+
* carries `/` and `/[year]`. Keyed by urlPath the intercepting node would
|
|
41
|
+
* collide with its own owner, and `[year]` with any top-level `[year]` route —
|
|
42
|
+
* so a client that had one mounted would reuse the wrong cached layout. The
|
|
43
|
+
* switch is sticky rather than per-node because the *descendants* are where
|
|
44
|
+
* the false URLs are; the intercepting node alone is not the problem.
|
|
45
|
+
*
|
|
46
|
+
* This is the single source of truth for segment keys — used by the
|
|
47
|
+
* element builder (skip decisions, SegmentOutlet props), segment info
|
|
48
|
+
* (X-Timber-Segments header), the client cache/state tree, and
|
|
49
|
+
* interception scoping (`routing/interception.ts`).
|
|
50
|
+
*/
|
|
51
|
+
export declare function computeSegmentKeys(segments: SegmentKeyInput[]): string[];
|
|
52
|
+
/**
|
|
53
|
+
* Compute tree paths for a segment chain — the directory path of each segment
|
|
54
|
+
* with slots elided, e.g. `app/(browse)/feed` → `/(browse)/feed`.
|
|
55
|
+
*
|
|
56
|
+
* This is `computeSegmentKeys` with the group branch applied to *every*
|
|
57
|
+
* segment rather than only to groups. That one difference is the whole point:
|
|
58
|
+
* `computeSegmentKeys` resets to `urlPath` at each URL-visible segment, so
|
|
59
|
+
* `(browse)/feed` and `(landing)/feed` both key as `/feed`. Two directories
|
|
60
|
+
* that render different layouts must not share an identity.
|
|
61
|
+
*
|
|
62
|
+
* Used for interception scoping (`routing/interception.ts`), where the
|
|
63
|
+
* question is "does this route pass through *that* directory?" — not "does it
|
|
64
|
+
* render this URL?". Not interchangeable with `computeSegmentKeys`: the state
|
|
65
|
+
* tree is keyed by URL on purpose, because the client caches by URL.
|
|
66
|
+
*/
|
|
67
|
+
export declare function computeSegmentTreePaths(segments: SegmentKeyInput[]): string[];
|
|
68
|
+
/**
|
|
69
|
+
* The directory names a tree path is built from — `/` is none, `/feed/(a)` is
|
|
70
|
+
* `['feed', '(a)']`.
|
|
71
|
+
*
|
|
72
|
+
* The inverse of the walk above, and it lives beside it so the format is
|
|
73
|
+
* stated once: `findChainByTreePath` (`server/children-interception.ts`) walks
|
|
74
|
+
* these names back down the tree to the directory the path addresses, and
|
|
75
|
+
* `treePathDepth` counts them. Both are readings of the same string, and a
|
|
76
|
+
* reader that disagreed with the producer about what separates two names
|
|
77
|
+
* resolves an interception to the wrong node or to none.
|
|
78
|
+
*/
|
|
79
|
+
export declare function treePathNames(treePath: string): string[];
|
|
80
|
+
/**
|
|
81
|
+
* How many directories a tree path names — `/` is 0, `/feed` is 1,
|
|
82
|
+
* `/feed/(a)` is 2.
|
|
83
|
+
*
|
|
84
|
+
* Two tree paths on a single rendered chain are strictly nested, so on that
|
|
85
|
+
* chain depth orders them totally — which is what makes it usable as "the
|
|
86
|
+
* deeper of these two directories" wherever a route passes through both
|
|
87
|
+
* (`routing/interception.ts`).
|
|
88
|
+
*/
|
|
89
|
+
export declare function treePathDepth(treePath: string): number;
|
|
90
|
+
/**
|
|
91
|
+
* Compute a unique key for a parallel route slot.
|
|
92
|
+
* Format: `{parentSegmentId}/@{slotName}`, e.g. `/@sidebar` or `/dashboard/@modal`.
|
|
93
|
+
*/
|
|
94
|
+
export declare function computeSlotKey(parentSegmentId: string, slotName: string): string;
|
|
95
|
+
//# sourceMappingURL=segment-keys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"segment-keys.d.ts","sourceRoot":"","sources":["../../src/routing/segment-keys.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,eAAe,EAAE,GAAG,MAAM,EAAE,CAmBxE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,eAAe,EAAE,GAAG,MAAM,EAAE,CAmB7E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAExD;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,eAAe,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAIhF"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parallel slot placement.
|
|
3
|
+
*
|
|
4
|
+
* One rule: a slot is resolved only for a segment on the **matched route
|
|
5
|
+
* chain**, and a slot's own subtree is never on that chain. So a slot declared
|
|
6
|
+
* anywhere inside another slot's subtree can never render, and is rejected at
|
|
7
|
+
* build time rather than left as a directory the author will keep editing.
|
|
8
|
+
*
|
|
9
|
+
* See design/07-routing.md §"Parallel Routes".
|
|
10
|
+
*/
|
|
11
|
+
import type { SegmentNode } from './types.js';
|
|
12
|
+
/**
|
|
13
|
+
* Reject every parallel slot that no renderer reaches.
|
|
14
|
+
*
|
|
15
|
+
* **Where slots are resolved.** Two places read `segment.slots`, and both walk
|
|
16
|
+
* the main route chain: `route-element-builder.ts` (the RSC render) and
|
|
17
|
+
* `tree-builder.ts`. Neither is reachable from inside a slot. The slot's own
|
|
18
|
+
* subtree is rendered by `slot-resolver.ts`, which walks the slot's matched
|
|
19
|
+
* chain to apply that chain's layouts, error boundaries and access gates
|
|
20
|
+
* (`wrapWithIntermediateSegments`, `wrapWithLayout`) and never reads `.slots`
|
|
21
|
+
* on any of those nodes. So `app/feed/@modal/photo/@side/page.tsx` and
|
|
22
|
+
* everything below it is dead: the file is scanned, typed, code-split and
|
|
23
|
+
* shipped, and no request can render it.
|
|
24
|
+
*
|
|
25
|
+
* That is the TIM-1278 failure — a directory that silently never renders —
|
|
26
|
+
* and the reason it is a build error rather than a documented limit is that
|
|
27
|
+
* nothing at request time can report it. A slot that does not match renders
|
|
28
|
+
* `default.tsx` or `null`, which is exactly what a slot the resolver never
|
|
29
|
+
* looked at also produces, so the author sees the *designed* behaviour of a
|
|
30
|
+
* non-matching slot and has no signal to distinguish it from a slot that
|
|
31
|
+
* cannot match at all.
|
|
32
|
+
*
|
|
33
|
+
* **Interception is incidental.** TIM-1311 arrived as
|
|
34
|
+
* `feed/@modal/(.)photo/@side`, and the interception contributes nothing: the
|
|
35
|
+
* identical `feed/@modal/photo/@side` never renders either, for the same
|
|
36
|
+
* reason and with no marker anywhere. Rejecting only the intercepting spelling
|
|
37
|
+
* would have drawn a line the author cannot see from the directory names.
|
|
38
|
+
*
|
|
39
|
+
* The children-path interception shape is **not** affected and must not be:
|
|
40
|
+
* its intercepting node joins the main chain (`server/children-interception.ts`
|
|
41
|
+
* splices `[…owner ancestors, interceptingNode, …descendants]` into an ordinary
|
|
42
|
+
* `RouteMatch`), so `route-element-builder.ts` resolves slots on it and below
|
|
43
|
+
* it exactly as it does for any other chain segment. `(browse)/(...)photo/[id]/@side`
|
|
44
|
+
* renders; `feed/@modal/(.)photo/@side` does not. The discriminator is the slot
|
|
45
|
+
* boundary, which is what this walk tracks — not the marker.
|
|
46
|
+
*/
|
|
47
|
+
export declare function validateSlotPlacement(root: SegmentNode): void;
|
|
48
|
+
//# sourceMappingURL=slot-placement.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slot-placement.d.ts","sourceRoot":"","sources":["../../src/routing/slot-placement.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,CAE7D"}
|
|
@@ -45,6 +45,12 @@ export interface CollectLeafRoutesOptions {
|
|
|
45
45
|
* entries (the build report deduplicates by URL afterward).
|
|
46
46
|
* - Parallel slots are skipped unless `includeSlots: true` (slots
|
|
47
47
|
* share their parent's URL and are not addressable on their own).
|
|
48
|
+
* - Intercepting subtrees are skipped unconditionally. They render only
|
|
49
|
+
* on soft navigation and add no URL depth, so their computed `urlPath`s
|
|
50
|
+
* are not addresses — listing them would advertise routes (`/[year]`)
|
|
51
|
+
* that no request can reach. This matches every other consumer of the
|
|
52
|
+
* tree that produces URLs: the sitemap generator, the static generator,
|
|
53
|
+
* prerendering and the prebuilt-payload builder all skip them too.
|
|
48
54
|
* - Result is sorted by `urlPath` for deterministic output.
|
|
49
55
|
*/
|
|
50
56
|
export declare function collectLeafRoutes<TFile>(root: SegmentNode<TFile>, options?: CollectLeafRoutesOptions): LeafRoute<TFile>[];
|