@timber-js/app 0.2.0-alpha.184 → 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 (441) 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-C539Pa2O.js.map +1 -0
  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-BtTlKviE.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 +872 -305
  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 +39 -16
  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 +915 -320
  136. package/dist/index.js.map +1 -1
  137. package/dist/plugin-context.d.ts +33 -1
  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 +149 -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/types.d.ts +1 -3
  173. package/dist/routing/types.d.ts.map +1 -1
  174. package/dist/routing/walkers.d.ts +6 -0
  175. package/dist/routing/walkers.d.ts.map +1 -1
  176. package/dist/search-params/define.d.ts +0 -6
  177. package/dist/search-params/define.d.ts.map +1 -1
  178. package/dist/search-params/index.js +176 -2
  179. package/dist/search-params/index.js.map +1 -1
  180. package/dist/segment-params/define.d.ts +0 -6
  181. package/dist/segment-params/define.d.ts.map +1 -1
  182. package/dist/segment-params/index.js +69 -1
  183. package/dist/segment-params/index.js.map +1 -0
  184. package/dist/server/actions.d.ts +6 -3
  185. package/dist/server/actions.d.ts.map +1 -1
  186. package/dist/server/als-registry.d.ts +2 -1
  187. package/dist/server/als-registry.d.ts.map +1 -1
  188. package/dist/server/build-manifest.d.ts +13 -1
  189. package/dist/server/build-manifest.d.ts.map +1 -1
  190. package/dist/server/chain-url-parts.d.ts +82 -0
  191. package/dist/server/chain-url-parts.d.ts.map +1 -0
  192. package/dist/server/children-interception.d.ts +49 -0
  193. package/dist/server/children-interception.d.ts.map +1 -0
  194. package/dist/server/default-status-page.d.ts +45 -0
  195. package/dist/server/default-status-page.d.ts.map +1 -0
  196. package/dist/server/deny-boundary.d.ts +4 -7
  197. package/dist/server/deny-boundary.d.ts.map +1 -1
  198. package/dist/server/deny-renderer.d.ts +14 -3
  199. package/dist/server/deny-renderer.d.ts.map +1 -1
  200. package/dist/server/head-response.d.ts +35 -0
  201. package/dist/server/head-response.d.ts.map +1 -0
  202. package/dist/server/index.js +2 -2
  203. package/dist/server/internal.js +528 -373
  204. package/dist/server/internal.js.map +1 -1
  205. package/dist/server/param-coercion.d.ts +10 -1
  206. package/dist/server/param-coercion.d.ts.map +1 -1
  207. package/dist/server/pipeline-helpers.d.ts +0 -18
  208. package/dist/server/pipeline-helpers.d.ts.map +1 -1
  209. package/dist/server/pipeline-interception.d.ts +59 -9
  210. package/dist/server/pipeline-interception.d.ts.map +1 -1
  211. package/dist/server/pipeline-outcome.d.ts.map +1 -1
  212. package/dist/server/pipeline-phases.d.ts.map +1 -1
  213. package/dist/server/pipeline.d.ts +11 -0
  214. package/dist/server/pipeline.d.ts.map +1 -1
  215. package/dist/server/prebuilt-builder.d.ts.map +1 -1
  216. package/dist/server/primitives.d.ts +0 -12
  217. package/dist/server/primitives.d.ts.map +1 -1
  218. package/dist/server/publish-params.d.ts +33 -0
  219. package/dist/server/publish-params.d.ts.map +1 -0
  220. package/dist/server/request-context.d.ts +48 -0
  221. package/dist/server/request-context.d.ts.map +1 -1
  222. package/dist/server/route-element-builder.d.ts +32 -2
  223. package/dist/server/route-element-builder.d.ts.map +1 -1
  224. package/dist/server/route-handler.d.ts.map +1 -1
  225. package/dist/server/route-matcher.d.ts +13 -0
  226. package/dist/server/route-matcher.d.ts.map +1 -1
  227. package/dist/server/rsc-cache-key-guard.d.ts +78 -0
  228. package/dist/server/rsc-cache-key-guard.d.ts.map +1 -0
  229. package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
  230. package/dist/server/rsc-entry/error-renderer.d.ts +14 -2
  231. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  232. package/dist/server/rsc-entry/helpers.d.ts +2 -10
  233. package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
  234. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  235. package/dist/server/rsc-entry/render-route.d.ts.map +1 -1
  236. package/dist/server/rsc-entry/rsc-payload.d.ts +3 -2
  237. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  238. package/dist/server/rsc-entry/rsc-stream.d.ts +3 -2
  239. package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
  240. package/dist/server/rsc-entry/ssr-renderer.d.ts +2 -0
  241. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  242. package/dist/server/sitemap-generator.d.ts.map +1 -1
  243. package/dist/server/skippable-prefix.d.ts +23 -0
  244. package/dist/server/skippable-prefix.d.ts.map +1 -0
  245. package/dist/server/slot-interception.d.ts +80 -0
  246. package/dist/server/slot-interception.d.ts.map +1 -0
  247. package/dist/server/slot-resolver.d.ts +70 -8
  248. package/dist/server/slot-resolver.d.ts.map +1 -1
  249. package/dist/server/ssr-bridge-types.d.ts +6 -0
  250. package/dist/server/ssr-bridge-types.d.ts.map +1 -1
  251. package/dist/server/ssr-entry.d.ts.map +1 -1
  252. package/dist/server/ssr-wrappers.d.ts +24 -13
  253. package/dist/server/ssr-wrappers.d.ts.map +1 -1
  254. package/dist/server/state-tree-diff.d.ts +6 -27
  255. package/dist/server/state-tree-diff.d.ts.map +1 -1
  256. package/dist/server/static-generator.d.ts +6 -0
  257. package/dist/server/static-generator.d.ts.map +1 -1
  258. package/dist/server/static-not-found.d.ts +52 -0
  259. package/dist/server/static-not-found.d.ts.map +1 -0
  260. package/dist/server/status-code-resolver.d.ts +3 -10
  261. package/dist/server/status-code-resolver.d.ts.map +1 -1
  262. package/dist/shared/als-slots.d.ts +41 -0
  263. package/dist/shared/als-slots.d.ts.map +1 -0
  264. package/dist/shared/base-path.d.ts +56 -0
  265. package/dist/shared/base-path.d.ts.map +1 -0
  266. package/dist/shared/param-value.d.ts +80 -0
  267. package/dist/shared/param-value.d.ts.map +1 -0
  268. package/dist/shared/payload-root.d.ts +108 -0
  269. package/dist/shared/payload-root.d.ts.map +1 -0
  270. package/dist/shared/rsc-cache-key.d.ts +163 -0
  271. package/dist/shared/rsc-cache-key.d.ts.map +1 -0
  272. package/dist/shared/rsc-error-envelope.d.ts +25 -0
  273. package/dist/shared/rsc-error-envelope.d.ts.map +1 -0
  274. package/dist/shared/rsc-manifest.d.ts +28 -0
  275. package/dist/shared/rsc-manifest.d.ts.map +1 -0
  276. package/dist/shared/rsc-payload-path.d.ts +42 -0
  277. package/dist/shared/rsc-payload-path.d.ts.map +1 -0
  278. package/dist/shared/segment-info.d.ts +59 -0
  279. package/dist/shared/segment-info.d.ts.map +1 -0
  280. package/dist/shared/slot-params.d.ts +51 -0
  281. package/dist/shared/slot-params.d.ts.map +1 -0
  282. package/dist/shared/static-platform-files.d.ts +71 -0
  283. package/dist/shared/static-platform-files.d.ts.map +1 -0
  284. package/dist/shims/navigation-client.d.ts +8 -19
  285. package/dist/shims/navigation-client.d.ts.map +1 -1
  286. package/dist/shims/navigation.d.ts +0 -1
  287. package/dist/shims/navigation.d.ts.map +1 -1
  288. package/docs/api/31-api-client.mdx +4 -2
  289. package/docs/learn/02-pages-and-layouts.mdx +1 -1
  290. package/docs/learn/11-error-handling.mdx +4 -3
  291. package/docs/learn/12-client-navigation.mdx +2 -2
  292. package/docs/learn/14-deploying.mdx +23 -0
  293. package/docs/more/01-advanced-routing.mdx +172 -2
  294. package/docs/more/04-metadata-and-fonts.mdx +1 -1
  295. package/package.json +2 -2
  296. package/src/adapters/build-output-helper.ts +116 -3
  297. package/src/adapters/cloudflare.ts +86 -11
  298. package/src/adapters/fs-identity.ts +156 -0
  299. package/src/adapters/nitro.ts +6 -6
  300. package/src/adapters/shared.ts +196 -21
  301. package/src/adapters/types.ts +13 -1
  302. package/src/cache/fast-hash.ts +5 -0
  303. package/src/client/browser-entry/action-dispatch.ts +9 -4
  304. package/src/client/browser-entry/hydrate.ts +40 -29
  305. package/src/client/browser-entry/index.ts +15 -1
  306. package/src/client/browser-entry/post-hydration.ts +10 -9
  307. package/src/client/browser-entry/router-init.ts +104 -48
  308. package/src/client/browser-entry/rsc-stream.ts +11 -2
  309. package/src/client/error-boundary.tsx +20 -15
  310. package/src/client/history.ts +13 -6
  311. package/src/client/internal.ts +4 -3
  312. package/src/client/link.tsx +55 -8
  313. package/src/client/navigation-api.ts +3 -3
  314. package/src/client/navigation-commit.ts +174 -0
  315. package/src/client/navigation-context.ts +40 -67
  316. package/src/client/navigation-root.tsx +326 -101
  317. package/src/client/params-context.ts +192 -0
  318. package/src/client/router-effects.ts +231 -0
  319. package/src/client/router-lifecycle.ts +288 -0
  320. package/src/client/router-pipeline.ts +389 -0
  321. package/src/client/router-ref.ts +1 -1
  322. package/src/client/router-skew.ts +30 -0
  323. package/src/client/router-types.ts +230 -0
  324. package/src/client/router.ts +242 -690
  325. package/src/client/rsc-fetch.ts +180 -122
  326. package/src/client/segment-cache.ts +121 -44
  327. package/src/client/ssr-data.ts +6 -0
  328. package/src/client/stale-client.ts +191 -0
  329. package/src/client/state.ts +14 -1
  330. package/src/client/top-loader.tsx +2 -1
  331. package/src/client/unload-guard.ts +34 -2
  332. package/src/client/use-cookie.ts +9 -2
  333. package/src/client/use-router.ts +1 -1
  334. package/src/client/use-segment-params.ts +41 -18
  335. package/src/index.ts +5 -1
  336. package/src/plugin-context.ts +34 -1
  337. package/src/plugins/adapter-build.ts +4 -0
  338. package/src/plugins/build-manifest.ts +34 -13
  339. package/src/plugins/entries.ts +4 -0
  340. package/src/plugins/fonts.ts +11 -8
  341. package/src/plugins/request-dep/analysis.ts +447 -0
  342. package/src/plugins/request-dep/index.ts +376 -0
  343. package/src/plugins/request-dep/origin.ts +310 -0
  344. package/src/plugins/routing.ts +60 -3
  345. package/src/plugins/static-build.ts +333 -63
  346. package/src/routing/codegen-types.ts +18 -0
  347. package/src/routing/codegen.ts +50 -10
  348. package/src/routing/collision-probe.ts +438 -0
  349. package/src/routing/collision-spaces.ts +281 -0
  350. package/src/routing/interception.ts +896 -50
  351. package/src/routing/manifest-codegen.ts +6 -9
  352. package/src/routing/scanner.ts +114 -113
  353. package/src/routing/segment-classify.ts +57 -0
  354. package/src/routing/segment-keys.ts +146 -0
  355. package/src/routing/slot-placement.ts +97 -0
  356. package/src/routing/types.ts +1 -3
  357. package/src/routing/walkers.ts +8 -0
  358. package/src/search-params/define.ts +6 -29
  359. package/src/segment-params/define.ts +4 -27
  360. package/src/server/action-handler.ts +3 -1
  361. package/src/server/actions.ts +6 -3
  362. package/src/server/als-registry.ts +2 -1
  363. package/src/server/build-manifest.ts +14 -1
  364. package/src/server/chain-url-parts.ts +163 -0
  365. package/src/server/children-interception.ts +115 -0
  366. package/src/server/default-status-page.ts +127 -0
  367. package/src/server/deny-boundary.ts +5 -31
  368. package/src/server/deny-renderer.ts +83 -22
  369. package/src/server/head-response.ts +54 -0
  370. package/src/server/param-coercion.ts +48 -18
  371. package/src/server/pipeline-helpers.ts +0 -45
  372. package/src/server/pipeline-interception.ts +81 -32
  373. package/src/server/pipeline-outcome.ts +3 -5
  374. package/src/server/pipeline-phases.ts +68 -16
  375. package/src/server/pipeline.ts +57 -10
  376. package/src/server/prebuilt-builder.ts +1 -7
  377. package/src/server/prebuilt-runtime.ts +4 -4
  378. package/src/server/primitives.ts +0 -18
  379. package/src/server/publish-params.ts +42 -0
  380. package/src/server/request-context.ts +97 -18
  381. package/src/server/route-element-builder.ts +89 -98
  382. package/src/server/route-handler.ts +8 -8
  383. package/src/server/route-matcher.ts +21 -9
  384. package/src/server/rsc-cache-key-guard.ts +170 -0
  385. package/src/server/rsc-entry/api-handler.ts +6 -8
  386. package/src/server/rsc-entry/error-renderer.ts +64 -25
  387. package/src/server/rsc-entry/helpers.ts +31 -16
  388. package/src/server/rsc-entry/index.ts +36 -28
  389. package/src/server/rsc-entry/render-route.ts +12 -7
  390. package/src/server/rsc-entry/revalidate-renderer.ts +1 -1
  391. package/src/server/rsc-entry/rsc-payload.ts +14 -25
  392. package/src/server/rsc-entry/rsc-stream.ts +4 -3
  393. package/src/server/rsc-entry/ssr-renderer.ts +13 -9
  394. package/src/server/sitemap-generator.ts +1 -7
  395. package/src/server/skippable-prefix.ts +92 -0
  396. package/src/server/slot-interception.ts +168 -0
  397. package/src/server/slot-resolver.ts +253 -156
  398. package/src/server/ssr-bridge-types.ts +6 -0
  399. package/src/server/ssr-entry.ts +12 -4
  400. package/src/server/ssr-wrappers.tsx +33 -32
  401. package/src/server/state-tree-diff.ts +14 -55
  402. package/src/server/static-generator.ts +67 -45
  403. package/src/server/static-not-found.ts +134 -0
  404. package/src/server/status-code-resolver.ts +4 -47
  405. package/src/shared/als-slots.ts +72 -0
  406. package/src/shared/base-path.ts +80 -0
  407. package/src/shared/param-value.ts +244 -0
  408. package/src/shared/payload-root.ts +151 -0
  409. package/src/shared/rsc-cache-key.ts +269 -0
  410. package/src/shared/rsc-error-envelope.ts +31 -0
  411. package/src/shared/rsc-manifest.ts +29 -0
  412. package/src/shared/rsc-payload-path.ts +45 -0
  413. package/src/shared/segment-info.ts +60 -0
  414. package/src/shared/slot-params.ts +111 -0
  415. package/src/shared/static-platform-files.ts +75 -0
  416. package/src/shims/navigation-client.ts +8 -26
  417. package/src/shims/navigation.ts +0 -4
  418. package/dist/_chunks/build-output-helper-DOGYFb_X.js +0 -196
  419. package/dist/_chunks/build-output-helper-DOGYFb_X.js.map +0 -1
  420. package/dist/_chunks/canonicalize-DQHyFClh.js.map +0 -1
  421. package/dist/_chunks/cli-schema-sync-D3naS3eH.js +0 -688
  422. package/dist/_chunks/cli-schema-sync-D3naS3eH.js.map +0 -1
  423. package/dist/_chunks/define-COtkxMRT.js +0 -191
  424. package/dist/_chunks/define-COtkxMRT.js.map +0 -1
  425. package/dist/_chunks/define-c4au4I9R.js +0 -82
  426. package/dist/_chunks/define-c4au4I9R.js.map +0 -1
  427. package/dist/_chunks/fast-hash-D6hIVt1Y.js.map +0 -1
  428. package/dist/_chunks/logger-AWfuX-KJ.js.map +0 -1
  429. package/dist/_chunks/navigation-root-bUDZLw74.js +0 -124
  430. package/dist/_chunks/navigation-root-bUDZLw74.js.map +0 -1
  431. package/dist/_chunks/plugin-context---kTF5v8.js.map +0 -1
  432. package/dist/_chunks/router-ref-CtmF-aPv.js.map +0 -1
  433. package/dist/_chunks/segment-classify-Byy425ng.js.map +0 -1
  434. package/dist/_chunks/ssr-data-BOWsq18U.js.map +0 -1
  435. package/dist/_chunks/use-segment-params-D1CzlgBo.js +0 -151
  436. package/dist/_chunks/use-segment-params-D1CzlgBo.js.map +0 -1
  437. package/dist/_chunks/walkers-BtTlKviE.js.map +0 -1
  438. package/dist/client/error-boundary.js.map +0 -1
  439. package/dist/plugins/request-dep.d.ts +0 -32
  440. package/dist/plugins/request-dep.d.ts.map +0 -1
  441. package/src/plugins/request-dep.ts +0 -499
