@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.
Files changed (418) hide show
  1. package/dist/_chunks/{actions-O_LsyCE4.js → actions-C-Rw9vPc.js} +3 -3
  2. package/dist/_chunks/{actions-O_LsyCE4.js.map → actions-C-Rw9vPc.js.map} +1 -1
  3. package/dist/_chunks/als-slots-mFweg276.js +27 -0
  4. package/dist/_chunks/als-slots-mFweg276.js.map +1 -0
  5. package/dist/_chunks/base-path-DaQrzbez.js +80 -0
  6. package/dist/_chunks/base-path-DaQrzbez.js.map +1 -0
  7. package/dist/_chunks/build-manifest-DWppEdLB.js +86 -0
  8. package/dist/_chunks/build-manifest-DWppEdLB.js.map +1 -0
  9. package/dist/_chunks/build-output-helper-C3DrfzZR.js +369 -0
  10. package/dist/_chunks/build-output-helper-C3DrfzZR.js.map +1 -0
  11. package/dist/_chunks/{cache-api-B-lhk9p4.js → cache-api-Cd0VZ_Pd.js} +3 -3
  12. package/dist/_chunks/{cache-api-B-lhk9p4.js.map → cache-api-Cd0VZ_Pd.js.map} +1 -1
  13. package/dist/_chunks/cli-schema-sync-CKgHC2MB.js +1857 -0
  14. package/dist/_chunks/cli-schema-sync-CKgHC2MB.js.map +1 -0
  15. package/dist/_chunks/{cloudflare-CnT5Lr7U.js → cloudflare-Cs0uZXea.js} +89 -12
  16. package/dist/_chunks/{cloudflare-CnT5Lr7U.js.map → cloudflare-Cs0uZXea.js.map} +1 -1
  17. package/dist/_chunks/error-boundary-DpYRI_I1.js +330 -0
  18. package/dist/_chunks/error-boundary-DpYRI_I1.js.map +1 -0
  19. package/dist/_chunks/{fast-hash-D6hIVt1Y.js → fast-hash-C-tVYrLb.js} +6 -1
  20. package/dist/_chunks/fast-hash-C-tVYrLb.js.map +1 -0
  21. package/dist/_chunks/fs-identity-D7vb6GdI.js +208 -0
  22. package/dist/_chunks/fs-identity-D7vb6GdI.js.map +1 -0
  23. package/dist/_chunks/{logger-AWfuX-KJ.js → logger-N7e5auP0.js} +9 -13
  24. package/dist/_chunks/logger-N7e5auP0.js.map +1 -0
  25. package/dist/_chunks/navigation-root-B29qg0_T.js +274 -0
  26. package/dist/_chunks/navigation-root-B29qg0_T.js.map +1 -0
  27. package/dist/_chunks/param-value-C8TNYchQ.js +66 -0
  28. package/dist/_chunks/param-value-C8TNYchQ.js.map +1 -0
  29. package/dist/_chunks/{plugin-context---kTF5v8.js → plugin-context-DEGLSJs3.js} +2 -1
  30. package/dist/_chunks/plugin-context-DEGLSJs3.js.map +1 -0
  31. package/dist/_chunks/{router-ref-CtmF-aPv.js → router-ref-DuYuV_0Q.js} +2 -2
  32. package/dist/_chunks/router-ref-DuYuV_0Q.js.map +1 -0
  33. package/dist/_chunks/rsc-cache-key-DD0fl_-s.js +243 -0
  34. package/dist/_chunks/rsc-cache-key-DD0fl_-s.js.map +1 -0
  35. package/dist/_chunks/rsc-error-envelope-tT5PJs4q.js +40 -0
  36. package/dist/_chunks/rsc-error-envelope-tT5PJs4q.js.map +1 -0
  37. package/dist/_chunks/rsc-payload-path-B_LBodc2.js +48 -0
  38. package/dist/_chunks/rsc-payload-path-B_LBodc2.js.map +1 -0
  39. package/dist/_chunks/{segment-classify-Byy425ng.js → segment-classify-C539Pa2O.js} +23 -2
  40. package/dist/_chunks/{segment-classify-Byy425ng.js.map → segment-classify-C539Pa2O.js.map} +1 -1
  41. package/dist/_chunks/{canonicalize-DQHyFClh.js → segment-keys-BawYuNFO.js} +61 -2
  42. package/dist/_chunks/segment-keys-BawYuNFO.js.map +1 -0
  43. package/dist/_chunks/slot-params-BCTmZkQB.js +76 -0
  44. package/dist/_chunks/slot-params-BCTmZkQB.js.map +1 -0
  45. package/dist/_chunks/{ssr-data-BOWsq18U.js → ssr-data-14MXm7Pj.js} +17 -2
  46. package/dist/_chunks/ssr-data-14MXm7Pj.js.map +1 -0
  47. package/dist/_chunks/use-segment-params-ClyUNq4d.js +128 -0
  48. package/dist/_chunks/use-segment-params-ClyUNq4d.js.map +1 -0
  49. package/dist/_chunks/{walkers-_6zKFlch.js → walkers-BhhwI9TD.js} +21 -87
  50. package/dist/_chunks/walkers-BhhwI9TD.js.map +1 -0
  51. package/dist/adapters/build-output-helper.d.ts +37 -0
  52. package/dist/adapters/build-output-helper.d.ts.map +1 -1
  53. package/dist/adapters/cloudflare-dev.js +1 -1
  54. package/dist/adapters/cloudflare-kv-cache.js +1 -1
  55. package/dist/adapters/cloudflare.d.ts.map +1 -1
  56. package/dist/adapters/cloudflare.js +1 -1
  57. package/dist/adapters/fs-identity.d.ts +64 -0
  58. package/dist/adapters/fs-identity.d.ts.map +1 -0
  59. package/dist/adapters/nitro.d.ts.map +1 -1
  60. package/dist/adapters/nitro.js +2 -3
  61. package/dist/adapters/nitro.js.map +1 -1
  62. package/dist/adapters/shared.d.ts +57 -1
  63. package/dist/adapters/shared.d.ts.map +1 -1
  64. package/dist/adapters/types.d.ts +13 -1
  65. package/dist/adapters/types.d.ts.map +1 -1
  66. package/dist/cache/fast-hash.d.ts +5 -0
  67. package/dist/cache/fast-hash.d.ts.map +1 -1
  68. package/dist/cache/index.js +1 -1
  69. package/dist/cli.js +2 -2
  70. package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -1
  71. package/dist/client/browser-entry/hydrate.d.ts +20 -9
  72. package/dist/client/browser-entry/hydrate.d.ts.map +1 -1
  73. package/dist/client/browser-entry/post-hydration.d.ts +4 -1
  74. package/dist/client/browser-entry/post-hydration.d.ts.map +1 -1
  75. package/dist/client/browser-entry/router-init.d.ts +3 -0
  76. package/dist/client/browser-entry/router-init.d.ts.map +1 -1
  77. package/dist/client/browser-entry/rsc-stream.d.ts +8 -0
  78. package/dist/client/browser-entry/rsc-stream.d.ts.map +1 -1
  79. package/dist/client/error-boundary.d.ts +1 -0
  80. package/dist/client/error-boundary.d.ts.map +1 -1
  81. package/dist/client/error-boundary.js +1 -162
  82. package/dist/client/history.d.ts +13 -6
  83. package/dist/client/history.d.ts.map +1 -1
  84. package/dist/client/index.js +18 -11
  85. package/dist/client/index.js.map +1 -1
  86. package/dist/client/internal.d.ts +4 -3
  87. package/dist/client/internal.d.ts.map +1 -1
  88. package/dist/client/internal.js +865 -306
  89. package/dist/client/internal.js.map +1 -1
  90. package/dist/client/link.d.ts.map +1 -1
  91. package/dist/client/navigation-api.d.ts +2 -2
  92. package/dist/client/navigation-commit.d.ts +71 -0
  93. package/dist/client/navigation-commit.d.ts.map +1 -0
  94. package/dist/client/navigation-context.d.ts +37 -20
  95. package/dist/client/navigation-context.d.ts.map +1 -1
  96. package/dist/client/navigation-root.d.ts +63 -23
  97. package/dist/client/navigation-root.d.ts.map +1 -1
  98. package/dist/client/params-context.d.ts +81 -0
  99. package/dist/client/params-context.d.ts.map +1 -0
  100. package/dist/client/router-effects.d.ts +129 -0
  101. package/dist/client/router-effects.d.ts.map +1 -0
  102. package/dist/client/router-lifecycle.d.ts +55 -0
  103. package/dist/client/router-lifecycle.d.ts.map +1 -0
  104. package/dist/client/router-pipeline.d.ts +84 -0
  105. package/dist/client/router-pipeline.d.ts.map +1 -0
  106. package/dist/client/router-ref.d.ts +1 -1
  107. package/dist/client/router-ref.d.ts.map +1 -1
  108. package/dist/client/router-skew.d.ts +21 -0
  109. package/dist/client/router-skew.d.ts.map +1 -0
  110. package/dist/client/router-types.d.ts +207 -0
  111. package/dist/client/router-types.d.ts.map +1 -0
  112. package/dist/client/router.d.ts +1 -182
  113. package/dist/client/router.d.ts.map +1 -1
  114. package/dist/client/rsc-fetch.d.ts +38 -25
  115. package/dist/client/rsc-fetch.d.ts.map +1 -1
  116. package/dist/client/segment-cache.d.ts +79 -34
  117. package/dist/client/segment-cache.d.ts.map +1 -1
  118. package/dist/client/ssr-data.d.ts +6 -0
  119. package/dist/client/ssr-data.d.ts.map +1 -1
  120. package/dist/client/stale-client.d.ts +69 -0
  121. package/dist/client/stale-client.d.ts.map +1 -0
  122. package/dist/client/state.d.ts +10 -1
  123. package/dist/client/state.d.ts.map +1 -1
  124. package/dist/client/top-loader.d.ts +2 -1
  125. package/dist/client/top-loader.d.ts.map +1 -1
  126. package/dist/client/unload-guard.d.ts +5 -0
  127. package/dist/client/unload-guard.d.ts.map +1 -1
  128. package/dist/client/use-cookie.d.ts.map +1 -1
  129. package/dist/client/use-router.d.ts +1 -1
  130. package/dist/client/use-segment-params.d.ts +18 -8
  131. package/dist/client/use-segment-params.d.ts.map +1 -1
  132. package/dist/cookies/index.js +3 -3
  133. package/dist/cookies/index.js.map +1 -1
  134. package/dist/index.d.ts.map +1 -1
  135. package/dist/index.js +906 -321
  136. package/dist/index.js.map +1 -1
  137. package/dist/plugin-context.d.ts +31 -0
  138. package/dist/plugin-context.d.ts.map +1 -1
  139. package/dist/plugins/adapter-build.d.ts.map +1 -1
  140. package/dist/plugins/build-manifest.d.ts +1 -1
  141. package/dist/plugins/build-manifest.d.ts.map +1 -1
  142. package/dist/plugins/entries.d.ts.map +1 -1
  143. package/dist/plugins/fonts.d.ts.map +1 -1
  144. package/dist/plugins/request-dep/analysis.d.ts +106 -0
  145. package/dist/plugins/request-dep/analysis.d.ts.map +1 -0
  146. package/dist/plugins/request-dep/index.d.ts +75 -0
  147. package/dist/plugins/request-dep/index.d.ts.map +1 -0
  148. package/dist/plugins/request-dep/origin.d.ts +61 -0
  149. package/dist/plugins/request-dep/origin.d.ts.map +1 -0
  150. package/dist/plugins/routing.d.ts +9 -0
  151. package/dist/plugins/routing.d.ts.map +1 -1
  152. package/dist/plugins/static-build.d.ts +136 -8
  153. package/dist/plugins/static-build.d.ts.map +1 -1
  154. package/dist/routing/codegen-types.d.ts +18 -0
  155. package/dist/routing/codegen-types.d.ts.map +1 -1
  156. package/dist/routing/codegen.d.ts.map +1 -1
  157. package/dist/routing/collision-probe.d.ts +104 -0
  158. package/dist/routing/collision-probe.d.ts.map +1 -0
  159. package/dist/routing/collision-spaces.d.ts +26 -0
  160. package/dist/routing/collision-spaces.d.ts.map +1 -0
  161. package/dist/routing/index.js +3 -3
  162. package/dist/routing/interception.d.ts +235 -6
  163. package/dist/routing/interception.d.ts.map +1 -1
  164. package/dist/routing/manifest-codegen.d.ts.map +1 -1
  165. package/dist/routing/scanner.d.ts.map +1 -1
  166. package/dist/routing/segment-classify.d.ts +33 -0
  167. package/dist/routing/segment-classify.d.ts.map +1 -1
  168. package/dist/routing/segment-keys.d.ts +95 -0
  169. package/dist/routing/segment-keys.d.ts.map +1 -0
  170. package/dist/routing/slot-placement.d.ts +48 -0
  171. package/dist/routing/slot-placement.d.ts.map +1 -0
  172. package/dist/routing/walkers.d.ts +6 -0
  173. package/dist/routing/walkers.d.ts.map +1 -1
  174. package/dist/search-params/define.d.ts +0 -6
  175. package/dist/search-params/define.d.ts.map +1 -1
  176. package/dist/search-params/index.js +176 -2
  177. package/dist/search-params/index.js.map +1 -1
  178. package/dist/segment-params/define.d.ts +0 -6
  179. package/dist/segment-params/define.d.ts.map +1 -1
  180. package/dist/segment-params/index.js +69 -1
  181. package/dist/segment-params/index.js.map +1 -0
  182. package/dist/server/actions.d.ts +6 -3
  183. package/dist/server/actions.d.ts.map +1 -1
  184. package/dist/server/als-registry.d.ts +2 -1
  185. package/dist/server/als-registry.d.ts.map +1 -1
  186. package/dist/server/build-manifest.d.ts +13 -1
  187. package/dist/server/build-manifest.d.ts.map +1 -1
  188. package/dist/server/chain-url-parts.d.ts +82 -0
  189. package/dist/server/chain-url-parts.d.ts.map +1 -0
  190. package/dist/server/children-interception.d.ts +49 -0
  191. package/dist/server/children-interception.d.ts.map +1 -0
  192. package/dist/server/default-status-page.d.ts +45 -0
  193. package/dist/server/default-status-page.d.ts.map +1 -0
  194. package/dist/server/deny-renderer.d.ts +14 -3
  195. package/dist/server/deny-renderer.d.ts.map +1 -1
  196. package/dist/server/head-response.d.ts +35 -0
  197. package/dist/server/head-response.d.ts.map +1 -0
  198. package/dist/server/index.js +2 -2
  199. package/dist/server/internal.js +393 -212
  200. package/dist/server/internal.js.map +1 -1
  201. package/dist/server/param-coercion.d.ts +10 -1
  202. package/dist/server/param-coercion.d.ts.map +1 -1
  203. package/dist/server/pipeline-helpers.d.ts +0 -18
  204. package/dist/server/pipeline-helpers.d.ts.map +1 -1
  205. package/dist/server/pipeline-interception.d.ts +59 -9
  206. package/dist/server/pipeline-interception.d.ts.map +1 -1
  207. package/dist/server/pipeline-outcome.d.ts.map +1 -1
  208. package/dist/server/pipeline-phases.d.ts.map +1 -1
  209. package/dist/server/pipeline.d.ts +11 -0
  210. package/dist/server/pipeline.d.ts.map +1 -1
  211. package/dist/server/publish-params.d.ts +33 -0
  212. package/dist/server/publish-params.d.ts.map +1 -0
  213. package/dist/server/request-context.d.ts +48 -0
  214. package/dist/server/request-context.d.ts.map +1 -1
  215. package/dist/server/route-element-builder.d.ts +32 -2
  216. package/dist/server/route-element-builder.d.ts.map +1 -1
  217. package/dist/server/route-handler.d.ts.map +1 -1
  218. package/dist/server/route-matcher.d.ts +13 -0
  219. package/dist/server/route-matcher.d.ts.map +1 -1
  220. package/dist/server/rsc-cache-key-guard.d.ts +78 -0
  221. package/dist/server/rsc-cache-key-guard.d.ts.map +1 -0
  222. package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
  223. package/dist/server/rsc-entry/error-renderer.d.ts +14 -2
  224. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  225. package/dist/server/rsc-entry/helpers.d.ts +2 -10
  226. package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
  227. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  228. package/dist/server/rsc-entry/render-route.d.ts.map +1 -1
  229. package/dist/server/rsc-entry/rsc-payload.d.ts +3 -2
  230. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  231. package/dist/server/rsc-entry/rsc-stream.d.ts +3 -2
  232. package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
  233. package/dist/server/rsc-entry/ssr-renderer.d.ts +2 -0
  234. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  235. package/dist/server/skippable-prefix.d.ts +23 -0
  236. package/dist/server/skippable-prefix.d.ts.map +1 -0
  237. package/dist/server/slot-interception.d.ts +80 -0
  238. package/dist/server/slot-interception.d.ts.map +1 -0
  239. package/dist/server/slot-resolver.d.ts +70 -8
  240. package/dist/server/slot-resolver.d.ts.map +1 -1
  241. package/dist/server/ssr-bridge-types.d.ts +6 -0
  242. package/dist/server/ssr-bridge-types.d.ts.map +1 -1
  243. package/dist/server/ssr-entry.d.ts.map +1 -1
  244. package/dist/server/ssr-wrappers.d.ts +24 -13
  245. package/dist/server/ssr-wrappers.d.ts.map +1 -1
  246. package/dist/server/state-tree-diff.d.ts +6 -27
  247. package/dist/server/state-tree-diff.d.ts.map +1 -1
  248. package/dist/server/static-generator.d.ts +6 -0
  249. package/dist/server/static-generator.d.ts.map +1 -1
  250. package/dist/server/static-not-found.d.ts +52 -0
  251. package/dist/server/static-not-found.d.ts.map +1 -0
  252. package/dist/shared/als-slots.d.ts +41 -0
  253. package/dist/shared/als-slots.d.ts.map +1 -0
  254. package/dist/shared/base-path.d.ts +56 -0
  255. package/dist/shared/base-path.d.ts.map +1 -0
  256. package/dist/shared/param-value.d.ts +80 -0
  257. package/dist/shared/param-value.d.ts.map +1 -0
  258. package/dist/shared/payload-root.d.ts +108 -0
  259. package/dist/shared/payload-root.d.ts.map +1 -0
  260. package/dist/shared/rsc-cache-key.d.ts +163 -0
  261. package/dist/shared/rsc-cache-key.d.ts.map +1 -0
  262. package/dist/shared/rsc-error-envelope.d.ts +25 -0
  263. package/dist/shared/rsc-error-envelope.d.ts.map +1 -0
  264. package/dist/shared/rsc-manifest.d.ts +28 -0
  265. package/dist/shared/rsc-manifest.d.ts.map +1 -0
  266. package/dist/shared/rsc-payload-path.d.ts +42 -0
  267. package/dist/shared/rsc-payload-path.d.ts.map +1 -0
  268. package/dist/shared/segment-info.d.ts +59 -0
  269. package/dist/shared/segment-info.d.ts.map +1 -0
  270. package/dist/shared/slot-params.d.ts +51 -0
  271. package/dist/shared/slot-params.d.ts.map +1 -0
  272. package/dist/shared/static-platform-files.d.ts +71 -0
  273. package/dist/shared/static-platform-files.d.ts.map +1 -0
  274. package/docs/api/31-api-client.mdx +4 -2
  275. package/docs/learn/02-pages-and-layouts.mdx +1 -1
  276. package/docs/learn/11-error-handling.mdx +2 -0
  277. package/docs/learn/12-client-navigation.mdx +2 -2
  278. package/docs/learn/14-deploying.mdx +23 -0
  279. package/docs/more/01-advanced-routing.mdx +172 -2
  280. package/docs/more/04-metadata-and-fonts.mdx +1 -1
  281. package/package.json +2 -2
  282. package/src/adapters/build-output-helper.ts +116 -3
  283. package/src/adapters/cloudflare.ts +86 -11
  284. package/src/adapters/fs-identity.ts +156 -0
  285. package/src/adapters/nitro.ts +6 -6
  286. package/src/adapters/shared.ts +196 -21
  287. package/src/adapters/types.ts +13 -1
  288. package/src/cache/fast-hash.ts +5 -0
  289. package/src/client/browser-entry/action-dispatch.ts +9 -4
  290. package/src/client/browser-entry/hydrate.ts +40 -29
  291. package/src/client/browser-entry/index.ts +15 -1
  292. package/src/client/browser-entry/post-hydration.ts +10 -9
  293. package/src/client/browser-entry/router-init.ts +104 -48
  294. package/src/client/browser-entry/rsc-stream.ts +11 -2
  295. package/src/client/error-boundary.tsx +20 -15
  296. package/src/client/history.ts +13 -6
  297. package/src/client/internal.ts +4 -3
  298. package/src/client/link.tsx +55 -8
  299. package/src/client/navigation-api.ts +3 -3
  300. package/src/client/navigation-commit.ts +174 -0
  301. package/src/client/navigation-context.ts +40 -67
  302. package/src/client/navigation-root.tsx +326 -101
  303. package/src/client/params-context.ts +192 -0
  304. package/src/client/router-effects.ts +231 -0
  305. package/src/client/router-lifecycle.ts +288 -0
  306. package/src/client/router-pipeline.ts +389 -0
  307. package/src/client/router-ref.ts +1 -1
  308. package/src/client/router-skew.ts +30 -0
  309. package/src/client/router-types.ts +230 -0
  310. package/src/client/router.ts +242 -707
  311. package/src/client/rsc-fetch.ts +169 -102
  312. package/src/client/segment-cache.ts +121 -44
  313. package/src/client/ssr-data.ts +6 -0
  314. package/src/client/stale-client.ts +191 -0
  315. package/src/client/state.ts +14 -1
  316. package/src/client/top-loader.tsx +2 -1
  317. package/src/client/unload-guard.ts +34 -2
  318. package/src/client/use-cookie.ts +9 -2
  319. package/src/client/use-router.ts +1 -1
  320. package/src/client/use-segment-params.ts +41 -18
  321. package/src/index.ts +5 -1
  322. package/src/plugin-context.ts +32 -0
  323. package/src/plugins/adapter-build.ts +4 -0
  324. package/src/plugins/build-manifest.ts +34 -13
  325. package/src/plugins/entries.ts +4 -0
  326. package/src/plugins/fonts.ts +11 -8
  327. package/src/plugins/request-dep/analysis.ts +447 -0
  328. package/src/plugins/request-dep/index.ts +376 -0
  329. package/src/plugins/request-dep/origin.ts +310 -0
  330. package/src/plugins/routing.ts +59 -2
  331. package/src/plugins/static-build.ts +315 -73
  332. package/src/routing/codegen-types.ts +18 -0
  333. package/src/routing/codegen.ts +50 -10
  334. package/src/routing/collision-probe.ts +438 -0
  335. package/src/routing/collision-spaces.ts +281 -0
  336. package/src/routing/interception.ts +896 -50
  337. package/src/routing/manifest-codegen.ts +5 -3
  338. package/src/routing/scanner.ts +114 -89
  339. package/src/routing/segment-classify.ts +57 -0
  340. package/src/routing/segment-keys.ts +146 -0
  341. package/src/routing/slot-placement.ts +97 -0
  342. package/src/routing/walkers.ts +8 -0
  343. package/src/search-params/define.ts +6 -29
  344. package/src/segment-params/define.ts +4 -27
  345. package/src/server/action-handler.ts +3 -1
  346. package/src/server/actions.ts +6 -3
  347. package/src/server/als-registry.ts +2 -1
  348. package/src/server/build-manifest.ts +14 -1
  349. package/src/server/chain-url-parts.ts +163 -0
  350. package/src/server/children-interception.ts +115 -0
  351. package/src/server/default-status-page.ts +127 -0
  352. package/src/server/deny-renderer.ts +81 -20
  353. package/src/server/head-response.ts +54 -0
  354. package/src/server/param-coercion.ts +48 -18
  355. package/src/server/pipeline-helpers.ts +0 -45
  356. package/src/server/pipeline-interception.ts +81 -32
  357. package/src/server/pipeline-outcome.ts +2 -4
  358. package/src/server/pipeline-phases.ts +68 -16
  359. package/src/server/pipeline.ts +57 -10
  360. package/src/server/prebuilt-runtime.ts +4 -4
  361. package/src/server/publish-params.ts +42 -0
  362. package/src/server/request-context.ts +97 -18
  363. package/src/server/route-element-builder.ts +89 -98
  364. package/src/server/route-handler.ts +8 -8
  365. package/src/server/route-matcher.ts +21 -9
  366. package/src/server/rsc-cache-key-guard.ts +170 -0
  367. package/src/server/rsc-entry/api-handler.ts +6 -8
  368. package/src/server/rsc-entry/error-renderer.ts +64 -25
  369. package/src/server/rsc-entry/helpers.ts +31 -16
  370. package/src/server/rsc-entry/index.ts +36 -28
  371. package/src/server/rsc-entry/render-route.ts +9 -4
  372. package/src/server/rsc-entry/revalidate-renderer.ts +1 -1
  373. package/src/server/rsc-entry/rsc-payload.ts +14 -25
  374. package/src/server/rsc-entry/rsc-stream.ts +4 -3
  375. package/src/server/rsc-entry/ssr-renderer.ts +13 -9
  376. package/src/server/skippable-prefix.ts +92 -0
  377. package/src/server/slot-interception.ts +168 -0
  378. package/src/server/slot-resolver.ts +253 -156
  379. package/src/server/ssr-bridge-types.ts +6 -0
  380. package/src/server/ssr-entry.ts +12 -4
  381. package/src/server/ssr-wrappers.tsx +33 -32
  382. package/src/server/state-tree-diff.ts +14 -55
  383. package/src/server/static-generator.ts +65 -27
  384. package/src/server/static-not-found.ts +134 -0
  385. package/src/shared/als-slots.ts +72 -0
  386. package/src/shared/base-path.ts +80 -0
  387. package/src/shared/param-value.ts +244 -0
  388. package/src/shared/payload-root.ts +151 -0
  389. package/src/shared/rsc-cache-key.ts +269 -0
  390. package/src/shared/rsc-error-envelope.ts +31 -0
  391. package/src/shared/rsc-manifest.ts +29 -0
  392. package/src/shared/rsc-payload-path.ts +45 -0
  393. package/src/shared/segment-info.ts +60 -0
  394. package/src/shared/slot-params.ts +111 -0
  395. package/src/shared/static-platform-files.ts +75 -0
  396. package/dist/_chunks/build-output-helper-DOGYFb_X.js +0 -196
  397. package/dist/_chunks/build-output-helper-DOGYFb_X.js.map +0 -1
  398. package/dist/_chunks/canonicalize-DQHyFClh.js.map +0 -1
  399. package/dist/_chunks/cli-schema-sync-BTWEKJXo.js +0 -668
  400. package/dist/_chunks/cli-schema-sync-BTWEKJXo.js.map +0 -1
  401. package/dist/_chunks/define-COtkxMRT.js +0 -191
  402. package/dist/_chunks/define-COtkxMRT.js.map +0 -1
  403. package/dist/_chunks/define-c4au4I9R.js +0 -82
  404. package/dist/_chunks/define-c4au4I9R.js.map +0 -1
  405. package/dist/_chunks/fast-hash-D6hIVt1Y.js.map +0 -1
  406. package/dist/_chunks/logger-AWfuX-KJ.js.map +0 -1
  407. package/dist/_chunks/navigation-root-bUDZLw74.js +0 -124
  408. package/dist/_chunks/navigation-root-bUDZLw74.js.map +0 -1
  409. package/dist/_chunks/plugin-context---kTF5v8.js.map +0 -1
  410. package/dist/_chunks/router-ref-CtmF-aPv.js.map +0 -1
  411. package/dist/_chunks/ssr-data-BOWsq18U.js.map +0 -1
  412. package/dist/_chunks/use-segment-params-D1CzlgBo.js +0 -151
  413. package/dist/_chunks/use-segment-params-D1CzlgBo.js.map +0 -1
  414. package/dist/_chunks/walkers-_6zKFlch.js.map +0 -1
  415. package/dist/client/error-boundary.js.map +0 -1
  416. package/dist/plugins/request-dep.d.ts +0 -32
  417. package/dist/plugins/request-dep.d.ts.map +0 -1
  418. 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"}
