@timber-js/app 0.2.0-alpha.18 → 0.2.0-alpha.180

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 (1026) hide show
  1. package/LICENSE +8 -0
  2. package/agent-skill.md +344 -0
  3. package/dist/_chunks/actions-O_LsyCE4.js +317 -0
  4. package/dist/_chunks/actions-O_LsyCE4.js.map +1 -0
  5. package/dist/_chunks/build-output-helper-DF5uScqS.js +158 -0
  6. package/dist/_chunks/build-output-helper-DF5uScqS.js.map +1 -0
  7. package/dist/_chunks/cache-api-B-lhk9p4.js +1202 -0
  8. package/dist/_chunks/cache-api-B-lhk9p4.js.map +1 -0
  9. package/dist/_chunks/canonicalize-DQHyFClh.js +248 -0
  10. package/dist/_chunks/canonicalize-DQHyFClh.js.map +1 -0
  11. package/dist/_chunks/cli-schema-sync-D3naS3eH.js +688 -0
  12. package/dist/_chunks/cli-schema-sync-D3naS3eH.js.map +1 -0
  13. package/dist/_chunks/cloudflare-AHoWYTYr.js +1188 -0
  14. package/dist/_chunks/cloudflare-AHoWYTYr.js.map +1 -0
  15. package/dist/_chunks/codec-registry-oOUxugz3.js +21 -0
  16. package/dist/_chunks/codec-registry-oOUxugz3.js.map +1 -0
  17. package/dist/_chunks/define-COtkxMRT.js +191 -0
  18. package/dist/_chunks/define-COtkxMRT.js.map +1 -0
  19. package/dist/_chunks/define-c4au4I9R.js +82 -0
  20. package/dist/_chunks/define-c4au4I9R.js.map +1 -0
  21. package/dist/_chunks/dist-BA3u1z3W.js +423 -0
  22. package/dist/_chunks/dist-BA3u1z3W.js.map +1 -0
  23. package/dist/_chunks/fast-hash-D6hIVt1Y.js +36 -0
  24. package/dist/_chunks/fast-hash-D6hIVt1Y.js.map +1 -0
  25. package/dist/_chunks/format-CfwjgPz9.js +14 -0
  26. package/dist/_chunks/format-CfwjgPz9.js.map +1 -0
  27. package/dist/_chunks/href-validation-CMc5JRls.js +141 -0
  28. package/dist/_chunks/href-validation-CMc5JRls.js.map +1 -0
  29. package/dist/_chunks/json-lossy-check-ClNvBM_3.js +63 -0
  30. package/dist/_chunks/json-lossy-check-ClNvBM_3.js.map +1 -0
  31. package/dist/_chunks/logger-AWfuX-KJ.js +1468 -0
  32. package/dist/_chunks/logger-AWfuX-KJ.js.map +1 -0
  33. package/dist/_chunks/navigation-root-bUDZLw74.js +124 -0
  34. package/dist/_chunks/navigation-root-bUDZLw74.js.map +1 -0
  35. package/dist/_chunks/plugin-context---kTF5v8.js +315 -0
  36. package/dist/_chunks/plugin-context---kTF5v8.js.map +1 -0
  37. package/dist/_chunks/registry-DbJPKoBp.js +20 -0
  38. package/dist/_chunks/registry-DbJPKoBp.js.map +1 -0
  39. package/dist/_chunks/resolve-schema-Dz3fcFUo.js +50 -0
  40. package/dist/_chunks/resolve-schema-Dz3fcFUo.js.map +1 -0
  41. package/dist/_chunks/router-ref-CtmF-aPv.js +28 -0
  42. package/dist/_chunks/router-ref-CtmF-aPv.js.map +1 -0
  43. package/dist/_chunks/schema-bridge-DT_Tn0Xf.js +119 -0
  44. package/dist/_chunks/schema-bridge-DT_Tn0Xf.js.map +1 -0
  45. package/dist/_chunks/segment-classify-Byy425ng.js +176 -0
  46. package/dist/_chunks/segment-classify-Byy425ng.js.map +1 -0
  47. package/dist/_chunks/segment-context-ZDnXDkbz.js +34 -0
  48. package/dist/_chunks/segment-context-ZDnXDkbz.js.map +1 -0
  49. package/dist/_chunks/sizeof-lXffQ1Vr.js +35 -0
  50. package/dist/_chunks/sizeof-lXffQ1Vr.js.map +1 -0
  51. package/dist/_chunks/{ssr-data-MjmprTmO.js → ssr-data-BOWsq18U.js} +1 -1
  52. package/dist/_chunks/ssr-data-BOWsq18U.js.map +1 -0
  53. package/dist/_chunks/{use-query-states-D5KaffOK.js → use-query-states-DFvWd-EA.js} +71 -26
  54. package/dist/_chunks/use-query-states-DFvWd-EA.js.map +1 -0
  55. package/dist/_chunks/use-segment-params-D1CzlgBo.js +151 -0
  56. package/dist/_chunks/use-segment-params-D1CzlgBo.js.map +1 -0
  57. package/dist/_chunks/walkers-BtTlKviE.js +1002 -0
  58. package/dist/_chunks/walkers-BtTlKviE.js.map +1 -0
  59. package/dist/adapters/build-output-helper.d.ts +29 -0
  60. package/dist/adapters/build-output-helper.d.ts.map +1 -0
  61. package/dist/adapters/cloudflare-dev.d.ts +109 -0
  62. package/dist/adapters/cloudflare-dev.d.ts.map +1 -0
  63. package/dist/adapters/cloudflare-dev.js +73 -0
  64. package/dist/adapters/cloudflare-dev.js.map +1 -0
  65. package/dist/adapters/cloudflare-kv-cache.d.ts +65 -0
  66. package/dist/adapters/cloudflare-kv-cache.d.ts.map +1 -0
  67. package/dist/adapters/cloudflare-kv-cache.js +124 -0
  68. package/dist/adapters/cloudflare-kv-cache.js.map +1 -0
  69. package/dist/adapters/cloudflare.d.ts +189 -21
  70. package/dist/adapters/cloudflare.d.ts.map +1 -1
  71. package/dist/adapters/cloudflare.js +2 -188
  72. package/dist/adapters/compress-module.d.ts +5 -4
  73. package/dist/adapters/compress-module.d.ts.map +1 -1
  74. package/dist/adapters/nitro.d.ts +41 -3
  75. package/dist/adapters/nitro.d.ts.map +1 -1
  76. package/dist/adapters/nitro.js +224 -172
  77. package/dist/adapters/nitro.js.map +1 -1
  78. package/dist/adapters/shared.d.ts +6 -0
  79. package/dist/adapters/shared.d.ts.map +1 -0
  80. package/dist/adapters/types.d.ts +2 -6
  81. package/dist/adapters/types.d.ts.map +1 -1
  82. package/dist/cache/cache-api.d.ts +48 -0
  83. package/dist/cache/cache-api.d.ts.map +1 -0
  84. package/dist/cache/handler-store.d.ts +33 -0
  85. package/dist/cache/handler-store.d.ts.map +1 -0
  86. package/dist/cache/index.d.ts +31 -8
  87. package/dist/cache/index.d.ts.map +1 -1
  88. package/dist/cache/index.js +3 -326
  89. package/dist/cache/invalidation-epoch.d.ts +43 -0
  90. package/dist/cache/invalidation-epoch.d.ts.map +1 -0
  91. package/dist/cache/json-lossy-check.d.ts +11 -0
  92. package/dist/cache/json-lossy-check.d.ts.map +1 -0
  93. package/dist/cache/redis-handler.d.ts +140 -8
  94. package/dist/cache/redis-handler.d.ts.map +1 -1
  95. package/dist/cache/singleflight.d.ts +19 -2
  96. package/dist/cache/singleflight.d.ts.map +1 -1
  97. package/dist/cache/sizeof.d.ts +22 -0
  98. package/dist/cache/sizeof.d.ts.map +1 -0
  99. package/dist/cache/stable-stringify.d.ts +9 -0
  100. package/dist/cache/stable-stringify.d.ts.map +1 -1
  101. package/dist/cache/store.d.ts +53 -0
  102. package/dist/cache/store.d.ts.map +1 -0
  103. package/dist/cache/stores/cloudflare-kv.d.ts +38 -0
  104. package/dist/cache/stores/cloudflare-kv.d.ts.map +1 -0
  105. package/dist/cache/stores/cloudflare-kv.js +29 -0
  106. package/dist/cache/stores/cloudflare-kv.js.map +1 -0
  107. package/dist/cache/stores/memory.d.ts +42 -0
  108. package/dist/cache/stores/memory.d.ts.map +1 -0
  109. package/dist/cache/stores/memory.js +90 -0
  110. package/dist/cache/stores/memory.js.map +1 -0
  111. package/dist/cache/stores/redis.d.ts +69 -0
  112. package/dist/cache/stores/redis.d.ts.map +1 -0
  113. package/dist/cache/stores/redis.js +35 -0
  114. package/dist/cache/stores/redis.js.map +1 -0
  115. package/dist/cache/stores/vercel.d.ts +36 -0
  116. package/dist/cache/stores/vercel.d.ts.map +1 -0
  117. package/dist/cache/stores/vercel.js +33 -0
  118. package/dist/cache/stores/vercel.js.map +1 -0
  119. package/dist/cache/tag-aware-handler.d.ts +52 -0
  120. package/dist/cache/tag-aware-handler.d.ts.map +1 -0
  121. package/dist/cache/timber-cache.d.ts +20 -10
  122. package/dist/cache/timber-cache.d.ts.map +1 -1
  123. package/dist/cdn/cloudflare-purge.d.ts +23 -0
  124. package/dist/cdn/cloudflare-purge.d.ts.map +1 -0
  125. package/dist/cdn/fastly-purge.d.ts +25 -0
  126. package/dist/cdn/fastly-purge.d.ts.map +1 -0
  127. package/dist/cdn/headers.d.ts +97 -0
  128. package/dist/cdn/headers.d.ts.map +1 -0
  129. package/dist/cdn/index.d.ts +5 -0
  130. package/dist/cdn/index.d.ts.map +1 -0
  131. package/dist/cdn/purge-store.d.ts +23 -0
  132. package/dist/cdn/purge-store.d.ts.map +1 -0
  133. package/dist/cdn/workers-cache-purge.d.ts +16 -0
  134. package/dist/cdn/workers-cache-purge.d.ts.map +1 -0
  135. package/dist/cli-schema-sync.d.ts +59 -0
  136. package/dist/cli-schema-sync.d.ts.map +1 -0
  137. package/dist/cli.d.ts +35 -2
  138. package/dist/cli.d.ts.map +1 -1
  139. package/dist/cli.js +113 -34
  140. package/dist/cli.js.map +1 -1
  141. package/dist/client/browser-dev.d.ts +37 -1
  142. package/dist/client/browser-dev.d.ts.map +1 -1
  143. package/dist/client/browser-entry/action-dispatch.d.ts +17 -0
  144. package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -0
  145. package/dist/client/browser-entry/hmr.d.ts +21 -0
  146. package/dist/client/browser-entry/hmr.d.ts.map +1 -0
  147. package/dist/client/browser-entry/hydrate.d.ts +46 -0
  148. package/dist/client/browser-entry/hydrate.d.ts.map +1 -0
  149. package/dist/client/browser-entry/index.d.ts +29 -0
  150. package/dist/client/browser-entry/index.d.ts.map +1 -0
  151. package/dist/client/browser-entry/post-hydration.d.ts +26 -0
  152. package/dist/client/browser-entry/post-hydration.d.ts.map +1 -0
  153. package/dist/client/browser-entry/router-init.d.ts +27 -0
  154. package/dist/client/browser-entry/router-init.d.ts.map +1 -0
  155. package/dist/client/browser-entry/rsc-stream.d.ts +24 -0
  156. package/dist/client/browser-entry/rsc-stream.d.ts.map +1 -0
  157. package/dist/client/browser-entry/scroll.d.ts +28 -0
  158. package/dist/client/browser-entry/scroll.d.ts.map +1 -0
  159. package/dist/client/error-boundary.d.ts +12 -5
  160. package/dist/client/error-boundary.d.ts.map +1 -1
  161. package/dist/client/error-boundary.js +47 -10
  162. package/dist/client/error-boundary.js.map +1 -1
  163. package/dist/client/error-reconstituter.d.ts +61 -0
  164. package/dist/client/error-reconstituter.d.ts.map +1 -0
  165. package/dist/client/form.d.ts +16 -27
  166. package/dist/client/form.d.ts.map +1 -1
  167. package/dist/client/history.d.ts +21 -6
  168. package/dist/client/history.d.ts.map +1 -1
  169. package/dist/client/index.d.ts +10 -24
  170. package/dist/client/index.d.ts.map +1 -1
  171. package/dist/client/index.js +185 -1134
  172. package/dist/client/index.js.map +1 -1
  173. package/dist/client/internal.d.ts +19 -0
  174. package/dist/client/internal.d.ts.map +1 -0
  175. package/dist/client/internal.js +887 -0
  176. package/dist/client/internal.js.map +1 -0
  177. package/dist/client/link.d.ts +69 -60
  178. package/dist/client/link.d.ts.map +1 -1
  179. package/dist/client/navigation-api.d.ts +121 -0
  180. package/dist/client/navigation-api.d.ts.map +1 -0
  181. package/dist/client/navigation-context.d.ts +3 -2
  182. package/dist/client/navigation-context.d.ts.map +1 -1
  183. package/dist/client/navigation-root.d.ts +119 -0
  184. package/dist/client/navigation-root.d.ts.map +1 -0
  185. package/dist/client/nuqs-adapter.d.ts +1 -1
  186. package/dist/client/nuqs-adapter.d.ts.map +1 -1
  187. package/dist/client/router-ref.d.ts +1 -1
  188. package/dist/client/router.d.ts +99 -14
  189. package/dist/client/router.d.ts.map +1 -1
  190. package/dist/client/rsc-fetch.d.ts +48 -15
  191. package/dist/client/rsc-fetch.d.ts.map +1 -1
  192. package/dist/client/segment-cache.d.ts +26 -7
  193. package/dist/client/segment-cache.d.ts.map +1 -1
  194. package/dist/client/segment-outlet.d.ts +57 -0
  195. package/dist/client/segment-outlet.d.ts.map +1 -0
  196. package/dist/client/segment-update-context.d.ts +21 -0
  197. package/dist/client/segment-update-context.d.ts.map +1 -0
  198. package/dist/client/shallow-url.d.ts +10 -0
  199. package/dist/client/shallow-url.d.ts.map +1 -0
  200. package/dist/client/slot-context.d.ts +31 -0
  201. package/dist/client/slot-context.d.ts.map +1 -0
  202. package/dist/client/slot-outlet.d.ts +16 -0
  203. package/dist/client/slot-outlet.d.ts.map +1 -0
  204. package/dist/client/slot-provider.d.ts +25 -0
  205. package/dist/client/slot-provider.d.ts.map +1 -0
  206. package/dist/client/ssr-data.d.ts +13 -4
  207. package/dist/client/ssr-data.d.ts.map +1 -1
  208. package/dist/client/state.d.ts +1 -1
  209. package/dist/client/top-loader.d.ts +5 -5
  210. package/dist/client/top-loader.d.ts.map +1 -1
  211. package/dist/client/use-cookie.d.ts +12 -0
  212. package/dist/client/use-cookie.d.ts.map +1 -1
  213. package/dist/client/use-link-status.d.ts +5 -5
  214. package/dist/client/use-link-status.d.ts.map +1 -1
  215. package/dist/client/use-pathname.d.ts.map +1 -1
  216. package/dist/client/use-pending-navigation.d.ts +23 -0
  217. package/dist/client/use-pending-navigation.d.ts.map +1 -0
  218. package/dist/client/use-query-states.d.ts +1 -1
  219. package/dist/client/use-query-states.d.ts.map +1 -1
  220. package/dist/client/use-router.d.ts +1 -1
  221. package/dist/client/use-router.d.ts.map +1 -1
  222. package/dist/client/use-search-params.d.ts +12 -5
  223. package/dist/client/use-search-params.d.ts.map +1 -1
  224. package/dist/client/{use-params.d.ts → use-segment-params.d.ts} +8 -6
  225. package/dist/client/use-segment-params.d.ts.map +1 -0
  226. package/dist/codec.d.ts +69 -0
  227. package/dist/codec.d.ts.map +1 -0
  228. package/dist/codec.js +76 -0
  229. package/dist/codec.js.map +1 -0
  230. package/dist/config-types.d.ts +284 -0
  231. package/dist/config-types.d.ts.map +1 -0
  232. package/dist/config-validation.d.ts +51 -0
  233. package/dist/config-validation.d.ts.map +1 -0
  234. package/dist/content/index.d.ts +1 -10
  235. package/dist/content/index.d.ts.map +1 -1
  236. package/dist/content/index.js +0 -2
  237. package/dist/cookies/define-cookie.d.ts +58 -25
  238. package/dist/cookies/define-cookie.d.ts.map +1 -1
  239. package/dist/cookies/index.d.ts +2 -1
  240. package/dist/cookies/index.d.ts.map +1 -1
  241. package/dist/cookies/index.js +257 -36
  242. package/dist/cookies/index.js.map +1 -1
  243. package/dist/cookies/json-cookie.d.ts +64 -0
  244. package/dist/cookies/json-cookie.d.ts.map +1 -0
  245. package/dist/cookies/validation.d.ts +34 -0
  246. package/dist/cookies/validation.d.ts.map +1 -0
  247. package/dist/dev-tools/404-page.d.ts +50 -0
  248. package/dist/dev-tools/404-page.d.ts.map +1 -0
  249. package/dist/dev-tools/browser-logs.d.ts +40 -0
  250. package/dist/dev-tools/browser-logs.d.ts.map +1 -0
  251. package/dist/dev-tools/dev-page-shell.d.ts +78 -0
  252. package/dist/dev-tools/dev-page-shell.d.ts.map +1 -0
  253. package/dist/dev-tools/error-page.d.ts +32 -0
  254. package/dist/dev-tools/error-page.d.ts.map +1 -0
  255. package/dist/dev-tools/holding-server.d.ts +54 -0
  256. package/dist/dev-tools/holding-server.d.ts.map +1 -0
  257. package/dist/dev-tools/hydration-overlay.d.ts +11 -0
  258. package/dist/dev-tools/hydration-overlay.d.ts.map +1 -0
  259. package/dist/dev-tools/index.d.ts +31 -0
  260. package/dist/dev-tools/index.d.ts.map +1 -0
  261. package/dist/dev-tools/instrumentation.d.ts +59 -0
  262. package/dist/dev-tools/instrumentation.d.ts.map +1 -0
  263. package/dist/{server/dev-logger.d.ts → dev-tools/logger.d.ts} +1 -1
  264. package/dist/dev-tools/logger.d.ts.map +1 -0
  265. package/dist/{plugins/dev-logs.d.ts → dev-tools/logs.d.ts} +17 -3
  266. package/dist/dev-tools/logs.d.ts.map +1 -0
  267. package/dist/dev-tools/overlay.d.ts +91 -0
  268. package/dist/dev-tools/overlay.d.ts.map +1 -0
  269. package/dist/dev-tools/stack-classifier.d.ts +34 -0
  270. package/dist/dev-tools/stack-classifier.d.ts.map +1 -0
  271. package/dist/dev-tools/terminal.d.ts +28 -0
  272. package/dist/dev-tools/terminal.d.ts.map +1 -0
  273. package/dist/fonts/ast-walk.d.ts +68 -0
  274. package/dist/fonts/ast-walk.d.ts.map +1 -0
  275. package/dist/fonts/ast.d.ts +110 -6
  276. package/dist/fonts/ast.d.ts.map +1 -1
  277. package/dist/fonts/bundle.d.ts +50 -0
  278. package/dist/fonts/bundle.d.ts.map +1 -0
  279. package/dist/fonts/dev-middleware.d.ts +22 -0
  280. package/dist/fonts/dev-middleware.d.ts.map +1 -0
  281. package/dist/fonts/fallbacks.d.ts +0 -7
  282. package/dist/fonts/fallbacks.d.ts.map +1 -1
  283. package/dist/fonts/google.d.ts +4 -2
  284. package/dist/fonts/google.d.ts.map +1 -1
  285. package/dist/fonts/local.d.ts +4 -4
  286. package/dist/fonts/local.d.ts.map +1 -1
  287. package/dist/fonts/paths.d.ts +43 -0
  288. package/dist/fonts/paths.d.ts.map +1 -0
  289. package/dist/fonts/pipeline.d.ts +177 -0
  290. package/dist/fonts/pipeline.d.ts.map +1 -0
  291. package/dist/fonts/transform.d.ts +82 -0
  292. package/dist/fonts/transform.d.ts.map +1 -0
  293. package/dist/fonts/types.d.ts +47 -1
  294. package/dist/fonts/types.d.ts.map +1 -1
  295. package/dist/fonts/virtual-modules.d.ts +77 -0
  296. package/dist/fonts/virtual-modules.d.ts.map +1 -0
  297. package/dist/index.d.ts +46 -180
  298. package/dist/index.d.ts.map +1 -1
  299. package/dist/index.js +9243 -14093
  300. package/dist/index.js.map +1 -1
  301. package/dist/params/codec-registry.d.ts +26 -0
  302. package/dist/params/codec-registry.d.ts.map +1 -0
  303. package/dist/params/define-schema.d.ts +81 -0
  304. package/dist/params/define-schema.d.ts.map +1 -0
  305. package/dist/params/index.d.ts +5 -0
  306. package/dist/params/index.d.ts.map +1 -0
  307. package/dist/params/index.js +34 -0
  308. package/dist/params/index.js.map +1 -0
  309. package/dist/params/resolve-schema.d.ts +34 -0
  310. package/dist/params/resolve-schema.d.ts.map +1 -0
  311. package/dist/plugin-context.d.ts +217 -0
  312. package/dist/plugin-context.d.ts.map +1 -0
  313. package/dist/plugins/adapter-build.d.ts +21 -1
  314. package/dist/plugins/adapter-build.d.ts.map +1 -1
  315. package/dist/plugins/build-manifest.d.ts +7 -3
  316. package/dist/plugins/build-manifest.d.ts.map +1 -1
  317. package/dist/plugins/build-report.d.ts +43 -7
  318. package/dist/plugins/build-report.d.ts.map +1 -1
  319. package/dist/plugins/cache.d.ts +64 -0
  320. package/dist/plugins/cache.d.ts.map +1 -0
  321. package/dist/plugins/callsite-ast.d.ts +117 -0
  322. package/dist/plugins/callsite-ast.d.ts.map +1 -0
  323. package/dist/plugins/callsite-jsx.d.ts +35 -0
  324. package/dist/plugins/callsite-jsx.d.ts.map +1 -0
  325. package/dist/plugins/chunks.d.ts +11 -4
  326. package/dist/plugins/chunks.d.ts.map +1 -1
  327. package/dist/plugins/client-chunks.d.ts +40 -0
  328. package/dist/plugins/client-chunks.d.ts.map +1 -0
  329. package/dist/plugins/cloudflare-wasm.d.ts +21 -0
  330. package/dist/plugins/cloudflare-wasm.d.ts.map +1 -0
  331. package/dist/plugins/content.d.ts +1 -1
  332. package/dist/plugins/content.d.ts.map +1 -1
  333. package/dist/plugins/dev-server.d.ts +17 -1
  334. package/dist/plugins/dev-server.d.ts.map +1 -1
  335. package/dist/plugins/entries.d.ts +28 -4
  336. package/dist/plugins/entries.d.ts.map +1 -1
  337. package/dist/plugins/fonts.d.ts +16 -73
  338. package/dist/plugins/fonts.d.ts.map +1 -1
  339. package/dist/plugins/mdx.d.ts +1 -1
  340. package/dist/plugins/mdx.d.ts.map +1 -1
  341. package/dist/plugins/prebuilt-capture.d.ts +60 -0
  342. package/dist/plugins/prebuilt-capture.d.ts.map +1 -0
  343. package/dist/plugins/prebuilt-options-analysis.d.ts +40 -0
  344. package/dist/plugins/prebuilt-options-analysis.d.ts.map +1 -0
  345. package/dist/plugins/prebuilt.d.ts +82 -0
  346. package/dist/plugins/prebuilt.d.ts.map +1 -0
  347. package/dist/plugins/prerender-sugar.d.ts +42 -0
  348. package/dist/plugins/prerender-sugar.d.ts.map +1 -0
  349. package/dist/plugins/request-dep.d.ts +21 -0
  350. package/dist/plugins/request-dep.d.ts.map +1 -0
  351. package/dist/plugins/routing.d.ts +1 -1
  352. package/dist/plugins/routing.d.ts.map +1 -1
  353. package/dist/plugins/server-bundle.d.ts.map +1 -1
  354. package/dist/plugins/shims.d.ts +29 -5
  355. package/dist/plugins/shims.d.ts.map +1 -1
  356. package/dist/plugins/static-build.d.ts +5 -26
  357. package/dist/plugins/static-build.d.ts.map +1 -1
  358. package/dist/routing/codegen-shared.d.ts +67 -0
  359. package/dist/routing/codegen-shared.d.ts.map +1 -0
  360. package/dist/routing/codegen-types.d.ts +64 -0
  361. package/dist/routing/codegen-types.d.ts.map +1 -0
  362. package/dist/routing/codegen.d.ts +7 -2
  363. package/dist/routing/codegen.d.ts.map +1 -1
  364. package/dist/routing/convention-lint.d.ts +41 -0
  365. package/dist/routing/convention-lint.d.ts.map +1 -0
  366. package/dist/routing/export-detect.d.ts +56 -0
  367. package/dist/routing/export-detect.d.ts.map +1 -0
  368. package/dist/routing/file-cache.d.ts +8 -0
  369. package/dist/routing/file-cache.d.ts.map +1 -0
  370. package/dist/routing/index.d.ts +7 -1
  371. package/dist/routing/index.d.ts.map +1 -1
  372. package/dist/routing/index.js +4 -2
  373. package/dist/routing/interception.d.ts +0 -5
  374. package/dist/routing/interception.d.ts.map +1 -1
  375. package/dist/routing/link-codegen.d.ts +90 -0
  376. package/dist/routing/link-codegen.d.ts.map +1 -0
  377. package/dist/routing/manifest-codegen.d.ts +32 -0
  378. package/dist/routing/manifest-codegen.d.ts.map +1 -0
  379. package/dist/routing/scanner.d.ts +1 -10
  380. package/dist/routing/scanner.d.ts.map +1 -1
  381. package/dist/routing/schema-validation.d.ts +35 -0
  382. package/dist/routing/schema-validation.d.ts.map +1 -0
  383. package/dist/routing/segment-classify.d.ts +81 -0
  384. package/dist/routing/segment-classify.d.ts.map +1 -0
  385. package/dist/routing/segment-codegen.d.ts +38 -0
  386. package/dist/routing/segment-codegen.d.ts.map +1 -0
  387. package/dist/routing/types.d.ts +81 -25
  388. package/dist/routing/types.d.ts.map +1 -1
  389. package/dist/routing/walkers.d.ts +51 -0
  390. package/dist/routing/walkers.d.ts.map +1 -0
  391. package/dist/rsc-runtime/rsc.d.ts +1 -1
  392. package/dist/rsc-runtime/rsc.d.ts.map +1 -1
  393. package/dist/rsc-runtime/ssr.d.ts +12 -0
  394. package/dist/rsc-runtime/ssr.d.ts.map +1 -1
  395. package/dist/schema-bridge.d.ts +91 -0
  396. package/dist/schema-bridge.d.ts.map +1 -0
  397. package/dist/search-params/define.d.ts +188 -0
  398. package/dist/search-params/define.d.ts.map +1 -0
  399. package/dist/search-params/index.d.ts +4 -7
  400. package/dist/search-params/index.d.ts.map +1 -1
  401. package/dist/search-params/index.js +34 -441
  402. package/dist/search-params/index.js.map +1 -1
  403. package/dist/search-params/registry.d.ts +2 -2
  404. package/dist/search-params/registry.d.ts.map +1 -1
  405. package/dist/search-params/wrappers.d.ts +53 -0
  406. package/dist/search-params/wrappers.d.ts.map +1 -0
  407. package/dist/segment-params/define.d.ts +89 -0
  408. package/dist/segment-params/define.d.ts.map +1 -0
  409. package/dist/segment-params/index.d.ts +3 -0
  410. package/dist/segment-params/index.d.ts.map +1 -0
  411. package/dist/segment-params/index.js +2 -0
  412. package/dist/server/access-gate.d.ts +8 -3
  413. package/dist/server/access-gate.d.ts.map +1 -1
  414. package/dist/server/action-client.d.ts +42 -7
  415. package/dist/server/action-client.d.ts.map +1 -1
  416. package/dist/server/action-encryption.d.ts +76 -0
  417. package/dist/server/action-encryption.d.ts.map +1 -0
  418. package/dist/server/action-handler.d.ts +35 -1
  419. package/dist/server/action-handler.d.ts.map +1 -1
  420. package/dist/server/actions.d.ts +6 -30
  421. package/dist/server/actions.d.ts.map +1 -1
  422. package/dist/server/als-registry.d.ts +93 -11
  423. package/dist/server/als-registry.d.ts.map +1 -1
  424. package/dist/server/asset-headers.d.ts +8 -18
  425. package/dist/server/asset-headers.d.ts.map +1 -1
  426. package/dist/server/body-limits.d.ts.map +1 -1
  427. package/dist/server/build-manifest.d.ts +12 -29
  428. package/dist/server/build-manifest.d.ts.map +1 -1
  429. package/dist/server/canonicalize.d.ts +10 -0
  430. package/dist/server/canonicalize.d.ts.map +1 -1
  431. package/dist/server/coalesce-tick.d.ts +40 -0
  432. package/dist/server/coalesce-tick.d.ts.map +1 -0
  433. package/dist/server/cookie-context.d.ts +170 -0
  434. package/dist/server/cookie-context.d.ts.map +1 -0
  435. package/dist/server/cookie-parsing.d.ts +65 -0
  436. package/dist/server/cookie-parsing.d.ts.map +1 -0
  437. package/dist/server/csrf.d.ts +3 -2
  438. package/dist/server/csrf.d.ts.map +1 -1
  439. package/dist/server/default-logger.d.ts +22 -0
  440. package/dist/server/default-logger.d.ts.map +1 -0
  441. package/dist/server/deny-boundary.d.ts +117 -0
  442. package/dist/server/deny-boundary.d.ts.map +1 -0
  443. package/dist/server/deny-renderer.d.ts +2 -2
  444. package/dist/server/deny-renderer.d.ts.map +1 -1
  445. package/dist/server/dev-source-map.d.ts +22 -0
  446. package/dist/server/dev-source-map.d.ts.map +1 -0
  447. package/dist/server/early-hints-sender.d.ts.map +1 -1
  448. package/dist/server/early-hints.d.ts +13 -11
  449. package/dist/server/early-hints.d.ts.map +1 -1
  450. package/dist/server/error-boundary-wrapper.d.ts +7 -1
  451. package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
  452. package/dist/server/fallback-error.d.ts +12 -7
  453. package/dist/server/fallback-error.d.ts.map +1 -1
  454. package/dist/server/flight-injection-state.d.ts +66 -0
  455. package/dist/server/flight-injection-state.d.ts.map +1 -0
  456. package/dist/server/flight-scripts.d.ts +42 -0
  457. package/dist/server/flight-scripts.d.ts.map +1 -0
  458. package/dist/server/form-data.d.ts +41 -0
  459. package/dist/server/form-data.d.ts.map +1 -1
  460. package/dist/server/html-injector-core.d.ts +242 -0
  461. package/dist/server/html-injector-core.d.ts.map +1 -0
  462. package/dist/server/html-injectors.d.ts +82 -41
  463. package/dist/server/html-injectors.d.ts.map +1 -1
  464. package/dist/server/index.d.ts +11 -47
  465. package/dist/server/index.d.ts.map +1 -1
  466. package/dist/server/index.js +182 -2906
  467. package/dist/server/index.js.map +1 -1
  468. package/dist/server/internal.d.ts +49 -0
  469. package/dist/server/internal.d.ts.map +1 -0
  470. package/dist/server/internal.js +3892 -0
  471. package/dist/server/internal.js.map +1 -0
  472. package/dist/server/logger.d.ts +39 -7
  473. package/dist/server/logger.d.ts.map +1 -1
  474. package/dist/server/metadata-routes.d.ts +60 -11
  475. package/dist/server/metadata-routes.d.ts.map +1 -1
  476. package/dist/server/metadata.d.ts +8 -0
  477. package/dist/server/metadata.d.ts.map +1 -1
  478. package/dist/server/middleware-runner.d.ts +19 -4
  479. package/dist/server/middleware-runner.d.ts.map +1 -1
  480. package/dist/server/node-stream-transforms.d.ts +119 -0
  481. package/dist/server/node-stream-transforms.d.ts.map +1 -0
  482. package/dist/server/param-coercion.d.ts +54 -0
  483. package/dist/server/param-coercion.d.ts.map +1 -0
  484. package/dist/server/pipeline-helpers.d.ts +95 -0
  485. package/dist/server/pipeline-helpers.d.ts.map +1 -0
  486. package/dist/server/pipeline-interception.d.ts +1 -1
  487. package/dist/server/pipeline-interception.d.ts.map +1 -1
  488. package/dist/server/pipeline-metadata.d.ts +6 -0
  489. package/dist/server/pipeline-metadata.d.ts.map +1 -1
  490. package/dist/server/pipeline-outcome.d.ts +49 -0
  491. package/dist/server/pipeline-outcome.d.ts.map +1 -0
  492. package/dist/server/pipeline-phases.d.ts +59 -0
  493. package/dist/server/pipeline-phases.d.ts.map +1 -0
  494. package/dist/server/pipeline.d.ts +140 -19
  495. package/dist/server/pipeline.d.ts.map +1 -1
  496. package/dist/server/port-resolution.d.ts +117 -0
  497. package/dist/server/port-resolution.d.ts.map +1 -0
  498. package/dist/server/prebuilt/cache-key.d.ts +62 -0
  499. package/dist/server/prebuilt/cache-key.d.ts.map +1 -0
  500. package/dist/server/prebuilt/capture-state.d.ts +57 -0
  501. package/dist/server/prebuilt/capture-state.d.ts.map +1 -0
  502. package/dist/server/prebuilt/key-discipline.d.ts +23 -0
  503. package/dist/server/prebuilt/key-discipline.d.ts.map +1 -0
  504. package/dist/server/prebuilt/manifest-tag-index.d.ts +27 -0
  505. package/dist/server/prebuilt/manifest-tag-index.d.ts.map +1 -0
  506. package/dist/server/prebuilt/overlay.d.ts +100 -0
  507. package/dist/server/prebuilt/overlay.d.ts.map +1 -0
  508. package/dist/server/prebuilt/payload-source.d.ts +78 -0
  509. package/dist/server/prebuilt/payload-source.d.ts.map +1 -0
  510. package/dist/server/prebuilt/slots.d.ts +99 -0
  511. package/dist/server/prebuilt/slots.d.ts.map +1 -0
  512. package/dist/server/prebuilt/synthetic-store.d.ts +66 -0
  513. package/dist/server/prebuilt/synthetic-store.d.ts.map +1 -0
  514. package/dist/server/prebuilt-builder.d.ts +120 -0
  515. package/dist/server/prebuilt-builder.d.ts.map +1 -0
  516. package/dist/server/prebuilt-runtime.d.ts +111 -0
  517. package/dist/server/prebuilt-runtime.d.ts.map +1 -0
  518. package/dist/server/primitives.d.ts +88 -43
  519. package/dist/server/primitives.d.ts.map +1 -1
  520. package/dist/server/render-timeout.d.ts +51 -0
  521. package/dist/server/render-timeout.d.ts.map +1 -0
  522. package/dist/server/render-utils.d.ts +25 -0
  523. package/dist/server/render-utils.d.ts.map +1 -0
  524. package/dist/server/request-context.d.ts +62 -107
  525. package/dist/server/request-context.d.ts.map +1 -1
  526. package/dist/server/request-dep.d.ts +15 -0
  527. package/dist/server/request-dep.d.ts.map +1 -0
  528. package/dist/server/route-element-builder.d.ts +53 -25
  529. package/dist/server/route-element-builder.d.ts.map +1 -1
  530. package/dist/server/route-handler.d.ts.map +1 -1
  531. package/dist/server/route-matcher.d.ts +25 -36
  532. package/dist/server/route-matcher.d.ts.map +1 -1
  533. package/dist/server/rsc-entry/action-middleware-runner.d.ts +66 -0
  534. package/dist/server/rsc-entry/action-middleware-runner.d.ts.map +1 -0
  535. package/dist/server/rsc-entry/api-handler.d.ts +12 -3
  536. package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
  537. package/dist/server/rsc-entry/deny-fallback.d.ts +29 -0
  538. package/dist/server/rsc-entry/deny-fallback.d.ts.map +1 -0
  539. package/dist/server/rsc-entry/error-renderer.d.ts +26 -13
  540. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  541. package/dist/server/rsc-entry/helpers.d.ts +69 -37
  542. package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
  543. package/dist/server/rsc-entry/index.d.ts +28 -6
  544. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  545. package/dist/server/rsc-entry/render-route.d.ts +51 -0
  546. package/dist/server/rsc-entry/render-route.d.ts.map +1 -0
  547. package/dist/server/rsc-entry/revalidate-renderer.d.ts +108 -0
  548. package/dist/server/rsc-entry/revalidate-renderer.d.ts.map +1 -0
  549. package/dist/server/rsc-entry/rsc-payload.d.ts +6 -6
  550. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  551. package/dist/server/rsc-entry/rsc-stream.d.ts +25 -1
  552. package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
  553. package/dist/server/rsc-entry/ssr-bridge.d.ts +5 -1
  554. package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
  555. package/dist/server/rsc-entry/ssr-renderer.d.ts +36 -4
  556. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  557. package/dist/server/rsc-entry/wrap-action-dispatch.d.ts +89 -0
  558. package/dist/server/rsc-entry/wrap-action-dispatch.d.ts.map +1 -0
  559. package/dist/server/safe-load.d.ts +46 -0
  560. package/dist/server/safe-load.d.ts.map +1 -0
  561. package/dist/server/sensitive-fields.d.ts +74 -0
  562. package/dist/server/sensitive-fields.d.ts.map +1 -0
  563. package/dist/server/sitemap-generator.d.ts +129 -0
  564. package/dist/server/sitemap-generator.d.ts.map +1 -0
  565. package/dist/server/sitemap-handler.d.ts +22 -0
  566. package/dist/server/sitemap-handler.d.ts.map +1 -0
  567. package/dist/server/slot-resolver.d.ts +66 -5
  568. package/dist/server/slot-resolver.d.ts.map +1 -1
  569. package/dist/server/ssr-bridge-types.d.ts +121 -0
  570. package/dist/server/ssr-bridge-types.d.ts.map +1 -0
  571. package/dist/server/ssr-entry.d.ts +2 -43
  572. package/dist/server/ssr-entry.d.ts.map +1 -1
  573. package/dist/server/ssr-render.d.ts +64 -21
  574. package/dist/server/ssr-render.d.ts.map +1 -1
  575. package/dist/server/ssr-wrappers.d.ts +50 -0
  576. package/dist/server/ssr-wrappers.d.ts.map +1 -0
  577. package/dist/server/state-tree-diff.d.ts +72 -9
  578. package/dist/server/state-tree-diff.d.ts.map +1 -1
  579. package/dist/server/status-code-resolver.d.ts +22 -11
  580. package/dist/server/status-code-resolver.d.ts.map +1 -1
  581. package/dist/server/stream-utils.d.ts +47 -0
  582. package/dist/server/stream-utils.d.ts.map +1 -0
  583. package/dist/server/tracing.d.ts +44 -9
  584. package/dist/server/tracing.d.ts.map +1 -1
  585. package/dist/server/tree-builder.d.ts +69 -30
  586. package/dist/server/tree-builder.d.ts.map +1 -1
  587. package/dist/server/tree-match.d.ts +49 -0
  588. package/dist/server/tree-match.d.ts.map +1 -0
  589. package/dist/server/types.d.ts +71 -6
  590. package/dist/server/types.d.ts.map +1 -1
  591. package/dist/server/utils/escape-html.d.ts +14 -0
  592. package/dist/server/utils/escape-html.d.ts.map +1 -0
  593. package/dist/server/utils/mdx-file.d.ts +15 -0
  594. package/dist/server/utils/mdx-file.d.ts.map +1 -0
  595. package/dist/server/version-skew.d.ts +61 -0
  596. package/dist/server/version-skew.d.ts.map +1 -0
  597. package/dist/server/workers-cache-bridge.d.ts +26 -0
  598. package/dist/server/workers-cache-bridge.d.ts.map +1 -0
  599. package/dist/shared/href-validation.d.ts +49 -0
  600. package/dist/shared/href-validation.d.ts.map +1 -0
  601. package/dist/shared/merge-search-params.d.ts +22 -0
  602. package/dist/shared/merge-search-params.d.ts.map +1 -0
  603. package/dist/shared/redirect-type.d.ts +17 -0
  604. package/dist/shared/redirect-type.d.ts.map +1 -0
  605. package/dist/shims/font-google.d.ts +1 -1
  606. package/dist/shims/font-google.d.ts.map +1 -1
  607. package/dist/shims/font-google.js +42 -0
  608. package/dist/shims/font-google.js.map +1 -0
  609. package/dist/shims/font-local.d.ts +26 -0
  610. package/dist/shims/font-local.d.ts.map +1 -0
  611. package/dist/shims/font-local.js +20 -0
  612. package/dist/shims/font-local.js.map +1 -0
  613. package/dist/shims/headers.d.ts +53 -1
  614. package/dist/shims/headers.d.ts.map +1 -1
  615. package/dist/shims/image.d.ts +120 -120
  616. package/dist/shims/image.d.ts.map +1 -1
  617. package/dist/shims/navigation-client.d.ts +35 -11
  618. package/dist/shims/navigation-client.d.ts.map +1 -1
  619. package/dist/shims/navigation.d.ts +11 -5
  620. package/dist/shims/navigation.d.ts.map +1 -1
  621. package/dist/utils/state-machine.d.ts +80 -0
  622. package/dist/utils/state-machine.d.ts.map +1 -0
  623. package/docs/api/30-api-server.mdx +233 -0
  624. package/docs/api/31-api-client.mdx +161 -0
  625. package/docs/api/32-api-cache.mdx +311 -0
  626. package/docs/api/33-api-search-params.mdx +154 -0
  627. package/docs/api/34-api-config.mdx +325 -0
  628. package/docs/api/35-api-typescript.mdx +170 -0
  629. package/docs/api/36-cli.mdx +143 -0
  630. package/docs/learn/00-introduction.mdx +109 -0
  631. package/docs/learn/01-quick-start.mdx +94 -0
  632. package/docs/learn/02-pages-and-layouts.mdx +147 -0
  633. package/docs/learn/03-fetching-data.mdx +211 -0
  634. package/docs/learn/03b-access-control.mdx +130 -0
  635. package/docs/learn/04-loading-states.mdx +67 -0
  636. package/docs/learn/04b-the-flush-point.mdx +115 -0
  637. package/docs/learn/05-typed-params.mdx +275 -0
  638. package/docs/learn/06-forms-and-actions.mdx +146 -0
  639. package/docs/learn/07-typed-routes.mdx +127 -0
  640. package/docs/learn/08-streaming.mdx +146 -0
  641. package/docs/learn/09-caching.mdx +252 -0
  642. package/docs/learn/10-middleware.mdx +157 -0
  643. package/docs/learn/11-error-handling.mdx +156 -0
  644. package/docs/learn/12-client-navigation.mdx +176 -0
  645. package/docs/learn/13-configuration.mdx +162 -0
  646. package/docs/learn/14-deploying.mdx +264 -0
  647. package/docs/more/01-advanced-routing.mdx +173 -0
  648. package/docs/more/02-advanced-forms.mdx +137 -0
  649. package/docs/more/03-coming-from-nextjs.mdx +186 -0
  650. package/docs/more/04-metadata-and-fonts.mdx +193 -0
  651. package/docs/more/04b-mdx.mdx +209 -0
  652. package/docs/more/05-content-collections.mdx +90 -0
  653. package/docs/more/06-instrumentation.mdx +214 -0
  654. package/docs/more/07-security.mdx +129 -0
  655. package/docs/more/08-developer-experience.mdx +134 -0
  656. package/docs/more/40-why-timber.mdx +50 -0
  657. package/docs/more/41-timber-vs-nextjs.mdx +81 -0
  658. package/docs/more/42-timber-vs-others.mdx +68 -0
  659. package/docs/more/50-ai-agent-instructions.mdx +169 -0
  660. package/llms.txt +55 -0
  661. package/package.json +105 -26
  662. package/src/adapters/build-output-helper.ts +199 -0
  663. package/src/adapters/cloudflare-dev.ts +177 -0
  664. package/src/adapters/cloudflare-kv-cache.ts +204 -0
  665. package/src/adapters/cloudflare.ts +620 -129
  666. package/src/adapters/compress-module.ts +27 -92
  667. package/src/adapters/nitro.ts +266 -122
  668. package/src/adapters/raw-imports.d.ts +5 -0
  669. package/src/adapters/shared.ts +68 -0
  670. package/src/adapters/types.ts +2 -7
  671. package/src/adapters/wrangler.d.ts +7 -0
  672. package/src/cache/cache-api.ts +107 -0
  673. package/src/cache/handler-store.ts +76 -0
  674. package/src/cache/index.ts +114 -21
  675. package/src/cache/invalidation-epoch.ts +93 -0
  676. package/src/cache/json-lossy-check.ts +75 -0
  677. package/src/cache/redis-handler.ts +197 -19
  678. package/src/cache/singleflight.ts +64 -6
  679. package/src/cache/sizeof.ts +33 -0
  680. package/src/cache/stable-stringify.ts +65 -2
  681. package/src/cache/store.ts +71 -0
  682. package/src/cache/stores/cloudflare-kv.ts +52 -0
  683. package/src/cache/stores/memory.ts +125 -0
  684. package/src/cache/stores/redis.ts +97 -0
  685. package/src/cache/stores/vercel.ts +59 -0
  686. package/src/cache/tag-aware-handler.ts +237 -0
  687. package/src/cache/timber-cache.ts +161 -36
  688. package/src/cdn/cloudflare-purge.ts +50 -0
  689. package/src/cdn/fastly-purge.ts +63 -0
  690. package/src/cdn/headers.ts +153 -0
  691. package/src/cdn/index.ts +17 -0
  692. package/src/cdn/purge-store.ts +34 -0
  693. package/src/cdn/workers-cache-purge.ts +30 -0
  694. package/src/cli-schema-sync.ts +401 -0
  695. package/src/cli.ts +167 -34
  696. package/src/client/browser-dev.ts +156 -1
  697. package/src/client/browser-entry/action-dispatch.ts +124 -0
  698. package/src/client/browser-entry/hmr.ts +70 -0
  699. package/src/client/browser-entry/hydrate.ts +187 -0
  700. package/src/client/browser-entry/index.ts +113 -0
  701. package/src/client/browser-entry/post-hydration.ts +110 -0
  702. package/src/client/browser-entry/router-init.ts +286 -0
  703. package/src/client/browser-entry/rsc-stream.ts +157 -0
  704. package/src/client/browser-entry/scroll.ts +50 -0
  705. package/src/client/error-boundary.tsx +127 -22
  706. package/src/client/error-reconstituter.tsx +79 -0
  707. package/src/client/form.tsx +31 -32
  708. package/src/client/history.ts +21 -6
  709. package/src/client/index.ts +67 -45
  710. package/src/client/internal.ts +58 -0
  711. package/src/client/link.tsx +349 -150
  712. package/src/client/navigation-api.ts +345 -0
  713. package/src/client/navigation-context.ts +15 -7
  714. package/src/client/navigation-root.tsx +355 -0
  715. package/src/client/nuqs-adapter.tsx +16 -3
  716. package/src/client/router-ref.ts +1 -1
  717. package/src/client/router.ts +565 -212
  718. package/src/client/rsc-fetch.ts +215 -34
  719. package/src/client/segment-cache.ts +91 -17
  720. package/src/client/segment-outlet.tsx +141 -0
  721. package/src/client/segment-update-context.ts +42 -0
  722. package/src/client/shallow-url.ts +22 -0
  723. package/src/client/slot-context.ts +50 -0
  724. package/src/client/slot-outlet.tsx +22 -0
  725. package/src/client/slot-provider.tsx +32 -0
  726. package/src/client/ssr-data.ts +13 -5
  727. package/src/client/state.ts +2 -2
  728. package/src/client/top-loader.tsx +11 -9
  729. package/src/client/use-cookie.ts +60 -15
  730. package/src/client/use-link-status.ts +7 -7
  731. package/src/client/use-pathname.ts +1 -0
  732. package/src/client/use-pending-navigation.ts +40 -0
  733. package/src/client/use-query-states.ts +108 -10
  734. package/src/client/use-router.ts +4 -1
  735. package/src/client/use-search-params.ts +31 -44
  736. package/src/client/{use-params.ts → use-segment-params.ts} +9 -6
  737. package/src/codec.ts +149 -0
  738. package/src/config-types.ts +282 -0
  739. package/src/config-validation.ts +330 -0
  740. package/src/content/index.ts +5 -13
  741. package/src/cookies/define-cookie.ts +217 -53
  742. package/src/cookies/index.ts +12 -1
  743. package/src/cookies/json-cookie.ts +105 -0
  744. package/src/cookies/validation.ts +192 -0
  745. package/src/dev-tools/404-page.ts +286 -0
  746. package/src/dev-tools/browser-logs.ts +55 -0
  747. package/src/dev-tools/dev-page-shell.ts +260 -0
  748. package/src/dev-tools/error-page.ts +331 -0
  749. package/src/dev-tools/holding-server.ts +187 -0
  750. package/src/dev-tools/hydration-overlay.ts +158 -0
  751. package/src/dev-tools/index.ts +83 -0
  752. package/src/dev-tools/instrumentation.ts +213 -0
  753. package/src/{server/dev-logger.ts → dev-tools/logger.ts} +33 -51
  754. package/src/{plugins/dev-logs.ts → dev-tools/logs.ts} +122 -26
  755. package/src/dev-tools/overlay.ts +469 -0
  756. package/src/dev-tools/stack-classifier.ts +75 -0
  757. package/src/dev-tools/terminal.ts +182 -0
  758. package/src/fonts/ast-walk.ts +235 -0
  759. package/src/fonts/ast.ts +477 -126
  760. package/src/fonts/bundle.ts +138 -0
  761. package/src/fonts/dev-middleware.ts +85 -0
  762. package/src/fonts/fallbacks.ts +0 -23
  763. package/src/fonts/google.ts +100 -18
  764. package/src/fonts/local.ts +9 -8
  765. package/src/fonts/paths.ts +58 -0
  766. package/src/fonts/pipeline.ts +348 -0
  767. package/src/fonts/transform.ts +311 -0
  768. package/src/fonts/types.ts +52 -1
  769. package/src/fonts/virtual-modules.ts +179 -0
  770. package/src/index.ts +446 -352
  771. package/src/params/codec-registry.ts +34 -0
  772. package/src/params/define-schema.ts +115 -0
  773. package/src/params/index.ts +17 -0
  774. package/src/params/resolve-schema.ts +84 -0
  775. package/src/plugin-context.ts +432 -0
  776. package/src/plugins/adapter-build.ts +220 -7
  777. package/src/plugins/build-manifest.ts +177 -23
  778. package/src/plugins/build-report.ts +253 -35
  779. package/src/plugins/cache.ts +243 -0
  780. package/src/plugins/callsite-ast.ts +472 -0
  781. package/src/plugins/callsite-jsx.ts +243 -0
  782. package/src/plugins/chunks.ts +74 -5
  783. package/src/plugins/client-chunks.ts +185 -0
  784. package/src/plugins/cloudflare-wasm.ts +141 -0
  785. package/src/plugins/content.ts +1 -1
  786. package/src/plugins/dev-server.ts +284 -94
  787. package/src/plugins/entries.ts +134 -16
  788. package/src/plugins/fonts.ts +225 -660
  789. package/src/plugins/mdx.ts +47 -10
  790. package/src/plugins/prebuilt-capture.ts +217 -0
  791. package/src/plugins/prebuilt-options-analysis.ts +175 -0
  792. package/src/plugins/prebuilt.ts +655 -0
  793. package/src/plugins/prerender-sugar.ts +328 -0
  794. package/src/plugins/request-dep.ts +458 -0
  795. package/src/plugins/routing.ts +237 -241
  796. package/src/plugins/server-bundle.ts +89 -12
  797. package/src/plugins/shims.ts +241 -64
  798. package/src/plugins/static-build.ts +15 -90
  799. package/src/routing/codegen-shared.ts +115 -0
  800. package/src/routing/codegen-types.ts +65 -0
  801. package/src/routing/codegen.ts +372 -178
  802. package/src/routing/convention-lint.ts +394 -0
  803. package/src/routing/export-detect.ts +304 -0
  804. package/src/routing/file-cache.ts +23 -0
  805. package/src/routing/index.ts +10 -1
  806. package/src/routing/interception.ts +3 -22
  807. package/src/routing/link-codegen.ts +313 -0
  808. package/src/routing/manifest-codegen.ts +287 -0
  809. package/src/routing/scanner.ts +338 -189
  810. package/src/routing/schema-validation.ts +155 -0
  811. package/src/routing/segment-classify.ts +223 -0
  812. package/src/routing/segment-codegen.ts +98 -0
  813. package/src/routing/types.ts +82 -25
  814. package/src/routing/walkers.ts +90 -0
  815. package/src/rsc-runtime/rsc.ts +9 -0
  816. package/src/rsc-runtime/ssr.ts +50 -0
  817. package/src/rsc-runtime/vendor-types.d.ts +7 -0
  818. package/src/schema-bridge.ts +253 -0
  819. package/src/search-params/define.ts +576 -0
  820. package/src/search-params/index.ts +14 -20
  821. package/src/search-params/registry.ts +2 -2
  822. package/src/search-params/wrappers.ts +101 -0
  823. package/src/segment-params/define.ts +249 -0
  824. package/src/segment-params/index.ts +9 -0
  825. package/src/server/access-gate.tsx +111 -34
  826. package/src/server/action-client.ts +120 -29
  827. package/src/server/action-encryption.ts +144 -0
  828. package/src/server/action-handler.ts +123 -33
  829. package/src/server/actions.ts +48 -54
  830. package/src/server/als-registry.ts +137 -20
  831. package/src/server/asset-headers.ts +15 -37
  832. package/src/server/body-limits.ts +10 -2
  833. package/src/server/build-manifest.ts +19 -56
  834. package/src/server/canonicalize.ts +6 -3
  835. package/src/server/coalesce-tick.ts +75 -0
  836. package/src/server/compress.ts +34 -7
  837. package/src/server/cookie-context.ts +484 -0
  838. package/src/server/cookie-parsing.ts +163 -0
  839. package/src/server/csrf.ts +39 -6
  840. package/src/server/default-logger.ts +99 -0
  841. package/src/server/deny-boundary.ts +314 -0
  842. package/src/server/deny-renderer.ts +85 -77
  843. package/src/server/dev-source-map.ts +31 -0
  844. package/src/server/early-hints-sender.ts +3 -2
  845. package/src/server/early-hints.ts +37 -27
  846. package/src/server/error-boundary-wrapper.ts +61 -22
  847. package/src/server/fallback-error.ts +79 -102
  848. package/src/server/flight-injection-state.ts +113 -0
  849. package/src/server/flight-scripts.ts +62 -0
  850. package/src/server/form-data.ts +124 -12
  851. package/src/server/html-injector-core.ts +495 -0
  852. package/src/server/html-injectors.ts +271 -254
  853. package/src/server/index.ts +31 -185
  854. package/src/server/internal.ts +181 -0
  855. package/src/server/logger.ts +72 -36
  856. package/src/server/metadata-routes.ts +205 -24
  857. package/src/server/metadata.ts +21 -0
  858. package/src/server/middleware-runner.ts +31 -4
  859. package/src/server/node-stream-transforms.ts +336 -0
  860. package/src/server/param-coercion.ts +207 -0
  861. package/src/server/pipeline-helpers.ts +204 -0
  862. package/src/server/pipeline-interception.ts +45 -18
  863. package/src/server/pipeline-metadata.ts +14 -0
  864. package/src/server/pipeline-outcome.ts +197 -0
  865. package/src/server/pipeline-phases.ts +545 -0
  866. package/src/server/pipeline.ts +274 -382
  867. package/src/server/port-resolution.ts +215 -0
  868. package/src/server/prebuilt/cache-key.ts +298 -0
  869. package/src/server/prebuilt/capture-state.ts +89 -0
  870. package/src/server/prebuilt/key-discipline.ts +53 -0
  871. package/src/server/prebuilt/manifest-tag-index.ts +46 -0
  872. package/src/server/prebuilt/overlay.ts +256 -0
  873. package/src/server/prebuilt/payload-source.ts +201 -0
  874. package/src/server/prebuilt/slots.ts +190 -0
  875. package/src/server/prebuilt/synthetic-store.ts +121 -0
  876. package/src/server/prebuilt-builder.ts +809 -0
  877. package/src/server/prebuilt-runtime.ts +815 -0
  878. package/src/server/primitives.ts +160 -83
  879. package/src/server/render-timeout.ts +108 -0
  880. package/src/server/render-utils.ts +31 -0
  881. package/src/server/request-context.ts +170 -337
  882. package/src/server/request-dep.ts +37 -0
  883. package/src/server/route-element-builder.ts +699 -295
  884. package/src/server/route-handler.ts +31 -4
  885. package/src/server/route-matcher.ts +158 -277
  886. package/src/server/rsc-entry/action-middleware-runner.ts +167 -0
  887. package/src/server/rsc-entry/api-handler.ts +69 -32
  888. package/src/server/rsc-entry/deny-fallback.ts +92 -0
  889. package/src/server/rsc-entry/error-renderer.ts +306 -89
  890. package/src/server/rsc-entry/helpers.ts +210 -85
  891. package/src/server/rsc-entry/index.ts +332 -332
  892. package/src/server/rsc-entry/render-route.ts +300 -0
  893. package/src/server/rsc-entry/revalidate-renderer.ts +349 -0
  894. package/src/server/rsc-entry/rsc-payload.ts +102 -42
  895. package/src/server/rsc-entry/rsc-stream.ts +93 -13
  896. package/src/server/rsc-entry/ssr-bridge.ts +18 -5
  897. package/src/server/rsc-entry/ssr-renderer.ts +275 -43
  898. package/src/server/rsc-entry/wrap-action-dispatch.ts +186 -0
  899. package/src/server/safe-load.ts +60 -0
  900. package/src/server/sensitive-fields.ts +230 -0
  901. package/src/server/server-only-guard-noop.js +3 -0
  902. package/src/server/sitemap-generator.ts +345 -0
  903. package/src/server/sitemap-handler.ts +157 -0
  904. package/src/server/slot-resolver.ts +574 -250
  905. package/src/server/ssr-bridge-types.ts +124 -0
  906. package/src/server/ssr-entry.ts +206 -86
  907. package/src/server/ssr-render.ts +345 -86
  908. package/src/server/ssr-wrappers.tsx +141 -0
  909. package/src/server/state-tree-diff.ts +177 -30
  910. package/src/server/status-code-resolver.ts +115 -130
  911. package/src/server/stream-utils.ts +288 -0
  912. package/src/server/tracing.ts +126 -14
  913. package/src/server/tree-builder.ts +214 -90
  914. package/src/server/tree-match.ts +262 -0
  915. package/src/server/types.ts +78 -9
  916. package/src/server/utils/escape-html.ts +20 -0
  917. package/src/server/utils/mdx-file.ts +22 -0
  918. package/src/server/version-skew.ts +104 -0
  919. package/src/server/workers-cache-bridge.ts +33 -0
  920. package/src/shared/href-validation.ts +159 -0
  921. package/src/shared/merge-search-params.ts +55 -0
  922. package/src/shared/redirect-type.ts +17 -0
  923. package/src/shims/font-google.ts +1 -1
  924. package/src/shims/font-local.ts +34 -0
  925. package/src/shims/headers.ts +122 -1
  926. package/src/shims/navigation-client.ts +51 -29
  927. package/src/shims/navigation.ts +14 -7
  928. package/src/utils/state-machine.ts +111 -0
  929. package/dist/_chunks/als-registry-B7DbZ2hS.js +0 -41
  930. package/dist/_chunks/als-registry-B7DbZ2hS.js.map +0 -1
  931. package/dist/_chunks/debug-B3Gypr3D.js +0 -108
  932. package/dist/_chunks/debug-B3Gypr3D.js.map +0 -1
  933. package/dist/_chunks/format-RyoGQL74.js +0 -164
  934. package/dist/_chunks/format-RyoGQL74.js.map +0 -1
  935. package/dist/_chunks/interception-BOoWmLUA.js +0 -676
  936. package/dist/_chunks/interception-BOoWmLUA.js.map +0 -1
  937. package/dist/_chunks/metadata-routes-Cjmvi3rQ.js +0 -153
  938. package/dist/_chunks/metadata-routes-Cjmvi3rQ.js.map +0 -1
  939. package/dist/_chunks/request-context-BQUC8PHn.js +0 -330
  940. package/dist/_chunks/request-context-BQUC8PHn.js.map +0 -1
  941. package/dist/_chunks/ssr-data-MjmprTmO.js.map +0 -1
  942. package/dist/_chunks/tracing-CemImE6h.js +0 -187
  943. package/dist/_chunks/tracing-CemImE6h.js.map +0 -1
  944. package/dist/_chunks/use-cookie-DX-l1_5E.js +0 -91
  945. package/dist/_chunks/use-cookie-DX-l1_5E.js.map +0 -1
  946. package/dist/_chunks/use-query-states-D5KaffOK.js.map +0 -1
  947. package/dist/adapters/cloudflare.js.map +0 -1
  948. package/dist/cache/index.js.map +0 -1
  949. package/dist/cache/register-cached-function.d.ts +0 -17
  950. package/dist/cache/register-cached-function.d.ts.map +0 -1
  951. package/dist/client/browser-entry.d.ts +0 -21
  952. package/dist/client/browser-entry.d.ts.map +0 -1
  953. package/dist/client/head.d.ts +0 -16
  954. package/dist/client/head.d.ts.map +0 -1
  955. package/dist/client/link-status-provider.d.ts +0 -11
  956. package/dist/client/link-status-provider.d.ts.map +0 -1
  957. package/dist/client/segment-merger.d.ts +0 -119
  958. package/dist/client/segment-merger.d.ts.map +0 -1
  959. package/dist/client/stale-reload.d.ts +0 -44
  960. package/dist/client/stale-reload.d.ts.map +0 -1
  961. package/dist/client/transition-root.d.ts +0 -74
  962. package/dist/client/transition-root.d.ts.map +0 -1
  963. package/dist/client/use-navigation-pending.d.ts +0 -26
  964. package/dist/client/use-navigation-pending.d.ts.map +0 -1
  965. package/dist/client/use-params.d.ts.map +0 -1
  966. package/dist/plugins/cache-transform.d.ts +0 -36
  967. package/dist/plugins/cache-transform.d.ts.map +0 -1
  968. package/dist/plugins/dev-error-overlay.d.ts +0 -60
  969. package/dist/plugins/dev-error-overlay.d.ts.map +0 -1
  970. package/dist/plugins/dev-logs.d.ts.map +0 -1
  971. package/dist/plugins/dynamic-transform.d.ts +0 -72
  972. package/dist/plugins/dynamic-transform.d.ts.map +0 -1
  973. package/dist/plugins/server-action-exports.d.ts +0 -26
  974. package/dist/plugins/server-action-exports.d.ts.map +0 -1
  975. package/dist/routing/status-file-lint.d.ts +0 -33
  976. package/dist/routing/status-file-lint.d.ts.map +0 -1
  977. package/dist/search-params/analyze.d.ts +0 -54
  978. package/dist/search-params/analyze.d.ts.map +0 -1
  979. package/dist/search-params/builtin-codecs.d.ts +0 -105
  980. package/dist/search-params/builtin-codecs.d.ts.map +0 -1
  981. package/dist/search-params/codecs.d.ts +0 -53
  982. package/dist/search-params/codecs.d.ts.map +0 -1
  983. package/dist/search-params/create.d.ts +0 -106
  984. package/dist/search-params/create.d.ts.map +0 -1
  985. package/dist/server/client-module-map.d.ts +0 -47
  986. package/dist/server/client-module-map.d.ts.map +0 -1
  987. package/dist/server/dev-fetch-instrumentation.d.ts +0 -22
  988. package/dist/server/dev-fetch-instrumentation.d.ts.map +0 -1
  989. package/dist/server/dev-logger.d.ts.map +0 -1
  990. package/dist/server/dev-span-processor.d.ts +0 -29
  991. package/dist/server/dev-span-processor.d.ts.map +0 -1
  992. package/dist/server/dev-warnings.d.ts +0 -129
  993. package/dist/server/dev-warnings.d.ts.map +0 -1
  994. package/dist/server/flush.d.ts +0 -74
  995. package/dist/server/flush.d.ts.map +0 -1
  996. package/dist/server/manifest-status-resolver.d.ts +0 -58
  997. package/dist/server/manifest-status-resolver.d.ts.map +0 -1
  998. package/dist/server/prerender.d.ts +0 -77
  999. package/dist/server/prerender.d.ts.map +0 -1
  1000. package/dist/utils/directive-parser.d.ts +0 -70
  1001. package/dist/utils/directive-parser.d.ts.map +0 -1
  1002. package/src/cache/register-cached-function.ts +0 -103
  1003. package/src/client/browser-entry.ts +0 -678
  1004. package/src/client/head.ts +0 -61
  1005. package/src/client/link-status-provider.tsx +0 -30
  1006. package/src/client/segment-merger.ts +0 -339
  1007. package/src/client/stale-reload.ts +0 -87
  1008. package/src/client/transition-root.tsx +0 -166
  1009. package/src/client/use-navigation-pending.ts +0 -38
  1010. package/src/plugins/cache-transform.ts +0 -199
  1011. package/src/plugins/dev-error-overlay.ts +0 -230
  1012. package/src/plugins/dynamic-transform.ts +0 -161
  1013. package/src/plugins/server-action-exports.ts +0 -220
  1014. package/src/routing/status-file-lint.ts +0 -112
  1015. package/src/search-params/analyze.ts +0 -192
  1016. package/src/search-params/builtin-codecs.ts +0 -228
  1017. package/src/search-params/codecs.ts +0 -153
  1018. package/src/search-params/create.ts +0 -321
  1019. package/src/server/client-module-map.ts +0 -58
  1020. package/src/server/dev-fetch-instrumentation.ts +0 -96
  1021. package/src/server/dev-span-processor.ts +0 -78
  1022. package/src/server/dev-warnings.ts +0 -283
  1023. package/src/server/flush.ts +0 -182
  1024. package/src/server/manifest-status-resolver.ts +0 -215
  1025. package/src/server/prerender.ts +0 -139
  1026. package/src/utils/directive-parser.ts +0 -529