@@ -18,11 +18,11 @@
18
18
  * (populated by ssr-entry.ts) to ensure correct per-request isolation
19
19
  * across concurrent requests with streaming Suspense.
20
20
  *
21
- * Reactivity: On the client, useParams() reads from NavigationContext
22
- * which is updated atomically with the RSC tree render. This replaces
23
- * the previous useSyncExternalStore approach that suffered from a
24
- * timing gap between tree render and store notification — causing
25
- * preserved layout components to briefly show stale active state.
21
+ * Reactivity: On the client, useParams() reads from ParamsContext, published
22
+ * by the one provider the client renders above the merge point
23
+ * (`PayloadRoot`). Params update atomically with the tree because they travel
24
+ * on the same payload root — there is no separate channel that could be
25
+ * seeded a render early or late (TIM-1294, TIM-1297).
26
26
  *
27
27
  * All mutable state is delegated to client/state.ts for singleton guarantees.
28
28
  * See design/18-build-system.md §"Singleton State Registry"
@@ -32,8 +32,15 @@
32
32
 
33
33
  import type { Routes } from '../index.js';
34
34
  import { getSsrData } from './ssr-data.js';
35
- import { currentParams, _setCurrentParams, paramsListeners } from './state.js';
36
- import { useNavigationContext } from './navigation-context.js';
35
+ import {
36
+ currentParams,
37
+ currentSlotParams,
38
+ _setCurrentParams,
39
+ _setCurrentSlotParams,
40
+ paramsListeners,
41
+ } from './state.js';
42
+ import { resolveSegmentParams, type SlotParamsRecord } from '../shared/slot-params.js';
43
+ import { useParamsContext } from './params-context.js';
37
44
 