@@ -1,4 +1,4 @@
1
- import { i as INTERCEPTION_MARKERS, n as classifyUrlSegment, r as DEFAULT_PAGE_EXTENSIONS, t as classifySegment } from "../_chunks/segment-classify-Byy425ng.js";
2
- import { i as scanRoutes } from "../_chunks/cli-schema-sync-BTWEKJXo.js";
3
- import { a as generateRouteMap, i as validateSchemaAgainstRoutes, n as collectInterceptionRewrites, r as collectDynamicSegmentsFromTree, t as collectLeafRoutes } from "../_chunks/walkers-_6zKFlch.js";
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
- /** A conditional rewrite rule generated from an intercepting route. */
21
- export interface InterceptionRewrite {
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 URL prefix that the client must be navigating FROM for this rewrite
29
- * to apply. Matched against the X-Timber-URL header.
30
- * E.g., "/feed" for a (.)photo/[id] inside /feed/@modal/.
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,EAAsB,MAAM,YAAY,CAAC;AAElE,uEAAuE;AACvE,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,kBAAkB,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,WAAW,GAAG,mBAAmB,EAAE,CAIpF"}
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,CA+IhF;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
+ {"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;AAwBpB;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,GAAE,aAAkB,GAAG,SAAS,CA4ChF"}
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>[];