@@ -0,0 +1 @@
1
+ {"version":3,"file":"walkers-BtTlKviE.js","names":[],"sources":["../../src/routing/codegen-shared.ts","../../src/routing/file-cache.ts","../../src/routing/export-detect.ts","../../src/routing/link-codegen.ts","../../src/routing/codegen.ts","../../src/routing/schema-validation.ts","../../src/routing/interception.ts","../../src/routing/walkers.ts"],"sourcesContent":["/**\n * Shared codegen helpers — import-path computation, codec chain type\n * builder, and searchParams type formatter.\n *\n * Extracted from `codegen.ts` so `link-codegen.ts` can use the same\n * helpers without a cyclic import.\n */\n\nimport { relative, posix } from 'node:path';\nimport type { ParamEntry, RouteEntry } from './codegen-types.js';\n\n/**\n * Compute a relative import specifier for a codec/page file, stripping\n * the .ts/.tsx extension and resolving against the codegen output dir.\n */\nexport function codecImportPath(codecFilePath: string, importBase: string | undefined): string {\n const absPath = codecFilePath.replace(/\\.(ts|tsx)$/, '');\n if (importBase) {\n return './' + relative(importBase, absPath).replace(/\\\\/g, '/');\n }\n return './' + posix.basename(absPath);\n}\n\n/** Name of the shared helper type emitted at the top of the .d.ts. */\nexport const RESOLVE_SEGMENT_FIELD_TYPE_NAME = '_TimberResolveSegmentField';\n\n/**\n * Helper type emitted once at the top of the generated `.d.ts` and\n * referenced by every codec-chain conditional. Without this shared\n * helper, the inline expansion would duplicate the fallback branch on\n * every step and grow O(2^N) in chain depth (a single deep nested route\n * could blow up the file size and TS performance). With the helper,\n * each step reuses the named type and growth is O(N).\n *\n * The helper is a 2-arg conditional: given a typeof import expression\n * (`Def`), a key (`K`), and a fallback (`F`), it returns `T[K]` if\n * `Def extends ParamsDefinition<T>` and `K extends keyof T`, otherwise\n * `F`. The codec chain composes calls to this helper.\n */\nexport function emitResolveSegmentFieldHelper(): string {\n return [\n `type ${RESOLVE_SEGMENT_FIELD_TYPE_NAME}<Def, K extends string, F> =`,\n ` Def extends import('@timber-js/app/segment-params').ParamsDefinition<infer T>`,\n ` ? K extends keyof T ? T[K] : F`,\n ` : F;`,\n ].join('\\n');\n}\n\n/**\n * Build a TypeScript type expression that resolves a single param's\n * codec by walking a chain of params.ts files in priority order.\n *\n * Each entry in the chain emits one application of the shared\n * `_TimberResolveSegmentField` helper type. Composing N applications\n * grows linearly with chain depth (O(N) characters), unlike an inline\n * conditional that would duplicate the fallback in each branch and\n * grow O(2^N).\n *\n * The closest match (position 0 in the chain) is checked first; if its\n * `segmentParams` definition declares the key, its inferred type wins.\n * Otherwise we fall through to the next entry, and finally to the\n * provided fallback. See TIM-834.\n */\nexport function buildCodecChainType(\n p: ParamEntry,\n importBase: string | undefined,\n fallback: string\n): string {\n const files = p.codecFilePaths;\n if (!files || files.length === 0) return fallback;\n const key = JSON.stringify(p.name);\n // Compose helper applications inside-out so the closest entry\n // (files[0]) ends up as the OUTERMOST application. Each application\n // adds a constant-size wrapper around the running fallback.\n let inner = fallback;\n for (let i = files.length - 1; i >= 0; i--) {\n const importPath = codecImportPath(files[i], importBase);\n inner = `${RESOLVE_SEGMENT_FIELD_TYPE_NAME}<(typeof import('${importPath}'))['segmentParams'], ${key}, ${inner}>`;\n }\n return inner;\n}\n\n/**\n * Build a TypeScript type expression for a single param using the global\n * schema's InferCodecType. Falls back to the param's base type when\n * schema doesn't declare this param (schemas are opt-in per key).\n *\n * Uses `infer` to extract the codec value rather than direct indexing\n * because TypeScript doesn't narrow index validity inside a conditional\n * type's true branch — `typeof schema.segmentParams[K]` produces TS2538\n * even when the condition proves K is a valid key. In .d.ts files that\n * error is suppressed and the type silently becomes `any`.\n */\nexport function buildSchemaParamType(p: ParamEntry, fallback?: string): string {\n const key = JSON.stringify(p.bracketName);\n const fb = fallback ?? p.type;\n return `typeof schema['segmentParams'] extends Record<${key}, infer V> ? InferCodecType<V> : ${fb}`;\n}\n\n/**\n * Format the searchParams type for a route entry.\n *\n * When a page.tsx (or params.ts) exports searchParams, we reference its\n * inferred type via an import type. The import path is relative to\n * `importBase` (the directory where the .d.ts will be written). When\n * importBase is undefined, falls back to a bare relative path.\n */\nexport function formatSearchParamsType(route: RouteEntry, importBase?: string): string {\n if (route.hasSearchParams && route.searchParamsPagePath) {\n const importPath = codecImportPath(route.searchParamsPagePath, importBase);\n // Extract the type from the named 'searchParams' export of the page module.\n return `(typeof import('${importPath}'))['searchParams'] extends import('@timber-js/app/search-params').SearchParamsDefinition<infer T> ? T : never`;\n }\n return '{}';\n}\n","import { readFileSync, statSync } from 'node:fs';\n\nconst cache = new Map<string, { mtimeMs: number; size: number; content: string }>();\n\n/**\n * Read a file's text content, returning a cached copy when the file\n * hasn't been modified since the last read (checked via mtime + size).\n *\n * Falls back to a fresh read on any stat/read error.\n */\nexport function readFileCached(filePath: string): string {\n try {\n const stat = statSync(filePath);\n const entry = cache.get(filePath);\n if (entry && entry.mtimeMs === stat.mtimeMs && entry.size === stat.size) return entry.content;\n const content = readFileSync(filePath, 'utf-8');\n cache.set(filePath, { mtimeMs: stat.mtimeMs, size: stat.size, content });\n return content;\n } catch {\n cache.delete(filePath);\n return readFileSync(filePath, 'utf-8');\n }\n}\n","/**\n * AST-based export detection for route files.\n *\n * Uses Vite's `parseAst` (backed by oxc) to precisely detect named and\n * default exports, replacing the regex-based approach that was fragile\n * with TypeScript syntax (type exports, `as` aliases, comments, etc.).\n */\n\nimport { existsSync } from 'node:fs';\nimport { parseAst } from 'vite';\nimport { readFileCached } from './file-cache.js';\n\ninterface AstNode {\n type: string;\n exportKind?: string;\n declaration?: AstNode;\n specifiers?: Array<{\n exported?: { name: string };\n local?: { name: string };\n exportKind?: string;\n }>;\n id?: { name: string };\n declarations?: Array<{ id?: { name: string } }>;\n}\n\ninterface ProgramNode {\n body: AstNode[];\n}\n\nfunction tryParse(source: string): ProgramNode | null {\n try {\n return parseAst(source, { lang: 'tsx' }) as unknown as ProgramNode;\n } catch {\n return null;\n }\n}\n\n/**\n * Collect all named export identifiers from a parsed program.\n * Handles: `export function X`, `export const X`, `export { X }`,\n * `export { X } from '...'`, `export { Y as X }`.\n */\nfunction collectNamedExports(program: ProgramNode): Set<string> {\n const names = new Set<string>();\n for (const stmt of program.body) {\n if (stmt.type !== 'ExportNamedDeclaration') continue;\n // Skip `export type ...` declarations — they're erased at runtime\n if (stmt.exportKind === 'type') continue;\n\n if (stmt.declaration) {\n if (stmt.declaration.id?.name) {\n names.add(stmt.declaration.id.name);\n }\n if (stmt.declaration.declarations) {\n for (const decl of stmt.declaration.declarations) {\n if (decl.id?.name) names.add(decl.id.name);\n }\n }\n }\n\n if (stmt.specifiers) {\n for (const spec of stmt.specifiers) {\n // Skip `export { type X }` — per-specifier type exports\n if (spec.exportKind === 'type') continue;\n if (spec.exported?.name && spec.exported.name !== 'default') {\n names.add(spec.exported.name);\n }\n }\n }\n }\n return names;\n}\n\n/**\n * Check whether a program has a default export.\n * Handles: `export default ...`, `export { X as default }`,\n * `export { default } from '...'`.\n */\nfunction hasDefaultExport(program: ProgramNode): boolean {\n for (const stmt of program.body) {\n if (stmt.type === 'ExportDefaultDeclaration') return true;\n if (stmt.type === 'ExportNamedDeclaration' && stmt.specifiers) {\n for (const spec of stmt.specifiers) {\n if (spec.exported?.name === 'default') return true;\n }\n }\n }\n return false;\n}\n\n/**\n * Check whether a program has any bare `export * from '...'` declarations.\n * Excludes `export * as X from '...'` (namespace re-exports) since those\n * create a namespace object, not individual top-level exports.\n */\nfunction hasStarExport(program: ProgramNode): boolean {\n return program.body.some(\n (stmt) =>\n stmt.type === 'ExportAllDeclaration' && !(stmt as any).exported && stmt.exportKind !== 'type'\n );\n}\n\n/**\n * Check if a file exports a specific named export.\n * Returns false if the file doesn't exist or can't be parsed.\n */\nexport function fileHasExport(filePath: string, exportName: string): boolean {\n if (!existsSync(filePath)) return false;\n try {\n const source = readFileCached(filePath);\n const program = tryParse(source);\n if (!program) return false;\n return collectNamedExports(program).has(exportName);\n } catch {\n return false;\n }\n}\n\n/**\n * Check if a file has any of the given named exports.\n * Returns the set of matching export names.\n */\nexport function fileHasAnyExport(filePath: string, exportNames: readonly string[]): Set<string> {\n const matches = new Set<string>();\n try {\n const source = readFileCached(filePath);\n const program = tryParse(source);\n if (!program) return matches;\n const exports = collectNamedExports(program);\n for (const name of exportNames) {\n if (exports.has(name)) matches.add(name);\n }\n } catch {\n // Graceful fallback: return empty set\n }\n return matches;\n}\n\n/**\n * Check if a file has a default export.\n * Returns false if the file doesn't exist or can't be parsed.\n */\nexport function fileHasDefaultExport(filePath: string): boolean {\n if (!existsSync(filePath)) return false;\n try {\n const source = readFileCached(filePath);\n const program = tryParse(source);\n if (!program) return false;\n return hasDefaultExport(program);\n } catch {\n return false;\n }\n}\n\n/**\n * Check if a file has any `export * from '...'` declarations.\n * Returns false if the file doesn't exist or can't be parsed.\n */\nexport function fileHasStarExport(filePath: string): boolean {\n if (!existsSync(filePath)) return false;\n try {\n const source = readFileCached(filePath);\n const program = tryParse(source);\n if (!program) return false;\n return hasStarExport(program);\n } catch {\n return false;\n }\n}\n\n/**\n * Parsed value of `export const prerender` from a route file.\n *\n * - `true` / `false` — literal boolean\n * - `{ ttl?, tags? }` — ISR options object (prerender: true is implied)\n * - `undefined` — no `export const prerender` found\n *\n * See design/45-cache-lifetimes.md §\"Route-Level Static\".\n */\nexport type PrerenderExportValue = boolean | { ttl?: number; tags?: string[] };\n\nfunction extractLiteralValue(node: AstNode): unknown {\n if (!node) return undefined;\n const n = node as any;\n if (n.type === 'Literal') return n.value;\n if (n.type === 'UnaryExpression' && n.operator === '-' && n.argument?.type === 'Literal') {\n return -(n.argument.value as number);\n }\n if (n.type === 'ArrayExpression') {\n const elements = n.elements as AstNode[] | undefined;\n if (!elements) return undefined;\n const result: unknown[] = [];\n for (const el of elements) {\n const v = extractLiteralValue(el);\n if (v === undefined) return undefined;\n result.push(v);\n }\n return result;\n }\n return undefined;\n}\n\nfunction extractObjectLiteral(node: AstNode): Record<string, unknown> | undefined {\n if ((node as any).type !== 'ObjectExpression') return undefined;\n const props = (node as any).properties as AstNode[] | undefined;\n if (!props) return undefined;\n const result: Record<string, unknown> = {};\n for (const prop of props) {\n const p = prop as any;\n if (p.type === 'SpreadElement') return undefined;\n if (p.type !== 'Property' || p.computed) return undefined;\n const key =\n p.key?.type === 'Identifier'\n ? p.key.name\n : p.key?.type === 'Literal'\n ? String(p.key.value)\n : undefined;\n if (!key) return undefined;\n const value = extractLiteralValue(p.value);\n if (value === undefined) return undefined;\n result[key] = value;\n }\n return result;\n}\n\n/**\n * Extract the value of `export const prerender` from a file.\n * Returns undefined if the file doesn't export `prerender` or can't be parsed.\n *\n * Supports:\n * export const prerender = true;\n * export const prerender = false;\n * export const prerender = { ttl: 3600, tags: ['docs'] };\n */\nexport function getPrerenderExport(filePath: string): PrerenderExportValue | undefined {\n if (!existsSync(filePath)) return undefined;\n try {\n const source = readFileCached(filePath);\n const program = tryParse(source);\n if (!program) return undefined;\n\n for (const stmt of program.body) {\n if (stmt.type !== 'ExportNamedDeclaration') continue;\n if (stmt.exportKind === 'type') continue;\n if (!stmt.declaration) continue;\n const decl = stmt.declaration;\n if (decl.type !== 'VariableDeclaration') continue;\n const declarations = decl.declarations as\n | Array<{\n id?: { name?: string };\n init?: AstNode;\n }>\n | undefined;\n if (!declarations) continue;\n for (const d of declarations) {\n if (d.id?.name !== 'prerender' || !d.init) continue;\n const init = d.init as any;\n if (init.type === 'Literal' && typeof init.value === 'boolean') {\n return init.value;\n }\n if (init.type === 'ObjectExpression') {\n const obj = extractObjectLiteral(init);\n if (!obj) return undefined;\n const result: { ttl?: number; tags?: string[] } = {};\n if ('ttl' in obj && typeof obj.ttl === 'number') result.ttl = obj.ttl;\n if (\n 'tags' in obj &&\n Array.isArray(obj.tags) &&\n obj.tags.every((t: unknown) => typeof t === 'string')\n ) {\n result.tags = obj.tags as string[];\n }\n return result;\n }\n return undefined;\n }\n }\n return undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Check if a file starts with a specific directive (e.g. \"use client\").\n * Directives are string literal expression statements at the top of the file.\n */\nexport function fileHasDirective(filePath: string, directive: string): boolean {\n if (!existsSync(filePath)) return false;\n try {\n const source = readFileCached(filePath);\n const program = tryParse(source);\n if (!program) return false;\n for (const stmt of program.body) {\n if (stmt.type !== 'ExpressionStatement') break;\n const expr = (stmt as any).expression;\n if (expr?.type !== 'Literal' || typeof expr.value !== 'string') break;\n if (expr.value === directive) return true;\n }\n return false;\n } catch {\n return false;\n }\n}\n","/**\n * Typed `<Link>` codegen — interface augmentation generation.\n *\n * Extracted from `codegen.ts` to keep that file under the project's\n * 500-line cap. This module owns everything that emits the\n * `interface LinkFunction { ... }` augmentation blocks in the generated\n * `.timber/timber-routes.d.ts`.\n *\n * Two augmentation blocks are emitted:\n *\n * 1. **Per-route discriminated union** (`formatTypedLinkOverloads`) —\n * one call signature whose props is a union keyed on `href`. TS\n * narrows by literal href and reports prop errors against the\n * matched variant. See TIM-835 and `design/09-typescript.md`.\n *\n * 2. **Catch-all overloads** (`formatLinkCatchAllOverloads`) — external\n * href literals (`http://`, `mailto:`, etc.) and a computed-string\n * `<H extends string>` signature for runtime-computed paths.\n *\n * Block ordering is critical for error UX: per-route is emitted FIRST\n * so that, after TS's \"later overload set ordered first\" merge rule,\n * the discriminated union ends up LAST in resolution order — the\n * overload TS reports against on failure.\n */\n\nimport type { ParamEntry, RouteEntry } from './codegen-types.js';\nimport {\n buildCodecChainType,\n buildSchemaParamType,\n formatSearchParamsType,\n} from './codegen-shared.js';\nimport { classifyUrlSegment } from './segment-classify.js';\n\n/** Shared Link base-props type literal used in every emitted call signature. */\nexport const LINK_BASE_PROPS_TYPE =\n \"Omit<import('react').AnchorHTMLAttributes<HTMLAnchorElement>, 'href'> & { prefetch?: boolean; scroll?: boolean; preserveSearchParams?: true | string[]; onNavigate?: import('./client/link.js').OnNavigateHandler; children?: import('react').ReactNode }\";\n\n/**\n * Build a TypeScript template literal pattern for a dynamic route.\n * e.g. '/products/[id]' → '/products/${string}'\n * '/blog/[...slug]' → '/blog/${string}'\n * '/docs/[[...path]]' → '/docs/${string}' (also matches /docs)\n * '/[org]/[repo]' → '/${string}/${string}'\n */\nexport function buildResolvedPattern(route: RouteEntry): string | null {\n const parts = route.urlPath.split('/');\n const templateParts = parts.map((part) => {\n const seg = classifyUrlSegment(part);\n switch (seg.kind) {\n case 'catch-all':\n case 'optional-catch-all':\n // eslint-disable-next-line no-template-curly-in-string -- codegen output\n return '${string}';\n case 'dynamic': {\n const prefix = seg.prefix ?? '';\n const suffix = seg.suffix ?? '';\n // eslint-disable-next-line no-template-curly-in-string -- codegen output\n return `${prefix}\\${string}${suffix}`;\n }\n default:\n return part;\n }\n });\n return templateParts.join('/');\n}\n\n/**\n * Format the segmentParams type for Link overloads.\n *\n * Link params accept `string | number` for single dynamic segments\n * (convenience — values are stringified at runtime). Catch-all and\n * optional catch-all remain `string[]` / `string[] | undefined`.\n *\n * When the segment's params chain (TIM-834) declares a typed codec, the\n * inferred type from the codec wins via a nested conditional.\n */\nexport function formatLinkParamsType(\n params: ParamEntry[],\n importBase?: string,\n hasSchema?: boolean\n): string {\n if (params.length === 0) {\n return '{}';\n }\n\n const fields = params.map((p) => {\n const fallback = p.type === 'string' ? 'string | number' : p.type;\n const codecType = hasSchema\n ? buildSchemaParamType(p, fallback)\n : buildCodecChainType(p, importBase, fallback);\n return `${p.name}: ${codecType}`;\n });\n return `{ ${fields.join('; ')} }`;\n}\n\n/**\n * Catch-all call signatures for `<Link>` — external hrefs and computed\n * `string` variables. Emitted from codegen in a SEPARATE\n * `declare module` block (declared AFTER the per-route block) so the TS\n * \"later overload set ordered first\" rule places these catch-all\n * signatures ahead of per-route in resolution order, leaving per-route\n * as the final overload whose error message is reported on failure.\n *\n * The conditional `string extends H ? ... : never` protection preserves\n * TIM-624's guarantee that unknown internal path literals don't match\n * the catch-all — typos like `<Link href=\"/typo\" />` still error.\n */\nexport function formatLinkCatchAllOverloads(): string[] {\n const lines: string[] = [];\n const baseProps = LINK_BASE_PROPS_TYPE;\n\n // TIM-830: the catch-all signatures accept EITHER the legacy\n // `{ definition, values }` wrapper OR a flat `Record<string, unknown>`\n // values object. External/computed hrefs can't be looked up in the\n // runtime registry, so the wrapped form is still the reliable path;\n // the flat form is kept permissive for callers migrating from typed-\n // route hrefs to computed strings. `resolveHref` discriminates at\n // runtime via the presence of a `definition` key.\n const catchAllSearchParams =\n '{ definition: SearchParamsDefinition<Record<string, unknown>>; values: Record<string, unknown> } | Record<string, unknown>';\n\n // ExternalHref inlined here rather than referenced as an exported\n // alias so the generated .d.ts stands alone without source imports.\n /* eslint-disable no-template-curly-in-string -- codegen output */\n const externalHref =\n '`http://${string}` | `https://${string}` | `mailto:${string}` | `tel:${string}` | `ftp://${string}` | `//${string}` | `#${string}` | `?${string}`';\n /* eslint-enable no-template-curly-in-string */\n\n lines.push(' // Typed Link overloads — catch-all (block 2 / emitted second)');\n lines.push(' interface LinkFunction {');\n\n // (1) External/literal-protocol hrefs.\n //\n // TIM-833: `segmentParams` is permissively typed as\n // `Record<string, unknown>` (not `never`) so generic wrappers that\n // forward a `LinkProps`-shaped object can compile when the wrapper\n // happens to bottom out at an external href. There are no dynamic\n // segments to interpolate for an external href, so this prop is\n // ignored at runtime — accepting an open-shape object instead of\n // forbidding it removes a footgun without changing behavior.\n lines.push(` (props: ${baseProps} & {`);\n lines.push(` href: ${externalHref}`);\n lines.push(` segmentParams?: Record<string, unknown>`);\n lines.push(` searchParams?: ${catchAllSearchParams}`);\n lines.push(` }): import('react').JSX.Element`);\n\n // (2) Computed/variable href — non-literal `string` only.\n //\n // `string extends H` is true only when H is the wide `string` type,\n // not a specific literal. For literal hrefs, this overload must NOT\n // be selectable so the per-route discriminated union (block 1) is\n // the resolution target.\n //\n // TIM-833 follow-up: the previous shape used `string extends H ? {...} : never`\n // on the WHOLE props type. For literal H, that collapsed `props` to\n // `never`, and JSX type inference then read `(never).children` as\n // `never` — producing the misleading\n // `'children' prop expects type 'never' which requires multiple\n // children, but only a single child was provided` (TS2745) error,\n // which buried the actual prop-mismatch message under a noise diagnostic.\n //\n // Fix: move the `: never` from the whole props onto just the `href`\n // field. The overload remains uncallable for literal H (since `\"/x\"`\n // is not assignable to `never`), but `children` retains its real\n // `ReactNode` type so JSX inference no longer collapses to never.\n // The diagnostic surface becomes: TS reports the per-route block's\n // error chain (the helpful \"Type 'number' is not assignable to type\n // 'string'\" message) WITHOUT a leading TS2745 noise line.\n lines.push(` <H extends string>(`);\n lines.push(` props: ${baseProps} & {`);\n lines.push(` href: string extends H ? H : never`);\n lines.push(` segmentParams?: Record<string, string | number | string[]>`);\n lines.push(` searchParams?: ${catchAllSearchParams}`);\n lines.push(` }`);\n lines.push(` ): import('react').JSX.Element`);\n\n lines.push(' }');\n return lines;\n}\n\n/**\n * Generate typed per-route Link call signatures via LinkFunction\n * interface merging.\n *\n * TIM-835: This emits a SINGLE call signature whose props is a\n * discriminated union keyed on `href`. TypeScript narrows the union by\n * the literal `href` at the call site, then checks the rest of the\n * props against the matched variant. When `segmentParams` or\n * `searchParams` is wrong, TS reports the error against the matched\n * variant — naming the user's actual `href` and the offending field.\n *\n * Before TIM-835, this function emitted N separate per-route overloads\n * (one per route, sometimes two for dynamic routes). When ALL overloads\n * failed, TS would pick an arbitrary failed overload (heuristically the\n * \"last tried\") to render the diagnostic, often pointing at a route\n * completely unrelated to the one the user wrote. The discriminated\n * union sidesteps overload-resolution heuristics entirely.\n *\n * Open property shapes (`Record<string, unknown>` instead of `never`)\n * for `segmentParams` on routes that don't declare them keep generic\n * `LinkProps`-spreading wrappers compiling. (Aligned with TIM-833.)\n *\n * TIM-832: this function still emits the per-route block FIRST and the\n * catch-all block follows, so per-route remains the LAST overload set in\n * resolution order — the one TS reports against on failure. With a\n * discriminated union there is only one call signature in this block,\n * so the resolved-template-vs-pattern ordering reduces to placing the\n * pattern variant before the resolved-template variant inside the union.\n */\nexport function formatTypedLinkOverloads(\n routes: RouteEntry[],\n importBase?: string,\n hasSchema?: boolean\n): string[] {\n const lines: string[] = [];\n const baseProps = LINK_BASE_PROPS_TYPE;\n\n // Build the union variants. Each route contributes one variant for the\n // pattern href (e.g. '/products/[id]') and, for dynamic routes, an\n // additional variant for the resolved-template href (e.g.\n // `/products/${string}`).\n //\n // The PATTERN variant must be listed BEFORE the resolved-template\n // variant for the same route so that when the user writes the literal\n // pattern href (`<Link href=\"/products/[id]\" />`), TS narrows to the\n // pattern variant (which carries the typed `segmentParams` shape)\n // rather than the looser resolved-template variant. Without this\n // ordering, TS would silently match the resolved-template variant\n // first — swallowing typed-segmentParams type errors.\n const variants: string[] = [];\n for (const route of routes) {\n const hasDynamicParams = route.params.length > 0;\n // For routes with no dynamic params, accept an absent OR open-shape\n // segmentParams. `Record<string, unknown>` keeps generic spreads\n // compiling and gives a readable error if a non-object is passed.\n const paramsProp = hasDynamicParams\n ? `segmentParams: ${formatLinkParamsType(route.params, importBase, hasSchema)}`\n : 'segmentParams?: Record<string, unknown>';\n\n const searchParamsType = route.hasSearchParams\n ? formatSearchParamsType(route, importBase)\n : null;\n // TIM-830: pattern href uses the FLAT `Partial<T>` shape — the\n // runtime registry is keyed by the un-interpolated pattern.\n //\n // TIM-833: when the route has NO searchParams definition, use\n // `Record<string, unknown>` (open shape) instead of\n // `Record<string, never>` so generic `LinkProps`-spreading wrappers\n // compile. The trade-off vs the original TIM-835 strict shape is\n // that excess searchParams keys on a no-def route no longer raise\n // a type error — but those keys are runtime no-ops anyway, and\n // wrapper compatibility is the more common pain point. Routes WITH\n // a searchParams definition still get strict `Partial<T>` typing.\n const patternSearchParamsProp = searchParamsType\n ? `searchParams?: Partial<${searchParamsType}>`\n : 'searchParams?: Record<string, unknown>';\n\n // Pattern variant FIRST (more specific).\n variants.push(\n `${baseProps} & { href: '${route.urlPath}'; ${paramsProp}; ${patternSearchParamsProp} }`\n );\n\n // Resolved-template variant SECOND (looser, matches interpolated hrefs).\n if (hasDynamicParams) {\n const templatePattern = buildResolvedPattern(route);\n if (templatePattern) {\n // TIM-830: resolved-template href keeps the WRAPPED\n // `{ definition, values }` shape — the registry can't be looked\n // up by an already-interpolated href.\n //\n // TIM-833: searchParams falls back to `Record<string, unknown>`\n // (was `Record<string, never>`) when the route has no\n // definition, mirroring the pattern-variant change above. The\n // resolved-template `segmentParams` is intentionally KEPT as\n // `Record<string, never>` below to preserve TIM-835's\n // pattern-variant typo detection: loosening segmentParams here\n // would let the resolved-template variant shadow the pattern\n // variant on literal pattern hrefs and silently swallow keyed\n // typos like `<Link href=\"/[id]\" segmentParams={{ idz: 1 }} />`.\n const resolvedSearchParamsProp = searchParamsType\n ? `searchParams?: { definition: SearchParamsDefinition<${searchParamsType}>; values: Partial<${searchParamsType}> }`\n : 'searchParams?: Record<string, unknown>';\n // TIM-835: `Record<string, never>` for segmentParams forbids ANY\n // provided keys on the resolved-template variant. Without this,\n // the resolved-template would shadow the pattern variant for\n // literal pattern hrefs (`<Link href=\"/products/[id]\" segmentParams={...} />`)\n // because both variants accept the literal `'/products/[id]'`\n // and the looser variant would silently swallow segmentParams\n // type errors.\n variants.push(\n `${baseProps} & { href: \\`${templatePattern}\\`; segmentParams?: Record<string, never>; ${resolvedSearchParamsProp} }`\n );\n }\n }\n }\n\n lines.push(' interface LinkFunction {');\n if (variants.length === 0) {\n // No page routes — emit nothing. The catch-all block in the second\n // augmentation still provides external/computed-string signatures.\n lines.push(' }');\n return lines;\n }\n lines.push(' (');\n lines.push(' props:');\n for (const variant of variants) {\n lines.push(` | (${variant})`);\n }\n lines.push(` ): import('react').JSX.Element`);\n lines.push(' }');\n\n return lines;\n}\n","/**\n * Route map codegen.\n *\n * Walks the scanned RouteTree and generates a TypeScript declaration file\n * mapping every route to its params and searchParams shapes.\n *\n * This runs at build time and in dev (regenerated on file changes).\n * No runtime overhead — purely static type generation.\n */\n\nimport { existsSync } from 'node:fs';\nimport { join, relative } from 'node:path';\nimport type { RouteTree, SegmentNode } from './types.js';\nimport type { ParamEntry, RouteEntry } from './codegen-types.js';\nimport {\n buildCodecChainType,\n buildSchemaParamType,\n emitResolveSegmentFieldHelper,\n formatSearchParamsType,\n} from './codegen-shared.js';\nimport { fileHasExport } from './export-detect.js';\nimport { formatLinkCatchAllOverloads, formatTypedLinkOverloads } from './link-codegen.js';\n\n/** Options for route map generation. */\nexport interface CodegenOptions {\n /** Absolute path to the app/ directory. Required for page searchParams detection. */\n appDir?: string;\n /**\n * Absolute path to the directory where the .d.ts file will be written.\n * Used to compute correct relative import paths for page files.\n * Defaults to appDir when not provided (preserves backward compat for tests).\n */\n outputDir?: string;\n /**\n * Whether a global schema (app/schema.ts) exists.\n * Auto-detected from appDir when not explicitly set.\n */\n hasSchema?: boolean;\n}\n\n/**\n * Generate a TypeScript declaration file string from a scanned route tree.\n *\n * The output is a `declare module '@timber-js/app'` block containing the Routes\n * interface that maps every route path to its params and searchParams shape.\n */\nexport function generateRouteMap(tree: RouteTree, options: CodegenOptions = {}): string {\n // Auto-detect schema from appDir when not explicitly set\n const hasSchema = options.hasSchema ?? detectSchema(options.appDir);\n\n const routes: RouteEntry[] = [];\n collectRoutes(tree.root, [], [], '', routes, hasSchema, false);\n\n // Sort routes alphabetically for deterministic output\n routes.sort((a, b) => a.urlPath.localeCompare(b.urlPath));\n\n // When outputDir differs from appDir, import paths must be relative to outputDir\n const importBase = options.outputDir ?? options.appDir;\n\n return formatDeclarationFile(routes, importBase, hasSchema, options.appDir);\n}\n\n/** Schema file extensions to check, in priority order. */\nconst SCHEMA_EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx'];\n\n/**\n * Detect whether app/schema.{ts,tsx,js,jsx} exists.\n */\nfunction detectSchema(appDir: string | undefined): boolean {\n if (!appDir) return false;\n return SCHEMA_EXTENSIONS.some((ext) => existsSync(join(appDir, `schema${ext}`)));\n}\n\n/**\n * Recursively walk the segment tree and collect route entries.\n *\n * A route entry is created for any segment that has a `page` or `route` file.\n * Params accumulate from ancestor dynamic segments.\n */\nfunction collectRoutes(\n node: SegmentNode,\n ancestorParams: ParamEntry[],\n ancestorParamsFiles: string[],\n parentTreePath: string,\n routes: RouteEntry[],\n hasSchema: boolean,\n insideSlot: boolean\n): void {\n // Build the tree path (includes groups, slots — uniquely identifies this segment).\n // Root node has empty segmentName, producing treePath = ''.\n const treePath = node.segmentName ? `${parentTreePath}/${node.segmentName}` : parentTreePath;\n // TIM-834: Identify this segment's own params.ts (if it has a\n // segmentParams export). The full chain of params.ts files in the\n // route ancestry is threaded down via `ancestorParamsFiles`; codec\n // resolution for each ParamEntry is deferred until leaf time so that\n // descendant params.ts files can override ancestor codecs (closest-\n // to-leaf wins, matching the runtime semantics of\n // coerceSegmentParams which walks segments top-down and overwrites\n // earlier coercions).\n const ownParamsFile =\n node.params && fileHasExport(node.params.filePath, 'segmentParams')\n ? node.params.filePath\n : undefined;\n\n // Accumulate params from this segment. We attach `codecFilePaths`\n // later (at leaf time) using the FULL chain so descendant overrides\n // are visible. The legacy layout/page fallback is recorded now\n // because it is per-segment (and does not participate in inheritance).\n const params = [...ancestorParams];\n if (node.paramName) {\n const legacyFallback = ownParamsFile ? undefined : findLegacyParamsExport(node);\n params.push({\n name: node.paramName,\n bracketName: bracketNameForSegment(node),\n type: paramTypeForSegment(node.segmentType),\n // Codec chain populated at leaf time. We carry the per-segment\n // legacy fallback (if any) so leaf-time resolution can fall back\n // to it when no params.ts in the chain declares this key.\n legacyCodecFilePath: legacyFallback,\n });\n }\n\n // Extend the chain for descendants of this segment.\n const nextAncestorFiles = ownParamsFile\n ? [...ancestorParamsFiles, ownParamsFile]\n : ancestorParamsFiles;\n\n // Check if this segment is a leaf route (has page or route file)\n const isPage = !!node.page;\n const isApiRoute = !!node.route;\n\n if (isPage || isApiRoute) {\n // TIM-834 P1 fix: at LEAF time, the full chain of params.ts files\n // (root-to-leaf) is known. Resolve every ParamEntry's\n // `codecFilePaths` to the chain in LEAF-FIRST order so the\n // closest-to-leaf entry is checked first — matching runtime\n // closest-wins semantics. The chain is shared by all params in the\n // route, so we compute it once.\n const leafFirstChain = nextAncestorFiles.length > 0 ? [...nextAncestorFiles].reverse() : [];\n const resolvedParams: ParamEntry[] = params.map((p) => {\n const codecFilePaths =\n leafFirstChain.length > 0\n ? leafFirstChain\n : p.legacyCodecFilePath\n ? [p.legacyCodecFilePath]\n : undefined;\n return {\n name: p.name,\n bracketName: p.bracketName,\n type: p.type,\n codecFilePaths,\n };\n });\n\n const entry: RouteEntry = {\n urlPath: node.urlPath,\n segmentPath: treePath || '/',\n params: resolvedParams,\n hasSearchParams: false,\n isApiRoute,\n isSlotRoute: insideSlot,\n hasSchema,\n };\n\n // Detect searchParams export from params.ts (primary) or page.tsx (fallback)\n if (isPage) {\n if (node.params && fileHasExport(node.params.filePath, 'searchParams')) {\n entry.hasSearchParams = true;\n entry.searchParamsPagePath = node.params.filePath;\n } else if (node.page && fileHasExport(node.page.filePath, 'searchParams')) {\n entry.hasSearchParams = true;\n entry.searchParamsPagePath = node.page.filePath;\n }\n }\n\n routes.push(entry);\n }\n\n // Recurse into children\n for (const child of node.children) {\n collectRoutes(child, params, nextAncestorFiles, treePath, routes, hasSchema, insideSlot);\n }\n\n // Recurse into slots (they share the parent's URL path, but may have their own pages)\n for (const slot of Object.values(node.slots)) {\n collectRoutes(slot, params, nextAncestorFiles, treePath, routes, hasSchema, true);\n }\n}\n\n/**\n * Dedupe route entries by urlPath for urlPath-keyed emissions (the Routes\n * interface, useQueryStates overloads, and typed Link variants).\n *\n * Parallel-slot pages share their parent's urlPath; emitting one entry per\n * slot page produced duplicate interface keys (TS2300/TS2717 under\n * skipLibCheck:false) and duplicate overloads. The non-slot entry is the\n * canonical one; when only slot entries exist (parent has no page), the\n * lexicographically smallest segmentPath wins so output is independent of\n * slot scan order. A slot's searchParams definition is carried onto the\n * merged entry when the canonical entry has none — never silently dropped.\n *\n * segmentPath-keyed emissions (getSegmentParams, useSegmentParams,\n * TimberSegmentParams) must NOT use this — segmentPaths are already unique\n * and slot entries feed those APIs directly.\n */\nfunction dedupeRoutesByUrlPath(routes: RouteEntry[]): RouteEntry[] {\n const byPath = new Map<string, RouteEntry>();\n for (const route of routes) {\n const existing = byPath.get(route.urlPath);\n if (!existing) {\n byPath.set(route.urlPath, route);\n continue;\n }\n\n let winner = existing;\n let loser = route;\n const routeWins =\n (existing.isSlotRoute && !route.isSlotRoute) ||\n (!!existing.isSlotRoute === !!route.isSlotRoute &&\n route.segmentPath.localeCompare(existing.segmentPath) < 0);\n if (routeWins) {\n winner = route;\n loser = existing;\n }\n\n if (!winner.hasSearchParams && loser.hasSearchParams) {\n winner = {\n ...winner,\n hasSearchParams: true,\n searchParamsPagePath: loser.searchParamsPagePath,\n };\n }\n byPath.set(route.urlPath, winner);\n }\n return [...byPath.values()];\n}\n\n/**\n * Determine the TypeScript type for a segment's param.\n */\n/**\n * Derive the bracket key for schema/codegen lookup.\n * For bare segments like `[id]` this is the segmentName itself.\n * For affixed segments like `img-[id].png` this is `[id]` — the bare bracket form.\n */\nfunction bracketNameForSegment(node: SegmentNode): string {\n if (node.paramPrefix || node.paramSuffix) {\n return `[${node.paramName}]`;\n }\n return node.segmentName;\n}\n\nfunction paramTypeForSegment(segmentType: string): ParamEntry['type'] {\n switch (segmentType) {\n case 'catch-all':\n return 'string[]';\n case 'optional-catch-all':\n return 'string[] | undefined';\n default:\n return 'string';\n }\n}\n\n/**\n * Find a legacy `segmentParams` export on layout.tsx or page.tsx.\n *\n * Backward-compat shim: TIM-508 made params.ts the canonical location\n * for `segmentParams`. Layout/page exports are still accepted for the\n * OWN segment only (not inherited by descendants — see TIM-834).\n */\nfunction findLegacyParamsExport(node: SegmentNode): string | undefined {\n if (node.layout && fileHasExport(node.layout.filePath, 'segmentParams')) {\n return node.layout.filePath;\n }\n if (node.page && fileHasExport(node.page.filePath, 'segmentParams')) {\n return node.page.filePath;\n }\n return undefined;\n}\n\n/**\n * Emit the schema-based type exports: TimberSegmentParams, TimberRoute,\n * AllSegmentParams, RoutesWithParams.\n *\n * These types use InferCodecType references so they stay in sync with\n * the schema without hardcoding resolved types.\n *\n * Design doc: design/41-global-params.md §Codegen Output\n */\nfunction formatSchemaTypes(routes: RouteEntry[]): string[] {\n const lines: string[] = [];\n\n lines.push('/** Union of all valid route patterns. */');\n lines.push('export type TimberRoute = keyof TimberSegmentParams;');\n lines.push('');\n lines.push('/** Maps each segment path to its accumulated segment params. */');\n lines.push('export interface TimberSegmentParams {');\n\n for (const route of routes) {\n if (route.params.length === 0) {\n lines.push(` '${route.segmentPath}': {};`);\n } else {\n lines.push(` '${route.segmentPath}': {`);\n for (const p of route.params) {\n lines.push(` ${p.name}: ${buildSchemaParamType(p)};`);\n }\n lines.push(' };');\n }\n }\n\n lines.push('}');\n lines.push('');\n\n // AllSegmentParams — flat union of all param types across all routes\n lines.push('/** All segment params (union of all route params). */');\n lines.push('export type AllSegmentParams = {');\n lines.push(\n ' [K in keyof TimberSegmentParams as TimberSegmentParams[K] extends Record<string, never>'\n );\n lines.push(' ? never');\n lines.push(' : K]: TimberSegmentParams[K];');\n lines.push('} extends infer U');\n lines.push(' ? { [K in keyof U[keyof U]]: U[keyof U][K] }');\n lines.push(' : never;');\n lines.push('');\n\n // RoutesWithParams — filter routes by required param keys\n lines.push(\n '/** Filters TimberRoute to routes whose accumulated params include all listed keys. */'\n );\n lines.push('export type RoutesWithParams<K extends keyof AllSegmentParams> = {');\n lines.push(' [R in TimberRoute]: K extends keyof TimberSegmentParams[R] ? R : never;');\n lines.push('}[TimberRoute];');\n\n return lines;\n}\n\n/**\n * Format the collected routes into a TypeScript declaration file.\n */\nfunction formatDeclarationFile(\n routes: RouteEntry[],\n importBase?: string,\n hasSchema?: boolean,\n appDir?: string\n): string {\n const lines: string[] = [];\n\n lines.push('// This file is auto-generated by timber.js route map codegen.');\n lines.push('// Do not edit manually. Regenerated on build and in dev mode.');\n lines.push('');\n // export {} makes this file a module, so all declare module blocks are\n // augmentations rather than ambient replacements. Without this, the\n // declare module blocks would replace the original module types entirely\n // (removing exports like bindUseQueryStates that aren't listed here).\n lines.push('export {};');\n lines.push('');\n\n if (hasSchema) {\n // Schema-based codegen: import schema and InferCodecType\n // Compute the schema import path relative to the output directory\n const schemaImport =\n appDir && importBase\n ? './' + relative(importBase, join(appDir, 'schema')).replace(/\\\\/g, '/')\n : '../app/schema';\n lines.push(`import type schema from '${schemaImport}';`);\n lines.push(\"import type { InferCodecType, SegmentParamCodec } from '@timber-js/app/params';\");\n lines.push('');\n // Collect all unique bracket keys from routes for key validation\n const allBracketKeys = new Set<string>();\n for (const route of routes) {\n for (const p of route.params) {\n allBracketKeys.add(p.bracketName);\n }\n }\n\n // Augment the ValidDynamicSegmentKeysRegistry so defineSchema constrains keys\n // to known filesystem segments. Unknown keys produce inline TS errors.\n if (allBracketKeys.size > 0) {\n lines.push(\"declare module '@timber-js/app/params' {\");\n lines.push(' interface ValidDynamicSegmentKeysRegistry {');\n for (const key of [...allBracketKeys].sort()) {\n lines.push(` ${JSON.stringify(key)}: true;`);\n }\n lines.push(' }');\n lines.push('}');\n lines.push('');\n }\n // Type-level validation: each schema value must be a Codec or Standard Schema.\n // Running `pnpm run typecheck` will surface errors for invalid values.\n lines.push('type _AssertSchemaValues = {');\n lines.push(\n \" [K in keyof typeof schema['segmentParams']]: typeof schema['segmentParams'][K] extends SegmentParamCodec ? true : ['Error: value for', K, 'is not a valid Codec or Standard Schema'];\"\n );\n lines.push('};');\n // Generic constraint enforces that all values are `true` — if any value is\n // an error tuple, TS reports a real diagnostic instead of silently computing it.\n lines.push(\n 'type _EnforceSchemaValues<_T extends Record<string, true> = _AssertSchemaValues> = true;'\n );\n lines.push('');\n }\n\n if (!hasSchema) {\n // TIM-834 P2: emit the shared codec-resolution helper type ONCE so the\n // per-param chain conditionals reference it instead of inlining the\n // fallback in both branches (which grows O(2^N) in chain depth).\n lines.push(emitResolveSegmentFieldHelper());\n lines.push('');\n }\n\n // urlPath-keyed emissions use the deduped list (slot pages share their\n // parent's urlPath); segmentPath-keyed emissions below keep all entries.\n const uniqueByUrlPath = dedupeRoutesByUrlPath(routes);\n\n lines.push(\"declare module '@timber-js/app' {\");\n lines.push(' interface Routes {');\n\n for (const route of uniqueByUrlPath) {\n const paramsType = formatParamsType(route.params, importBase, hasSchema);\n const searchParamsType = formatSearchParamsType(route, importBase);\n\n lines.push(` '${route.urlPath}': {`);\n lines.push(` segmentParams: ${paramsType}`);\n lines.push(` searchParams: ${searchParamsType}`);\n lines.push(` }`);\n }\n\n lines.push(' }');\n\n // When a global schema exists, emit segment param types inside the\n // @timber-js/app module augmentation so that declare module blocks\n // for @timber-js/app/server and @timber-js/app/client can reference\n // AllSegmentParams via `import type { AllSegmentParams } from '@timber-js/app'`.\n if (hasSchema) {\n lines.push('');\n lines.push(...formatSchemaTypes(routes).map((l) => ` ${l}`));\n }\n\n lines.push('}');\n lines.push('');\n\n // useQueryStates + typed Link are urlPath-keyed → deduped list.\n const pageRoutes = uniqueByUrlPath.filter((r) => !r.isApiRoute);\n // getSegmentParams / useSegmentParams are segmentPath-keyed → full list,\n // so slot segments keep their own typed overloads.\n const dynamicRoutes = routes.filter((r) => r.params.length > 0);\n\n // Generate @timber-js/app/server augmentation — typed getSegmentParams\n if (dynamicRoutes.length > 0) {\n lines.push(\"declare module '@timber-js/app/server' {\");\n if (hasSchema) {\n lines.push(\" import type { AllSegmentParams } from '@timber-js/app'\");\n }\n for (const route of dynamicRoutes) {\n const paramsType = formatParamsType(route.params, importBase, hasSchema);\n lines.push(\n ` export function getSegmentParams(segmentPath: '${route.segmentPath}'): ${paramsType}`\n );\n }\n lines.push(\n hasSchema\n ? ' export function getSegmentParams(): Partial<AllSegmentParams>'\n : ' export function getSegmentParams(): Record<string, string | string[]>'\n );\n lines.push('}');\n lines.push('');\n }\n\n // Generate overloads for @timber-js/app/client\n\n if (dynamicRoutes.length > 0 || pageRoutes.length > 0) {\n lines.push(\"declare module '@timber-js/app/client' {\");\n lines.push(\n \" import type { SearchParamsDefinition, SetParams, QueryStatesOptions, SearchParamCodec } from '@timber-js/app/search-params'\"\n );\n if (hasSchema) {\n lines.push(\" import type { AllSegmentParams } from '@timber-js/app'\");\n }\n lines.push('');\n\n // useSegmentParams overloads\n if (dynamicRoutes.length > 0) {\n for (const route of dynamicRoutes) {\n const paramsType = formatParamsType(route.params, importBase, hasSchema);\n lines.push(\n ` export function useSegmentParams(segmentPath: '${route.segmentPath}'): ${paramsType}`\n );\n }\n lines.push(\n hasSchema\n ? ' export function useSegmentParams(): Partial<AllSegmentParams>'\n : ' export function useSegmentParams(): Record<string, string | string[]>'\n );\n lines.push('');\n }\n\n // useQueryStates overloads\n if (pageRoutes.length > 0) {\n lines.push(...formatUseQueryStatesOverloads(pageRoutes, importBase));\n lines.push('');\n }\n\n // Typed Link overloads — per-route with DIRECT types (no conditionals).\n // Direct types preserve TypeScript's excess property checking.\n //\n // TIM-832: per-route and catch-all are emitted as TWO separate\n // augmentation blocks. Per TS's merging rule \"later overload sets\n // ordered first\", the catch-all block (declared SECOND in this file)\n // ends up FIRST in the merged call-signature list at resolution time,\n // which puts the per-route block LAST — so its error message is the\n // one TypeScript reports when no overload matches. This gives users a\n // clear prop-mismatch error (e.g. \"'string | undefined' is not\n // assignable to 'string | number' on id\") instead of the old\n // confusing \"Type 'string' is not assignable to type 'never'\" cascade.\n if (pageRoutes.length > 0) {\n lines.push(' // Typed Link overloads — per-route (block 1 / emitted first)');\n lines.push(...formatTypedLinkOverloads(pageRoutes, importBase, hasSchema));\n lines.push('');\n }\n\n lines.push('}');\n lines.push('');\n }\n\n // TIM-832: catch-all block — emitted as a SEPARATE `declare module`\n // augmentation so TS's \"later overload set first\" rule orders it ahead\n // of the per-route block above at resolution time, leaving per-route as\n // the \"last overload\" whose error TypeScript reports.\n lines.push(\"declare module '@timber-js/app/client' {\");\n lines.push(\" import type { SearchParamsDefinition } from '@timber-js/app/search-params'\");\n lines.push('');\n lines.push(...formatLinkCatchAllOverloads());\n lines.push('}');\n lines.push('');\n\n return lines.join('\\n');\n}\n\n/**\n * Format the params type for a route entry.\n */\nfunction formatParamsType(params: ParamEntry[], importBase?: string, hasSchema?: boolean): string {\n if (params.length === 0) {\n return '{}';\n }\n\n const fields = params.map((p) => {\n const codecType = hasSchema\n ? buildSchemaParamType(p)\n : buildCodecChainType(p, importBase, p.type);\n return `${p.name}: ${codecType}`;\n });\n return `{ ${fields.join('; ')} }`;\n}\n\n/**\n * Generate useQueryStates overloads.\n *\n * For each page route:\n * - Routes with search-params.ts get a typed overload returning the inferred T\n * - Routes without search-params.ts get an overload returning [{}, SetParams<{}>]\n *\n * A fallback overload for standalone codecs (existing API) is emitted last.\n */\nfunction formatUseQueryStatesOverloads(routes: RouteEntry[], importBase?: string): string[] {\n const lines: string[] = [];\n\n for (const route of routes) {\n const searchParamsType = route.hasSearchParams\n ? formatSearchParamsType(route, importBase)\n : '{}';\n lines.push(\n ` export function useQueryStates<R extends '${route.urlPath}'>(route: R, options?: QueryStatesOptions): [${searchParamsType}, SetParams<${searchParamsType}>]`\n );\n }\n\n // Fallback: standalone codecs (existing API)\n lines.push(\n ' export function useQueryStates<T extends Record<string, unknown>>(codecs: { [K in keyof T]: SearchParamCodec<T[K]> }, options?: QueryStatesOptions): [T, SetParams<T>]'\n );\n\n return lines;\n}\n\n// Link overload formatters and helpers (`formatTypedLinkOverloads`,\n// `formatLinkCatchAllOverloads`, `formatLinkParamsType`,\n// `buildResolvedPattern`, `LINK_BASE_PROPS_TYPE`) were extracted to\n// `./link-codegen.ts` (TIM-835) to keep this file under the 500-line\n// cap. They are imported at the top of this file.\n","/**\n * Schema key/value validation against the filesystem route tree.\n *\n * Runs at codegen time (build + dev) to catch mismatches between\n * app/schema.ts keys and the actual dynamic segments on disk.\n *\n * Design doc: design/41-global-params.md\n */\n\nimport { readFileCached } from './file-cache.js';\nimport type { RouteTree, SegmentNode } from './types.js';\nimport { findSchemaFile, parseExistingSchemaKeys } from '../cli-schema-sync.js';\nimport { classifyUrlSegment } from './segment-classify.js';\n\nexport interface SchemaWarning {\n type: 'stale-key' | 'missing-key' | 'bracket-mismatch';\n key: string;\n message: string;\n filesystemKey?: string;\n}\n\n/**\n * Collect all unique bracket-keyed dynamic segment names from a route tree.\n * Returns entries like '[artistSlug]', '[...slug]', '[[...topic]]'.\n */\nexport function collectDynamicSegmentsFromTree(tree: RouteTree): Set<string> {\n const segments = new Set<string>();\n walkTree(tree.root, segments);\n return segments;\n}\n\nfunction walkTree(node: SegmentNode, segments: Set<string>): void {\n if (node.paramName && node.segmentName) {\n const classified = classifyUrlSegment(node.segmentName);\n if (classified.kind !== 'static') {\n // Use bare bracket form for schema keys — affixed segments like\n // `img-[id].png` register as `[id]`, matching runtime codec lookup.\n if (classified.kind === 'dynamic' && (classified.prefix || classified.suffix)) {\n segments.add(`[${classified.name}]`);\n } else {\n segments.add(node.segmentName);\n }\n }\n }\n for (const child of node.children) {\n walkTree(child, segments);\n }\n for (const slot of Object.values(node.slots)) {\n walkTree(slot, segments);\n }\n}\n\n/**\n * Extract the param name from a bracket key.\n * '[id]' → 'id', '[...slug]' → 'slug', '[[...topic]]' → 'topic'\n */\nfunction extractParamName(bracketKey: string): string | null {\n const seg = classifyUrlSegment(bracketKey);\n if (seg.kind === 'static') return null;\n return seg.name;\n}\n\n/**\n * Validate schema keys against the filesystem route tree.\n *\n * Returns warnings for:\n * - Stale keys: schema keys that don't match any filesystem segment\n * - Bracket form mismatches: same param name, different bracket form\n * - Missing keys: filesystem segments not registered in schema (informational)\n */\nexport function validateSchemaAgainstRoutes(tree: RouteTree, appDir: string): SchemaWarning[] {\n const schemaPath = findSchemaFile(appDir);\n if (!schemaPath) return [];\n\n const content = readFileCached(schemaPath);\n const schemaKeys = parseExistingSchemaKeys(content);\n\n if (schemaKeys.length === 0) return [];\n\n const filesystemSegments = collectDynamicSegmentsFromTree(tree);\n\n return validateKeys(schemaKeys, filesystemSegments);\n}\n\n/**\n * Core validation: compare schema keys against filesystem segments.\n * Exported separately for testing without filesystem dependencies.\n */\nexport function validateKeys(\n schemaKeys: string[],\n filesystemSegments: Set<string>\n): SchemaWarning[] {\n const warnings: SchemaWarning[] = [];\n\n // Build a map of param name → bracket form for filesystem segments\n const fsParamToKey = new Map<string, string>();\n for (const fsKey of filesystemSegments) {\n const name = extractParamName(fsKey);\n if (name) {\n fsParamToKey.set(name, fsKey);\n }\n }\n\n // Build a set of schema param names for the missing-key check\n const schemaParamNames = new Set<string>();\n\n for (const schemaKey of schemaKeys) {\n const schemaParamName = extractParamName(schemaKey);\n if (!schemaParamName) continue;\n\n schemaParamNames.add(schemaParamName);\n\n if (filesystemSegments.has(schemaKey)) {\n // Exact match — no issue\n continue;\n }\n\n // Check if the param name exists but with a different bracket form\n const fsKey = fsParamToKey.get(schemaParamName);\n if (fsKey) {\n warnings.push({\n type: 'bracket-mismatch',\n key: schemaKey,\n filesystemKey: fsKey,\n message:\n `Schema key '${schemaKey}' does not match filesystem bracket form '${fsKey}'. ` +\n `Update the schema key to '${fsKey}'.`,\n });\n } else {\n warnings.push({\n type: 'stale-key',\n key: schemaKey,\n message:\n `Schema key '${schemaKey}' does not match any dynamic segment in the filesystem. ` +\n `Remove it from app/schema.ts or create the corresponding route segment.`,\n });\n }\n }\n\n // Check for filesystem segments not in schema (informational)\n for (const fsKey of filesystemSegments) {\n const name = extractParamName(fsKey);\n if (name && !schemaParamNames.has(name)) {\n warnings.push({\n type: 'missing-key',\n key: fsKey,\n message:\n `Dynamic segment '${fsKey}' has no codec in app/schema.ts (defaults to string). ` +\n `Run: timber schema sync`,\n });\n }\n }\n\n return warnings;\n}\n","/**\n * Intercepting route utilities.\n *\n * Computes rewrite rules from the route tree that enable intercepting routes\n * to conditionally render when navigating via client-side (soft) navigation.\n *\n * The mechanism: at build time, each intercepting route directory generates a\n * conditional rewrite. On soft navigation, the client sends an `X-Timber-URL`\n * header with the current pathname. The server checks if any rewrite's source\n * (the intercepted URL) matches the target pathname AND the header matches\n * the intercepting route's parent URL. If both match, the intercepting route\n * renders instead of the normal route.\n *\n * On hard navigation (no header), no rewrite matches, and the normal route\n * renders.\n *\n * See design/07-routing.md §\"Intercepting Routes\"\n */\n\nimport type { SegmentNode, InterceptionMarker } from './types.js';\n\n/** A conditional rewrite rule generated from an intercepting route. */\nexport interface InterceptionRewrite {\n /**\n * The URL pattern that this rewrite intercepts (the target of navigation).\n * E.g., \"/photo/[id]\" for a (.)photo/[id] interception.\n */\n interceptedPattern: string;\n /**\n * The URL prefix that the client must be navigating FROM for this rewrite\n * to apply. Matched against the X-Timber-URL header.\n * E.g., \"/feed\" for a (.)photo/[id] inside /feed/@modal/.\n */\n interceptingPrefix: string;\n}\n\n/**\n * Collect all interception rewrite rules from the route tree.\n *\n * Walks the tree recursively. For each intercepting segment, computes the\n * intercepted URL based on the marker and the segment's position.\n */\nexport function collectInterceptionRewrites(root: SegmentNode): InterceptionRewrite[] {\n const rewrites: InterceptionRewrite[] = [];\n walkForInterceptions(root, [root], rewrites);\n return rewrites;\n}\n\n/**\n * Recursively walk the segment tree to find intercepting routes.\n */\nfunction walkForInterceptions(\n node: SegmentNode,\n ancestors: SegmentNode[],\n rewrites: InterceptionRewrite[]\n): void {\n // Check children\n for (const child of node.children) {\n if (child.segmentType === 'intercepting' && child.interceptionMarker) {\n // Found an intercepting route — collect rewrites from its sub-tree\n collectFromInterceptingNode(child, ancestors, rewrites);\n } else {\n walkForInterceptions(child, [...ancestors, child], rewrites);\n }\n }\n\n // Check slots (intercepting routes are typically inside slots like @modal)\n for (const slot of Object.values(node.slots)) {\n walkForInterceptions(slot, ancestors, rewrites);\n }\n}\n\n/**\n * For an intercepting segment, find all leaf pages in its sub-tree and\n * generate rewrite rules for each.\n */\nfunction collectFromInterceptingNode(\n interceptingNode: SegmentNode,\n ancestors: SegmentNode[],\n rewrites: InterceptionRewrite[]\n): void {\n const marker = interceptingNode.interceptionMarker!;\n const segmentName = interceptingNode.interceptedSegmentName!;\n\n // Compute the intercepted URL base based on the marker\n const parentUrlPath = ancestors[ancestors.length - 1].urlPath;\n const interceptedBase = computeInterceptedBase(parentUrlPath, marker);\n const interceptedUrlBase =\n interceptedBase === '/' ? `/${segmentName}` : `${interceptedBase}/${segmentName}`;\n\n // Find all leaf pages in the intercepting sub-tree\n collectLeavesWithRewrites(interceptingNode, interceptedUrlBase, parentUrlPath, rewrites);\n}\n\n/**\n * Recursively find leaf pages in an intercepting sub-tree and generate\n * rewrite rules for each.\n */\nfunction collectLeavesWithRewrites(\n node: SegmentNode,\n interceptedUrlPath: string,\n interceptingPrefix: string,\n rewrites: InterceptionRewrite[]\n): void {\n if (node.page) {\n rewrites.push({\n interceptedPattern: interceptedUrlPath,\n interceptingPrefix,\n });\n }\n\n for (const child of node.children) {\n const childUrl =\n child.segmentType === 'group'\n ? interceptedUrlPath\n : `${interceptedUrlPath}/${child.segmentName}`;\n collectLeavesWithRewrites(child, childUrl, interceptingPrefix, rewrites);\n }\n}\n\n/**\n * Compute the base URL that an intercepting route intercepts, given the\n * parent's URL path and the interception marker.\n *\n * - (.) — same level: parent's URL path\n * - (..) — one level up: parent's parent URL path\n * - (...) — root level: /\n * - (..)(..) — two levels up: parent's grandparent URL path\n *\n * Level counting operates on URL path segments, NOT filesystem directories.\n * Route groups and parallel slots are already excluded from urlPath (they\n * don't add URL depth), so (..) correctly climbs visible segments. This\n * avoids the Vinext bug where path.dirname() on filesystem paths would\n * waste climbs on invisible route groups.\n */\nfunction computeInterceptedBase(parentUrlPath: string, marker: InterceptionMarker): string {\n switch (marker) {\n case '(.)':\n return parentUrlPath;\n case '(..)': {\n const parts = parentUrlPath.split('/').filter(Boolean);\n parts.pop();\n return parts.length === 0 ? '/' : `/${parts.join('/')}`;\n }\n case '(...)':\n return '/';\n case '(..)(..)': {\n const parts = parentUrlPath.split('/').filter(Boolean);\n parts.pop();\n parts.pop();\n return parts.length === 0 ? '/' : `/${parts.join('/')}`;\n }\n }\n}\n","/**\n * Shared route-tree walkers (TIM-848).\n *\n * Tiny helpers that walk a `SegmentNode<TFile>` tree generically. Both the\n * build-time tree (`SegmentNode<RouteFile>`) and the runtime manifest\n * tree (`SegmentNode<ManifestFile>`) flow through these helpers because\n * the walker only reads the structural fields shared by both shapes\n * (`children`, `slots`, `page`, `route`, `urlPath`).\n *\n * Before this module, three near-identical `collectRoutes` functions\n * lived in `plugins/dev-404-page.ts`, `plugins/build-report.ts`, and\n * `routing/codegen.ts`. The codegen one is special-purpose (it\n * accumulates `ParamEntry[]` and resolves codec chains) and stays\n * local; the other two now share `collectLeafRoutes` from this file.\n */\n\nimport type { SegmentNode } from './types.js';\n\n/** A leaf route discovered while walking the segment tree. */\nexport interface LeafRoute<TFile> {\n /** URL path of the leaf (root is \"/\"). */\n urlPath: string;\n /** Segment chain from root to this leaf, inclusive. */\n segments: SegmentNode<TFile>[];\n /** The page file at this leaf, if any. */\n page?: TFile;\n /** The route handler file at this leaf, if any. */\n route?: TFile;\n}\n\n/** Options for `collectLeafRoutes`. */\nexport interface CollectLeafRoutesOptions {\n /**\n * If true, recurse into parallel slots and emit slot leaves alongside\n * the main route tree. Defaults to `false` because slots render\n * alongside their parent at the same URL and are not separately\n * URL-addressable. The build report excludes slots; route-listing\n * UIs that want to show \"all leaves with a page handler\" can opt in.\n */\n includeSlots?: boolean;\n}\n\n/**\n * Walk a segment tree and collect every leaf with a `page` or `route`\n * handler. Generic over `TFile` so it works on both the build-time\n * scanner output and the runtime manifest tree.\n *\n * - Pages and route handlers at the same URL produce two distinct\n * entries (the build report deduplicates by URL afterward).\n * - Parallel slots are skipped unless `includeSlots: true` (slots\n * share their parent's URL and are not addressable on their own).\n * - Result is sorted by `urlPath` for deterministic output.\n */\nexport function collectLeafRoutes<TFile>(\n root: SegmentNode<TFile>,\n options: CollectLeafRoutesOptions = {}\n): LeafRoute<TFile>[] {\n const { includeSlots = false } = options;\n const result: LeafRoute<TFile>[] = [];\n walk(root, [], result, includeSlots);\n result.sort((a, b) => a.urlPath.localeCompare(b.urlPath));\n return result;\n}\n\nfunction walk<TFile>(\n node: SegmentNode<TFile>,\n chain: SegmentNode<TFile>[],\n result: LeafRoute<TFile>[],\n includeSlots: boolean\n): void {\n const currentChain = [...chain, node];\n const path = node.urlPath || '/';\n\n if (node.page) {\n result.push({ urlPath: path, segments: currentChain, page: node.page });\n }\n if (node.route) {\n result.push({ urlPath: path, segments: currentChain, route: node.route });\n }\n\n for (const child of node.children) {\n walk(child, currentChain, result, includeSlots);\n }\n\n if (includeSlots) {\n for (const slotNode of Object.values(node.slots)) {\n walk(slotNode, currentChain, result, includeSlots);\n }\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { TimberConfig } from './types';
2
+ /** Options for the shared build output steps. */
3
+ export interface BuildOutputBaseOptions {
4
+ /** Resolved timber config. */
5
+ config: TimberConfig;
6
+ /** Root build directory (e.g. `.timber/build`). */
7
+ buildDir: string;
8
+ /** Adapter-specific output directory (e.g. `.timber/build/nitro`). */
9
+ outDir: string;
10
+ /**
11
+ * Name of the public/static directory within outDir.
12
+ * Nitro uses 'public', Cloudflare uses 'static'.
13
+ */
14
+ publicDirName: string;
15
+ }
16
+ /**
17
+ * Run the platform-agnostic build output steps shared by all adapters:
18
+ *
19
+ * 1. Create the output directory
20
+ * 2. Copy client assets to the public/static directory
21
+ * 3. Write the `_headers` file for static asset cache control
22
+ * 4. Copy RSC and SSR server bundles into the output directory
23
+ * 5. Write the manifest-init module if present
24
+ *
25
+ * Returns the resolved public directory path for further adapter-specific use.
26
+ */
27
+ export declare function runSharedBuildSteps(opts: BuildOutputBaseOptions): Promise<string>;
28
+ export declare function findUnhashedStaticFiles(publicDir: string): Promise<string[]>;
29
+ //# sourceMappingURL=build-output-helper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-output-helper.d.ts","sourceRoot":"","sources":["../../src/adapters/build-output-helper.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,iDAAiD;AACjD,MAAM,WAAW,sBAAsB;IACrC,8BAA8B;IAC9B,MAAM,EAAE,YAAY,CAAC;IACrB,mDAAmD;IACnD,QAAQ,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,sBAAsB,GAAG,OAAO,CAAC,MAAM,CAAC,CA+DvF;AAuBD,wBAAsB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAuBlF"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Cloudflare dev-mode bindings via wrangler's getPlatformProxy().
3
+ *
4
+ * This Vite plugin starts a local workerd process (via Miniflare) that
5
+ * emulates Cloudflare bindings (KV, D1, R2, Queues, Durable Objects, etc.)
6
+ * during development. The proxy env is injected into the request ALS so
7
+ * `getCloudflareBindings()` works identically in dev and production.
8
+ *
9
+ * Design doc: design/35-cloudflare-primitives.md §"Dev Experience"
10
+ *
11
+ * Usage:
12
+ * ```ts
13
+ * // vite.config.ts
14
+ * import { timber } from '@timber-js/app'
15
+ * import { cloudflare } from '@timber-js/app/adapters/cloudflare'
16
+ * import { cloudflareDevBindings } from '@timber-js/app/adapters/cloudflare/dev'
17
+ *
18
+ * export default defineConfig({
19
+ * plugins: [
20
+ * timber({ adapter: cloudflare() }),
21
+ * cloudflareDevBindings(),
22
+ * ],
23
+ * })
24
+ * ```
25
+ *
26
+ * Requires `wrangler` as a dev dependency. Install it:
27
+ * ```bash
28
+ * pnpm add -D wrangler
29
+ * ```
30
+ */
31
+ import type { Plugin } from 'vite';
32
+ /**
33
+ * Dynamically import wrangler. Extracted as a named export so tests
34
+ * can mock it without needing wrangler installed.
35
+ * @internal
36
+ */
37
+ export declare function loadWrangler(): Promise<{
38
+ getPlatformProxy: (opts: any) => Promise<any>;
39
+ }>;
40
+ /**
41
+ * Symbol key used to store the dev request wrapper on ViteDevServer.
42
+ *
43
+ * @internal Exported for testing. The dev-server plugin uses
44
+ * `Symbol.for('timber:dev-request-wrapper')` directly to avoid
45
+ * importing from this module.
46
+ */
47
+ export declare const DEV_REQUEST_WRAPPER_KEY: unique symbol;
48
+ /** Options for the Cloudflare dev bindings plugin. */
49
+ export interface CloudflareDevBindingsOptions {
50
+ /**
51
+ * Path to the wrangler configuration file.
52
+ * @default Auto-detected by wrangler (wrangler.jsonc, wrangler.json, wrangler.toml)
53
+ */
54
+ configPath?: string;
55
+ /**
56
+ * Whether to persist binding data (KV, D1, R2) between dev server restarts.
57
+ *
58
+ * - `true` — persist in wrangler's default location (`.wrangler/state/`)
59
+ * - `{ path: string }` — persist in a custom directory
60
+ * - `false` — start fresh on every restart
61
+ *
62
+ * @default true
63
+ */
64
+ persist?: boolean | {
65
+ path: string;
66
+ };
67
+ /**
68
+ * Wrangler environment to use (for multi-environment configs).
69
+ * Maps to `[env.<name>]` sections in wrangler.toml / wrangler.jsonc.
70
+ */
71
+ environment?: string;
72
+ /**
73
+ * @internal Override the wrangler loader for testing.
74
+ * Not part of the public API — may change without notice.
75
+ */
76
+ _loadWrangler?: () => Promise<{
77
+ getPlatformProxy: (opts: any) => Promise<any>;
78
+ }>;
79
+ }
80
+ /**
81
+ * Vite plugin that provides Cloudflare bindings in dev mode via
82
+ * wrangler's `getPlatformProxy()`.
83
+ *
84
+ * Starts a local workerd process on dev server startup and injects
85
+ * the proxy env into the per-request ALS. This makes
86
+ * `getCloudflareBindings()` return real (emulated) bindings during
87
+ * development — KV, D1, R2, Queues, Durable Objects, and all other
88
+ * bindings declared in wrangler.jsonc.
89
+ *
90
+ * The proxy is automatically disposed when the dev server closes.
91
+ *
92
+ * **Requirements:**
93
+ * - `wrangler` installed as a dev dependency
94
+ * - A `wrangler.jsonc` (or `wrangler.toml`) with binding declarations
95
+ *
96
+ * @example
97
+ * ```ts
98
+ * import { cloudflareDevBindings } from '@timber-js/app/adapters/cloudflare/dev'
99
+ *
100
+ * export default defineConfig({
101
+ * plugins: [
102
+ * timber({ adapter: cloudflare() }),
103
+ * cloudflareDevBindings(),
104
+ * ],
105
+ * })
106
+ * ```
107
+ */
108
+ export declare function cloudflareDevBindings(options?: CloudflareDevBindingsOptions): Plugin;
109
+ //# sourceMappingURL=cloudflare-dev.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudflare-dev.d.ts","sourceRoot":"","sources":["../../src/adapters/cloudflare-dev.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAiB,MAAM,MAAM,CAAC;AAGlD;;;;GAIG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC;IAAE,gBAAgB,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,CAAA;CAAE,CAAC,CAU/F;AAaD;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,eAA2C,CAAC;AAEhF,sDAAsD;AACtD,MAAM,WAAW,4BAA4B;IAC3C;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,OAAO,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAErC;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC;QAAE,gBAAgB,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,CAAA;KAAE,CAAC,CAAC;CAClF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,GAAE,4BAAiC,GAAG,MAAM,CA6CxF"}
@@ -0,0 +1,73 @@
1
+ import { d as runWithBindings } from "../_chunks/cloudflare-AHoWYTYr.js";
2
+ //#region src/adapters/cloudflare-dev.ts
3
+ /**
4
+ * Dynamically import wrangler. Extracted as a named export so tests
5
+ * can mock it without needing wrangler installed.
6
+ * @internal
7
+ */
8
+ async function loadWrangler() {
9
+ try {
10
+ return await import("wrangler");
11
+ } catch {
12
+ throw new Error("[timber] Could not import wrangler. cloudflareDevBindings() requires wrangler as a dev dependency.\nInstall it: pnpm add -D wrangler");
13
+ }
14
+ }
15
+ /**
16
+ * Symbol key used to store the dev request wrapper on ViteDevServer.
17
+ *
18
+ * @internal Exported for testing. The dev-server plugin uses
19
+ * `Symbol.for('timber:dev-request-wrapper')` directly to avoid
20
+ * importing from this module.
21
+ */
22
+ var DEV_REQUEST_WRAPPER_KEY = Symbol.for("timber:dev-request-wrapper");
23
+ /**
24
+ * Vite plugin that provides Cloudflare bindings in dev mode via
25
+ * wrangler's `getPlatformProxy()`.
26
+ *
27
+ * Starts a local workerd process on dev server startup and injects
28
+ * the proxy env into the per-request ALS. This makes
29
+ * `getCloudflareBindings()` return real (emulated) bindings during
30
+ * development — KV, D1, R2, Queues, Durable Objects, and all other
31
+ * bindings declared in wrangler.jsonc.
32
+ *
33
+ * The proxy is automatically disposed when the dev server closes.
34
+ *
35
+ * **Requirements:**
36
+ * - `wrangler` installed as a dev dependency
37
+ * - A `wrangler.jsonc` (or `wrangler.toml`) with binding declarations
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * import { cloudflareDevBindings } from '@timber-js/app/adapters/cloudflare/dev'
42
+ *
43
+ * export default defineConfig({
44
+ * plugins: [
45
+ * timber({ adapter: cloudflare() }),
46
+ * cloudflareDevBindings(),
47
+ * ],
48
+ * })
49
+ * ```
50
+ */
51
+ function cloudflareDevBindings(options = {}) {
52
+ return {
53
+ name: "timber-cloudflare-dev-bindings",
54
+ apply: "serve",
55
+ async configureServer(server) {
56
+ const { getPlatformProxy } = await (options._loadWrangler ?? loadWrangler)();
57
+ const proxyOptions = { persist: options.persist ?? true };
58
+ if (options.configPath) proxyOptions.configPath = options.configPath;
59
+ if (options.environment) proxyOptions.environment = options.environment;
60
+ const proxy = await getPlatformProxy(proxyOptions);
61
+ server[DEV_REQUEST_WRAPPER_KEY] = (fn) => {
62
+ return runWithBindings(proxy.env, fn);
63
+ };
64
+ server.httpServer?.on("close", () => {
65
+ proxy.dispose().catch(() => {});
66
+ });
67
+ }
68
+ };
69
+ }
70
+ //#endregion
71
+ export { DEV_REQUEST_WRAPPER_KEY, cloudflareDevBindings, loadWrangler };
72
+
73
+ //# sourceMappingURL=cloudflare-dev.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudflare-dev.js","names":[],"sources":["../../src/adapters/cloudflare-dev.ts"],"sourcesContent":["/**\n * Cloudflare dev-mode bindings via wrangler's getPlatformProxy().\n *\n * This Vite plugin starts a local workerd process (via Miniflare) that\n * emulates Cloudflare bindings (KV, D1, R2, Queues, Durable Objects, etc.)\n * during development. The proxy env is injected into the request ALS so\n * `getCloudflareBindings()` works identically in dev and production.\n *\n * Design doc: design/35-cloudflare-primitives.md §\"Dev Experience\"\n *\n * Usage:\n * ```ts\n * // vite.config.ts\n * import { timber } from '@timber-js/app'\n * import { cloudflare } from '@timber-js/app/adapters/cloudflare'\n * import { cloudflareDevBindings } from '@timber-js/app/adapters/cloudflare/dev'\n *\n * export default defineConfig({\n * plugins: [\n * timber({ adapter: cloudflare() }),\n * cloudflareDevBindings(),\n * ],\n * })\n * ```\n *\n * Requires `wrangler` as a dev dependency. Install it:\n * ```bash\n * pnpm add -D wrangler\n * ```\n */\n\nimport type { Plugin, ViteDevServer } from 'vite';\nimport { runWithBindings } from './cloudflare.js';\n\n/**\n * Dynamically import wrangler. Extracted as a named export so tests\n * can mock it without needing wrangler installed.\n * @internal\n */\nexport async function loadWrangler(): Promise<{ getPlatformProxy: (opts: any) => Promise<any> }> {\n try {\n return await import('wrangler');\n } catch {\n throw new Error(\n '[timber] Could not import wrangler. ' +\n 'cloudflareDevBindings() requires wrangler as a dev dependency.\\n' +\n 'Install it: pnpm add -D wrangler'\n );\n }\n}\n\n// ─── Contract ─────────────────────────────────────────────────────────────\n//\n// The dev request wrapper is stored on the ViteDevServer instance using a\n// well-known Symbol. This allows cross-plugin communication without import\n// dependencies — the dev-server plugin checks for this Symbol per-request\n// and wraps the handler call when present.\n//\n// The wrapper type is: <T>(fn: () => T) => T\n// It runs `fn` inside the Cloudflare bindings ALS so getCloudflareBindings()\n// works throughout the request lifecycle.\n\n/**\n * Symbol key used to store the dev request wrapper on ViteDevServer.\n *\n * @internal Exported for testing. The dev-server plugin uses\n * `Symbol.for('timber:dev-request-wrapper')` directly to avoid\n * importing from this module.\n */\nexport const DEV_REQUEST_WRAPPER_KEY = Symbol.for('timber:dev-request-wrapper');\n\n/** Options for the Cloudflare dev bindings plugin. */\nexport interface CloudflareDevBindingsOptions {\n /**\n * Path to the wrangler configuration file.\n * @default Auto-detected by wrangler (wrangler.jsonc, wrangler.json, wrangler.toml)\n */\n configPath?: string;\n\n /**\n * Whether to persist binding data (KV, D1, R2) between dev server restarts.\n *\n * - `true` — persist in wrangler's default location (`.wrangler/state/`)\n * - `{ path: string }` — persist in a custom directory\n * - `false` — start fresh on every restart\n *\n * @default true\n */\n persist?: boolean | { path: string };\n\n /**\n * Wrangler environment to use (for multi-environment configs).\n * Maps to `[env.<name>]` sections in wrangler.toml / wrangler.jsonc.\n */\n environment?: string;\n\n /**\n * @internal Override the wrangler loader for testing.\n * Not part of the public API — may change without notice.\n */\n _loadWrangler?: () => Promise<{ getPlatformProxy: (opts: any) => Promise<any> }>;\n}\n\n/**\n * Vite plugin that provides Cloudflare bindings in dev mode via\n * wrangler's `getPlatformProxy()`.\n *\n * Starts a local workerd process on dev server startup and injects\n * the proxy env into the per-request ALS. This makes\n * `getCloudflareBindings()` return real (emulated) bindings during\n * development — KV, D1, R2, Queues, Durable Objects, and all other\n * bindings declared in wrangler.jsonc.\n *\n * The proxy is automatically disposed when the dev server closes.\n *\n * **Requirements:**\n * - `wrangler` installed as a dev dependency\n * - A `wrangler.jsonc` (or `wrangler.toml`) with binding declarations\n *\n * @example\n * ```ts\n * import { cloudflareDevBindings } from '@timber-js/app/adapters/cloudflare/dev'\n *\n * export default defineConfig({\n * plugins: [\n * timber({ adapter: cloudflare() }),\n * cloudflareDevBindings(),\n * ],\n * })\n * ```\n */\nexport function cloudflareDevBindings(options: CloudflareDevBindingsOptions = {}): Plugin {\n return {\n name: 'timber-cloudflare-dev-bindings',\n\n // Dev mode only — never active during production builds.\n // See design/35-cloudflare-primitives.md §\"Security Considerations\":\n // \"Dev bindings are dev-only. apply: 'serve' ensures it never runs\n // in production builds.\"\n apply: 'serve',\n\n async configureServer(server: ViteDevServer) {\n // Dynamic import — wrangler is an optional peer dependency.\n // Users must install it themselves: `pnpm add -D wrangler`\n const { getPlatformProxy } = await (options._loadWrangler ?? loadWrangler)();\n\n // Build getPlatformProxy options from our public API.\n const proxyOptions: Record<string, unknown> = {\n persist: options.persist ?? true,\n };\n if (options.configPath) {\n proxyOptions.configPath = options.configPath;\n }\n if (options.environment) {\n proxyOptions.environment = options.environment;\n }\n\n const proxy = await getPlatformProxy(proxyOptions);\n\n // Store a request wrapper on the server instance. The dev-server\n // plugin checks for this Symbol per-request and wraps the RSC\n // handler call so getCloudflareBindings() works throughout the\n // request lifecycle (server components, middleware, server actions).\n (server as any)[DEV_REQUEST_WRAPPER_KEY] = <T>(fn: () => T): T => {\n return runWithBindings(proxy.env as Record<string, unknown>, fn);\n };\n\n // Dispose the proxy when the dev server closes. This shuts down\n // the local workerd process started by getPlatformProxy().\n server.httpServer?.on('close', () => {\n proxy.dispose().catch(() => {\n // Disposal errors are non-fatal — the process is shutting down.\n });\n });\n },\n };\n}\n"],"mappings":";;;;;;;AAuCA,eAAsB,eAA2E;CAC/F,IAAI;EACF,OAAO,MAAM,OAAO;CACtB,QAAQ;EACN,MAAM,IAAI,MACR,sIAGF;CACF;AACF;;;;;;;;AAoBA,IAAa,0BAA0B,OAAO,IAAI,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8D9E,SAAgB,sBAAsB,UAAwC,CAAC,GAAW;CACxF,OAAO;EACL,MAAM;EAMN,OAAO;EAEP,MAAM,gBAAgB,QAAuB;GAG3C,MAAM,EAAE,qBAAqB,OAAO,QAAQ,iBAAiB,aAAA,CAAc;GAG3E,MAAM,eAAwC,EAC5C,SAAS,QAAQ,WAAW,KAC9B;GACA,IAAI,QAAQ,YACV,aAAa,aAAa,QAAQ;GAEpC,IAAI,QAAQ,aACV,aAAa,cAAc,QAAQ;GAGrC,MAAM,QAAQ,MAAM,iBAAiB,YAAY;GAMjD,OAAgB,4BAA+B,OAAmB;IAChE,OAAO,gBAAgB,MAAM,KAAgC,EAAE;GACjE;GAIA,OAAO,YAAY,GAAG,eAAe;IACnC,MAAM,QAAQ,CAAC,CAAC,YAAY,CAE5B,CAAC;GACH,CAAC;EACH;CACF;AACF"}
@@ -0,0 +1,65 @@
1
+ import type { CacheHandler } from '../cache/index';
2
+ /**
3
+ * Cloudflare Workers KV interface — the subset of KVNamespace we depend on.
4
+ * Users don't need to import this; the handler resolves the binding internally
5
+ * via `getCloudflareBindings()`.
6
+ */
7
+ export interface CloudflareKVNamespace {
8
+ get(key: string, options: {
9
+ type: 'json';
10
+ }): Promise<unknown>;
11
+ get(key: string, options?: {
12
+ type?: string;
13
+ }): Promise<string | null>;
14
+ put(key: string, value: string, options?: {
15
+ expirationTtl?: number;
16
+ }): Promise<void>;
17
+ delete(key: string): Promise<void>;
18
+ }
19
+ /**
20
+ * Cloudflare Workers KV–backed CacheHandler.
21
+ *
22
+ * Uses tag index keys for tag-based invalidation (KV has no secondary indexes).
23
+ * Stores entries with 2× TTL so stale entries survive for `staleWhileRevalidate`
24
+ * reads. The logical staleness is determined by the `expiresAt` timestamp inside
25
+ * the entry payload.
26
+ *
27
+ * **Consistency:** KV is eventually consistent (~60s propagation). TTL is the
28
+ * primary expiry mechanism. Tag invalidation is best-effort — do not rely on it
29
+ * for security-critical cache purging (use short TTLs instead).
30
+ *
31
+ * ```ts
32
+ * // timber.config.ts
33
+ * import { CloudflareKVCacheHandler } from '@timber-js/app/adapters/cloudflare/cache';
34
+ *
35
+ * export default {
36
+ * cacheHandler: new CloudflareKVCacheHandler({ bindingName: 'TIMBER_CACHE' }),
37
+ * };
38
+ * ```
39
+ */
40
+ export declare class CloudflareKVCacheHandler implements CacheHandler {
41
+ private bindingName;
42
+ private prefix;
43
+ constructor(options: {
44
+ bindingName: string;
45
+ prefix?: string;
46
+ });
47
+ /** Resolve the KV binding from the current request's Cloudflare env. */
48
+ private getKV;
49
+ private dataKey;
50
+ private tagKey;
51
+ get(key: string): Promise<{
52
+ value: unknown;
53
+ stale: boolean;
54
+ } | null>;
55
+ set(key: string, value: unknown, opts: {
56
+ ttl: number;
57
+ tags: string[];
58
+ generation?: number;
59
+ }): Promise<void>;
60
+ invalidate(opts: {
61
+ key?: string;
62
+ tag?: string;
63
+ }): Promise<void>;
64
+ }
65
+ //# sourceMappingURL=cloudflare-kv-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudflare-kv-cache.d.ts","sourceRoot":"","sources":["../../src/adapters/cloudflare-kv-cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAInD;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9D,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACtE,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrF,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpC;AAwCD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,wBAAyB,YAAW,YAAY;IAC3D,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,MAAM,CAAS;IAEvB,YAAY,OAAO,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,EAG5D;IAED,wEAAwE;IACxE,OAAO,CAAC,KAAK;IAYb,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,MAAM;IAIR,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC,CAQzE;IAEK,GAAG,CACP,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,OAAO,EACd,IAAI,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GACzD,OAAO,CAAC,IAAI,CAAC,CAoCf;IAEK,UAAU,CAAC,IAAI,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA6CpE;CACF"}