38
45
  // ---------------------------------------------------------------------------
39
46
  // Module-level subscribe/notify pattern — kept for backward compat and tests
@@ -81,6 +88,18 @@ export function setCurrentParams(params: Record<string, string | string[]>): voi
81
88
  _setCurrentParams(params);
82
89
  }
83
90
 
91
+ /**
92
+ * Set the per-slot params snapshot in the module-level store.
93
+ *
94
+ * Paired with `setCurrentParams`: the router calls both on every navigation,
95
+ * including with `null` when a response carries no slot params, so a slot's
96
+ * params from the *previous* route cannot be read on the next one. Fill and
97
+ * serve are paired; so are fill and clear. See TIM-1285.
98
+ */
99
+ export function setCurrentSlotParams(slotParams: SlotParamsRecord | null): void {
100
+ _setCurrentSlotParams(slotParams);
101
+ }
102
+
84
103
  /**
85
104
  * Notify all legacy subscribers that params have changed.
86
105
  *
@@ -105,9 +124,9 @@ export function notifyParamsListeners(): void {
105
124
  * The optional `_route` argument exists only for TypeScript narrowing —
106
125
  * it does not affect the runtime return value.
107
126
  *
108
- * On the client, reads from NavigationContext (provided by
109
- * NavigationProvider in renderRoot). This ensures params update
110
- * atomically with the RSC tree — no timing gap.
127
+ * On the client, reads from ParamsContext, published by `PayloadRoot` above
128
+ * everything the navigation renders. Params update atomically with the RSC
129
+ * tree — no timing gap.
111
130
  *
112
131
  * During SSR, reads from the ALS-backed SSR data context to ensure
113
132
  * per-request isolation across concurrent requests with streaming Suspense.
@@ -123,15 +142,17 @@ export function useSegmentParams<R extends keyof Routes>(
123
142
  segmentPath: R
124
143
  ): Routes[R] extends { segmentParams: infer P } ? P : Record<string, string | string[]>;
125
144
  export function useSegmentParams(segmentPath?: string): Record<string, string | string[]>;
126
- export function useSegmentParams(_segmentPath?: string): Record<string, string | string[]> {
127
- // Try reading from NavigationContext (client-side, inside React tree).
128
- // During SSR, no NavigationProvider is mounted, so this returns null.
129
- // When called outside a React component, useContext throws — caught below.
145
+ export function useSegmentParams(segmentPath?: string): Record<string, string | string[]> {
146
+ // Try the client-owned provider first. It sits above everything a navigation
147
+ // renders, so any component on the page — initial document, full navigation,
148
+ // or a layout the server skipped — has one above it. Absent during SSR,
149
+ // where the ALS path below is the answer. When called outside a React
150
+ // component, useContext throws — caught below.
130
151
  try {
131
152
  // eslint-disable-next-line react-hooks/rules-of-hooks -- conditional on environment, not render path
132
- const navContext = useNavigationContext();
133
- if (navContext !== null) {
134
- return navContext.params;
153
+ const paramsContext = useParamsContext();
154
+ if (paramsContext !== null) {
155
+ return resolveSegmentParams(paramsContext.params, paramsContext.slotParams, segmentPath);
135
156
  }
136
157
  } catch {
137
158
  // No React dispatcher available (called outside a component).
@@ -140,5 +161,7 @@ export function useSegmentParams(_segmentPath?: string): Record<string, string |
140
161
 
141
162
  // SSR path: read from ALS-backed SSR data context.
142
163
  // Falls back to module-level currentParams for tests.
143
- return getSsrData()?.params ?? currentParams;
164
+ const ssrData = getSsrData();
165
+ if (ssrData) return resolveSegmentParams(ssrData.params, ssrData.slotParams, segmentPath);
166
+ return resolveSegmentParams(currentParams, currentSlotParams, segmentPath);
144
167
  }
package/src/index.ts CHANGED
@@ -31,7 +31,7 @@ import { timberChunks } from './plugins/chunks';
31
31
  import { clientChunkGroup } from './plugins/client-chunks';
32
32
  import { timberServerBundle } from './plugins/server-bundle';
33
33
  import { timberCacheTransform } from './plugins/cache';
34
- import { timberRequestDep } from './plugins/request-dep';
34
+ import { timberRequestDep } from './plugins/request-dep/index.js';
35
35
  import { timberPrebuilt } from './plugins/prebuilt';
36
36
  import { timberPrerenderSugar } from './plugins/prerender-sugar';
37
37
  import { timberCloudflareWasm } from './plugins/cloudflare-wasm';
@@ -464,6 +464,10 @@ export function timber(config?: TimberUserConfig): PluginOption[] {
464
464
  ctx.root = resolved.root;
465
465
  ctx.appDir = resolveAppDir(resolved.root, ctx.config.appDir);
466
466
  ctx.dev = resolved.command === 'serve';
467
+ // Vite's resolved base — the deployment path prefix. Captured once
468
+ // here so every sub-plugin that emits a URL (assets, fonts, RSC
469
+ // payloads) reads the same value. See TIM-1261.
470
+ ctx.base = resolved.base;
467
471
 
468
472
  // Register all timber config file candidates as Vite config file
469
473
  // dependencies so Vite's built-in restart-on-change handles them
@@ -18,6 +18,7 @@ import type { CaptureSummary } from './server/prebuilt-builder';
18
18
  import type { StartupTimer } from './utils/startup-timer';
19
19
  import { createStartupTimer } from './utils/startup-timer';
20
20
  import type { TimberUserConfig, ClientJavascriptConfig } from './config-types.js';
21
+ import type { RscManifest } from './plugins/static-build.js';
21
22
  import type { HoldingServer } from './dev-tools/holding-server.js';
22
23
  import type { ProgramNode } from './plugins/callsite-ast.js';
23
24
 
@@ -72,6 +73,21 @@ export interface PluginContext {
72
73
  root: string;
73
74
  /** Whether the dev server is running (set by timber-root-sync in configResolved) */
74
75
  dev: boolean;
76
+ /**
77
+ * Vite's resolved `base` (set by timber-root-sync in configResolved).
78
+ * Always has a trailing slash; `'/'` unless the app is deployed under a
79
+ * sub-path. Every URL the framework emits — assets, fonts, RSC payloads —
80
+ * carries this prefix. This is the single copy: sub-plugins read it here
81
+ * rather than capturing `config.base` in their own configResolved.
82
+ *
83
+ * **Availability:** written by timber-root-sync, which has no `enforce`, so
84
+ * it is populated from `buildStart`/`load`/`generateBundle`/`configureServer`
85
+ * onward — but NOT during the `configResolved` of an `enforce: 'pre'`
86
+ * plugin, which Vite runs first. A pre plugin that needs the base inside
87
+ * its own `configResolved` must read `config.base` there (timber-fonts
88
+ * does). See TIM-1261.
89
+ */
90
+ base: string;
75
91
  /** CSS build manifest (populated by adapter after client build, null in dev) */
76
92
  buildManifest: BuildManifest | null;
77
93
  /** Per-build deployment ID for version skew detection (null in dev) */
@@ -97,6 +113,22 @@ export interface PluginContext {
97
113
  * populate per-route modulepreload entries from clientReferenceDeps.
98
114
  */
99
115
  routeClientRefKeys?: Map<string, Set<string>>;
116
+ /**
117
+ * Static request-dependency verdict per segment entry file, keyed by the
118
+ * absolute `filePath` the route scanner produced. Computed once by
119
+ * `timber-request-dep`'s RSC `buildEnd` and serialized into
120
+ * `buildManifest.requestDep` by `timber-build-manifest` (build only — dev
121
+ * answers the same question through the `Symbol.for('timber:request-dep')`
122
+ * bridge instead).
123
+ *
124
+ * `undefined` and `{}` are different states and the difference is the whole
125
+ * of TIM-1300: an empty object means the analysis ran and found no segments,
126
+ * `undefined` means it never ran, and the runtime cannot tell them apart —
127
+ * every key is absent either way, so every segment falls to the conservative
128
+ * `true` and nothing is ever skipped. The build fails loudly on `undefined`
129
+ * rather than shipping that silently.
130
+ */
131
+ requestDepMap?: Record<string, boolean>;
100
132
  /**
101
133
  * Maps absolute module IDs of client references in non-facade RSC
102
134
  * chunks to the absolute paths of their consuming facade modules.
@@ -171,7 +203,7 @@ export interface PluginContext {
171
203
  * Populated during static generation, consumed by adapters to set
172
204
  * immutable cache headers for `_rsc/` files. See TIM-1254.
173
205
  */
174
- rscManifest?: Record<string, string>;
206
+ rscManifest?: RscManifest;
175
207
  }
176
208
 
177
209
  // ── AST parse memo ───────────────────────────────────────────────────────
@@ -257,6 +289,7 @@ export function createPluginContext(config?: TimberUserConfig, root?: string): P
257
289
  appDir: join(projectRoot, 'app'),
258
290
  root: projectRoot,
259
291
  dev: false,
292
+ base: '/',
260
293
  buildManifest: null,
261
294
  deploymentId: null,
262
295
  timer: createStartupTimer(),
@@ -21,6 +21,7 @@ import type { PluginContext } from '../plugin-context.js';
21
21
  import type { TimberPlatformAdapter, TimberConfig } from '../adapters/types.js';
22
22
  import type { BuildManifest } from '../server/build-manifest.js';
23
23
  import { swallow } from '../server/logger.js';
24
+ import { normalizeBasePath } from '../shared/base-path.js';
24
25
 
25
26
  export function timberAdapterBuild(ctx: PluginContext): Plugin {
26
27
  return {
@@ -85,6 +86,9 @@ export function timberAdapterBuild(ctx: PluginContext): Plugin {
85
86
 
86
87
  const adapterConfig: TimberConfig = {
87
88
  root: ctx.root,
89
+ // Normalized once here, not in each adapter: the platform files
90
+ // adapters write address deployed-URL space (TIM-1274).
91
+ base: normalizeBasePath(ctx.base),
88
92
  output: ctx.config.output ?? 'server',
89
93
  clientJavascriptDisabled: ctx.clientJavascript.disabled,
90
94
  manifestInit,
@@ -20,7 +20,7 @@ import { randomUUID, createHash } from 'node:crypto';
20
20
  import { readFileSync } from 'node:fs';
21
21
  import type { Plugin, ResolvedConfig } from 'vite';
22
22
  import type { PluginContext } from '../plugin-context.js';
23
- import type { BuildManifest } from '../server/build-manifest.js';
23
+ import { EMPTY_BUILD_MANIFEST, type BuildManifest } from '../server/build-manifest.js';
24
24
  import type { SegmentNode, RouteFile } from '../routing/types.js';
25
25
  import { isDynamicMetadataExtension } from '../server/metadata-routes.js';
26
26
 
@@ -335,14 +335,12 @@ function walkModuleImports(
335
335
  * Hooks: configResolved, resolveId, load, generateBundle (client and RSC envs)
336
336
  */
337
337
  export function timberBuildManifest(ctx: PluginContext): Plugin {
338
- let resolvedBase = '/';
339
338
  let isDev = false;
340
339
 
341
340
  return {
342
341
  name: 'timber-build-manifest',
343
342
 
344
343
  configResolved(config: ResolvedConfig) {
345
- resolvedBase = config.base;
346
344
  isDev = config.command === 'serve';
347
345
 
348
346
  // Generate a per-build deployment ID early so virtual:timber-config
@@ -373,13 +371,18 @@ export function timberBuildManifest(ctx: PluginContext): Plugin {
373
371
  load(id: string) {
374
372
  if (id !== RESOLVED_VIRTUAL_ID) return null;
375
373
 
374
+ // Serialized, not restated: an empty manifest is described once, in
375
+ // server/build-manifest.ts. Both branches below emitted their own object
376
+ // literal and had already drifted apart — see EMPTY_BUILD_MANIFEST.
377
+ const empty = JSON.stringify(EMPTY_BUILD_MANIFEST);
378
+
376
379
  // In dev mode, return empty manifest — Vite HMR handles CSS.
377
380
  if (isDev) {
378
381
  return [
379
382
  '// Auto-generated build manifest — do not edit.',
380
383
  '// Dev mode: empty manifest (Vite HMR handles CSS/JS).',
381
384
  '',
382
- 'const manifest = { css: {}, js: {}, modulepreload: {}, fonts: {}, metadataRouteHashes: {} };',
385
+ `const manifest = ${empty};`,
383
386
  '',
384
387
  'export default manifest;',
385
388
  ].join('\n');
@@ -389,11 +392,17 @@ export function timberBuildManifest(ctx: PluginContext): Plugin {
389
392
  // The adapter writes a _timber-manifest-init.js that sets this global
390
393
  // before the RSC handler imports this module. ESM evaluation order
391
394
  // guarantees the global is set by the time this code runs.
395
+ //
396
+ // The literal is only reached when the global is unset — an app built
397
+ // with no adapter, which writes no init module. It is NOT the map the
398
+ // build computed; that lives in _timber-manifest-init.js (TIM-1300).
392
399
  return [
393
400
  '// Auto-generated build manifest — do not edit.',
394
401
  '// Production: reads manifest from globalThis (set by _timber-manifest-init.js).',
402
+ '// The object below is only the fallback for when that global is unset —',
403
+ '// the real manifest, including the requestDep map, is in that init module.',
395
404
  '',
396
- 'const manifest = globalThis.__TIMBER_BUILD_MANIFEST__ ?? { css: {}, js: {}, modulepreload: {}, fonts: {}, metadataRouteHashes: {}, requestDep: {} };',
405
+ `const manifest = globalThis.__TIMBER_BUILD_MANIFEST__ ?? ${empty};`,
397
406
  '',
398
407
  'export default manifest;',
399
408
  ].join('\n');
@@ -436,21 +445,33 @@ export function timberBuildManifest(ctx: PluginContext): Plugin {
436
445
  }
437
446
 
438
447
  if (envName === 'client') {
439
- ctx.buildManifest = buildManifestFromBundle(bundle, resolvedBase, ctx.root);
448
+ ctx.buildManifest = buildManifestFromBundle(bundle, ctx.base, ctx.root);
440
449
 
441
450
  // Compute cache-busting hashes for metadata route files
442
451
  if (ctx.routeTree) {
443
452
  ctx.buildManifest.metadataRouteHashes = computeMetadataRouteHashes(ctx.routeTree.root);
444
453
  }
445
454
 
446
- // Attach static request-dependency map from the request-dep plugin.
447
- // Computed in the RSC buildEnd hook and stored on ctx.
448
- const requestDepMap = (ctx as unknown as Record<string, unknown>).requestDepMap as
449
- | Record<string, boolean>
450
- | undefined;
451
- if (requestDepMap) {
452
- ctx.buildManifest.requestDep = requestDepMap;
455
+ // Attach the static request-dependency map from the request-dep
456
+ // plugin, computed in the RSC `buildEnd` hook. The RSC environment is
457
+ // built before the client one, so the field is populated by now.
458
+ //
459
+ // Absent means the RSC `buildEnd` never ran — a broken plugin pipeline,
460
+ // not an app without segments, which produces `{}`. Serializing that as
461
+ // an empty map is indistinguishable at runtime from an analysis that
462
+ // found nothing (`server/request-dep.ts` answers `true` for any absent
463
+ // key either way), so every segment and slot silently stops being a
464
+ // skip candidate and slot caching is off with nothing to show for it.
465
+ // Fail the build instead (TIM-1300).
466
+ if (ctx.requestDepMap === undefined) {
467
+ throw new Error(
468
+ '[timber] Build manifest: the request-dependency map was never computed. ' +
469
+ "The RSC environment's buildEnd hook did not run before the client build, " +
470
+ 'so no segment or slot could be skipped on client navigation. This is a ' +
471
+ 'plugin pipeline bug — timber-request-dep must run in the rsc environment.'
472
+ );
453
473
  }
474
+ ctx.buildManifest.requestDep = ctx.requestDepMap;
454
475
 
455
476
  // When client JavaScript is disabled, strip JS chunks from the bundle
456
477
  // so Rollup never writes them to disk. CSS assets are preserved —
@@ -136,6 +136,10 @@ function generateConfigModule(ctx: PluginContext): string {
136
136
  csrf: ctx.config.csrf ?? true,
137
137
  allowedOrigins: ctx.config.allowedOrigins,
138
138
  clientJavascript: ctx.clientJavascript,
139
+ // Vite's resolved `base` — the deployment path prefix. The client needs
140
+ // it to address pre-generated RSC payloads in static mode, which live
141
+ // below the base like every other emitted file (TIM-1261).
142
+ base: ctx.base,
139
143
  dev: ctx.dev ?? false,
140
144
  slowPhaseMs: ctx.config.dev?.slowPhaseMs ?? 200,
141
145
  slowRequestMs: ctx.config.slowRequestMs ?? 3000,
@@ -62,18 +62,21 @@ export {
62
62
  */
63
63
  export function timberFonts(ctx: PluginContext): Plugin {
64
64
  const pipeline = new FontPipeline({ hashOnRegister: !ctx.dev });
65
- let resolvedBase = '/';
66
65
 
67
66
  return {
68
67
  name: 'timber-fonts',
69
68
 
70
69
  /**
71
- * Capture Vite's resolved `base` so every font URL the pipeline emits
72
- * (@font-face src, manifest hrefs, dev middleware matching) carries
73
- * the prefix. Emitted file locations are unaffected — only URLs.
70
+ * Push Vite's resolved `base` into the pipeline so every font URL it
71
+ * emits (@font-face src, manifest hrefs, dev middleware matching)
72
+ * carries the prefix. Emitted file locations are unaffected — only URLs.
73
+ *
74
+ * `config.base` is read here rather than `ctx.base`: this plugin is
75
+ * `enforce: 'pre'`, so its configResolved runs before timber-root-sync
76
+ * populates `ctx.base`. Every *later* hook reads `ctx.base` — the single
77
+ * copy (TIM-1261).
74
78
  */
75
79
  configResolved(config: ResolvedConfig) {
76
- resolvedBase = config.base;
77
80
  pipeline.setBase(config.base);
78
81
 
79
82
  // Font binaries are emitted in generateBundle, after Vite's CSS
@@ -188,7 +191,7 @@ export function timberFonts(ctx: PluginContext): Plugin {
188
191
  pipeline.attachCachedFiles(font.id, familyCached);
189
192
  pipeline.attachFaces(
190
193
  font.id,
191
- generateProductionFontFaces(familyCached, font.display, fontUrlPrefix(resolvedBase))
194
+ generateProductionFontFaces(familyCached, font.display, fontUrlPrefix(ctx.base))
192
195
  );
193
196
  }
194
197
  } catch (e) {
@@ -211,7 +214,7 @@ export function timberFonts(ctx: PluginContext): Plugin {
211
214
  * this middleware.
212
215
  */
213
216
  configureServer(server: ViteDevServer) {
214
- installFontDevMiddleware(server, pipeline, resolvedBase);
217
+ installFontDevMiddleware(server, pipeline, ctx.base);
215
218
  },
216
219
 
217
220
  /**
@@ -292,7 +295,7 @@ export function timberFonts(ctx: PluginContext): Plugin {
292
295
  (msg) => this.warn(msg)
293
296
  );
294
297
  if (!ctx.buildManifest) return;
295
- writeFontManifest(pipeline, ctx.buildManifest, resolvedBase);
298
+ writeFontManifest(pipeline, ctx.buildManifest, ctx.base);
296
299
  },
297
300
  };
298
301
  }