@timber-js/app 0.2.0-alpha.7 → 0.2.0-alpha.71

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 (500) hide show
  1. package/LICENSE +8 -0
  2. package/dist/_chunks/{als-registry-B7DbZ2hS.js → als-registry-BJARkOcu.js} +1 -1
  3. package/dist/_chunks/als-registry-BJARkOcu.js.map +1 -0
  4. package/dist/_chunks/chunk-DYhsFzuS.js +33 -0
  5. package/dist/_chunks/{debug-gwlJkDuf.js → debug-ECi_61pb.js} +2 -2
  6. package/dist/_chunks/debug-ECi_61pb.js.map +1 -0
  7. package/dist/_chunks/define-CGuYoRHU.js +199 -0
  8. package/dist/_chunks/define-CGuYoRHU.js.map +1 -0
  9. package/dist/_chunks/define-Dz1bqwaS.js +106 -0
  10. package/dist/_chunks/define-Dz1bqwaS.js.map +1 -0
  11. package/dist/_chunks/define-cookie-B5mewxwM.js +93 -0
  12. package/dist/_chunks/define-cookie-B5mewxwM.js.map +1 -0
  13. package/dist/_chunks/error-boundary-D9hzsveV.js +216 -0
  14. package/dist/_chunks/error-boundary-D9hzsveV.js.map +1 -0
  15. package/dist/_chunks/{format-DviM89f0.js → format-Rn922VH2.js} +3 -20
  16. package/dist/_chunks/format-Rn922VH2.js.map +1 -0
  17. package/dist/_chunks/{tracing-Cwn7697K.js → handler-store-BVePM7hp.js} +68 -3
  18. package/dist/_chunks/handler-store-BVePM7hp.js.map +1 -0
  19. package/dist/_chunks/{interception-BOoWmLUA.js → interception-CEdHHviP.js} +171 -97
  20. package/dist/_chunks/interception-CEdHHviP.js.map +1 -0
  21. package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js → metadata-routes-DS3eKNmf.js} +1 -1
  22. package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js.map → metadata-routes-DS3eKNmf.js.map} +1 -1
  23. package/dist/_chunks/{request-context-DIkVh_jG.js → request-context-CywiO4jV.js} +181 -69
  24. package/dist/_chunks/request-context-CywiO4jV.js.map +1 -0
  25. package/dist/_chunks/schema-bridge-C4SwjCQD.js +86 -0
  26. package/dist/_chunks/schema-bridge-C4SwjCQD.js.map +1 -0
  27. package/dist/_chunks/segment-classify-BDNn6EzD.js +65 -0
  28. package/dist/_chunks/segment-classify-BDNn6EzD.js.map +1 -0
  29. package/dist/_chunks/segment-context-hzuJ048X.js +72 -0
  30. package/dist/_chunks/segment-context-hzuJ048X.js.map +1 -0
  31. package/dist/_chunks/stale-reload-BLUC_Pl_.js +64 -0
  32. package/dist/_chunks/stale-reload-BLUC_Pl_.js.map +1 -0
  33. package/dist/_chunks/{use-query-states-D5KaffOK.js → use-query-states-DAhgj8Gx.js} +1 -1
  34. package/dist/_chunks/use-query-states-DAhgj8Gx.js.map +1 -0
  35. package/dist/_chunks/wrappers-LZbghvn0.js +63 -0
  36. package/dist/_chunks/wrappers-LZbghvn0.js.map +1 -0
  37. package/dist/adapters/cloudflare-dev.d.ts +109 -0
  38. package/dist/adapters/cloudflare-dev.d.ts.map +1 -0
  39. package/dist/adapters/cloudflare-dev.js +73 -0
  40. package/dist/adapters/cloudflare-dev.js.map +1 -0
  41. package/dist/adapters/cloudflare.d.ts +148 -12
  42. package/dist/adapters/cloudflare.d.ts.map +1 -1
  43. package/dist/adapters/cloudflare.js +135 -11
  44. package/dist/adapters/cloudflare.js.map +1 -1
  45. package/dist/adapters/compress-module.d.ts.map +1 -1
  46. package/dist/adapters/nitro.d.ts +17 -1
  47. package/dist/adapters/nitro.d.ts.map +1 -1
  48. package/dist/adapters/nitro.js +56 -13
  49. package/dist/adapters/nitro.js.map +1 -1
  50. package/dist/cache/cache-api.d.ts +24 -0
  51. package/dist/cache/cache-api.d.ts.map +1 -0
  52. package/dist/cache/fast-hash.d.ts +22 -0
  53. package/dist/cache/fast-hash.d.ts.map +1 -0
  54. package/dist/cache/handler-store.d.ts +31 -0
  55. package/dist/cache/handler-store.d.ts.map +1 -0
  56. package/dist/cache/index.d.ts +7 -5
  57. package/dist/cache/index.d.ts.map +1 -1
  58. package/dist/cache/index.js +111 -73
  59. package/dist/cache/index.js.map +1 -1
  60. package/dist/cache/singleflight.d.ts +18 -1
  61. package/dist/cache/singleflight.d.ts.map +1 -1
  62. package/dist/cache/timber-cache.d.ts +1 -1
  63. package/dist/cache/timber-cache.d.ts.map +1 -1
  64. package/dist/client/error-boundary.d.ts +12 -5
  65. package/dist/client/error-boundary.d.ts.map +1 -1
  66. package/dist/client/error-boundary.js +1 -125
  67. package/dist/client/error-reconstituter.d.ts +54 -0
  68. package/dist/client/error-reconstituter.d.ts.map +1 -0
  69. package/dist/client/form.d.ts +2 -2
  70. package/dist/client/form.d.ts.map +1 -1
  71. package/dist/client/history.d.ts +19 -4
  72. package/dist/client/history.d.ts.map +1 -1
  73. package/dist/client/index.d.ts +6 -5
  74. package/dist/client/index.d.ts.map +1 -1
  75. package/dist/client/index.js +537 -166
  76. package/dist/client/index.js.map +1 -1
  77. package/dist/client/link-pending-store.d.ts +78 -0
  78. package/dist/client/link-pending-store.d.ts.map +1 -0
  79. package/dist/client/link.d.ts +90 -32
  80. package/dist/client/link.d.ts.map +1 -1
  81. package/dist/client/nav-link-store.d.ts +36 -0
  82. package/dist/client/nav-link-store.d.ts.map +1 -0
  83. package/dist/client/navigation-api-types.d.ts +90 -0
  84. package/dist/client/navigation-api-types.d.ts.map +1 -0
  85. package/dist/client/navigation-api.d.ts +115 -0
  86. package/dist/client/navigation-api.d.ts.map +1 -0
  87. package/dist/client/navigation-context.d.ts +13 -2
  88. package/dist/client/navigation-context.d.ts.map +1 -1
  89. package/dist/client/{transition-root.d.ts → navigation-root.d.ts} +42 -8
  90. package/dist/client/navigation-root.d.ts.map +1 -0
  91. package/dist/client/nuqs-adapter.d.ts.map +1 -1
  92. package/dist/client/router.d.ts +70 -4
  93. package/dist/client/router.d.ts.map +1 -1
  94. package/dist/client/rsc-fetch.d.ts +38 -3
  95. package/dist/client/rsc-fetch.d.ts.map +1 -1
  96. package/dist/client/segment-cache.d.ts +1 -1
  97. package/dist/client/segment-cache.d.ts.map +1 -1
  98. package/dist/client/segment-context.d.ts +1 -1
  99. package/dist/client/segment-context.d.ts.map +1 -1
  100. package/dist/client/segment-merger.d.ts.map +1 -1
  101. package/dist/client/segment-outlet.d.ts +63 -0
  102. package/dist/client/segment-outlet.d.ts.map +1 -0
  103. package/dist/client/ssr-data.d.ts +13 -4
  104. package/dist/client/ssr-data.d.ts.map +1 -1
  105. package/dist/client/stale-reload.d.ts +15 -0
  106. package/dist/client/stale-reload.d.ts.map +1 -1
  107. package/dist/client/top-loader.d.ts +3 -3
  108. package/dist/client/top-loader.d.ts.map +1 -1
  109. package/dist/client/use-params.d.ts +6 -4
  110. package/dist/client/use-params.d.ts.map +1 -1
  111. package/dist/client/use-query-states.d.ts +1 -1
  112. package/dist/client/use-query-states.d.ts.map +1 -1
  113. package/dist/codec.d.ts +23 -0
  114. package/dist/codec.d.ts.map +1 -0
  115. package/dist/codec.js +2 -0
  116. package/dist/cookies/define-cookie.d.ts +35 -14
  117. package/dist/cookies/define-cookie.d.ts.map +1 -1
  118. package/dist/cookies/index.d.ts +2 -0
  119. package/dist/cookies/index.d.ts.map +1 -1
  120. package/dist/cookies/index.js +3 -84
  121. package/dist/fonts/css.d.ts +1 -0
  122. package/dist/fonts/css.d.ts.map +1 -1
  123. package/dist/index.d.ts +154 -38
  124. package/dist/index.d.ts.map +1 -1
  125. package/dist/index.js +12092 -11916
  126. package/dist/index.js.map +1 -1
  127. package/dist/plugins/adapter-build.d.ts +1 -1
  128. package/dist/plugins/adapter-build.d.ts.map +1 -1
  129. package/dist/plugins/build-manifest.d.ts +2 -2
  130. package/dist/plugins/build-manifest.d.ts.map +1 -1
  131. package/dist/plugins/build-report.d.ts +3 -3
  132. package/dist/plugins/build-report.d.ts.map +1 -1
  133. package/dist/plugins/client-chunks.d.ts +32 -0
  134. package/dist/plugins/client-chunks.d.ts.map +1 -0
  135. package/dist/plugins/content.d.ts +1 -1
  136. package/dist/plugins/content.d.ts.map +1 -1
  137. package/dist/plugins/dev-browser-logs.d.ts +84 -0
  138. package/dist/plugins/dev-browser-logs.d.ts.map +1 -0
  139. package/dist/plugins/dev-error-overlay.d.ts +26 -1
  140. package/dist/plugins/dev-error-overlay.d.ts.map +1 -1
  141. package/dist/plugins/dev-logs.d.ts +1 -1
  142. package/dist/plugins/dev-logs.d.ts.map +1 -1
  143. package/dist/plugins/dev-server.d.ts +1 -1
  144. package/dist/plugins/dev-server.d.ts.map +1 -1
  145. package/dist/plugins/entries.d.ts +1 -1
  146. package/dist/plugins/entries.d.ts.map +1 -1
  147. package/dist/plugins/fonts.d.ts +19 -5
  148. package/dist/plugins/fonts.d.ts.map +1 -1
  149. package/dist/plugins/mdx.d.ts +1 -1
  150. package/dist/plugins/mdx.d.ts.map +1 -1
  151. package/dist/plugins/routing.d.ts +1 -1
  152. package/dist/plugins/routing.d.ts.map +1 -1
  153. package/dist/plugins/server-bundle.d.ts.map +1 -1
  154. package/dist/plugins/shims.d.ts +6 -5
  155. package/dist/plugins/shims.d.ts.map +1 -1
  156. package/dist/plugins/static-build.d.ts +1 -1
  157. package/dist/plugins/static-build.d.ts.map +1 -1
  158. package/dist/routing/codegen.d.ts +2 -2
  159. package/dist/routing/codegen.d.ts.map +1 -1
  160. package/dist/routing/index.d.ts +2 -0
  161. package/dist/routing/index.d.ts.map +1 -1
  162. package/dist/routing/index.js +3 -2
  163. package/dist/routing/scanner.d.ts.map +1 -1
  164. package/dist/routing/segment-classify.d.ts +46 -0
  165. package/dist/routing/segment-classify.d.ts.map +1 -0
  166. package/dist/routing/status-file-lint.d.ts +2 -1
  167. package/dist/routing/status-file-lint.d.ts.map +1 -1
  168. package/dist/routing/types.d.ts +16 -4
  169. package/dist/routing/types.d.ts.map +1 -1
  170. package/dist/rsc-runtime/rsc.d.ts +1 -1
  171. package/dist/rsc-runtime/rsc.d.ts.map +1 -1
  172. package/dist/rsc-runtime/ssr.d.ts +12 -0
  173. package/dist/rsc-runtime/ssr.d.ts.map +1 -1
  174. package/dist/schema-bridge.d.ts +76 -0
  175. package/dist/schema-bridge.d.ts.map +1 -0
  176. package/dist/search-params/define.d.ts +139 -0
  177. package/dist/search-params/define.d.ts.map +1 -0
  178. package/dist/search-params/index.d.ts +4 -6
  179. package/dist/search-params/index.d.ts.map +1 -1
  180. package/dist/search-params/index.js +4 -474
  181. package/dist/search-params/registry.d.ts +1 -1
  182. package/dist/search-params/wrappers.d.ts +53 -0
  183. package/dist/search-params/wrappers.d.ts.map +1 -0
  184. package/dist/segment-params/define.d.ts +78 -0
  185. package/dist/segment-params/define.d.ts.map +1 -0
  186. package/dist/segment-params/index.d.ts +7 -0
  187. package/dist/segment-params/index.d.ts.map +1 -0
  188. package/dist/segment-params/index.js +4 -0
  189. package/dist/server/access-gate.d.ts +4 -0
  190. package/dist/server/access-gate.d.ts.map +1 -1
  191. package/dist/server/action-client.d.ts +12 -1
  192. package/dist/server/action-client.d.ts.map +1 -1
  193. package/dist/server/action-encryption.d.ts +76 -0
  194. package/dist/server/action-encryption.d.ts.map +1 -0
  195. package/dist/server/action-handler.d.ts.map +1 -1
  196. package/dist/server/actions.d.ts +3 -6
  197. package/dist/server/actions.d.ts.map +1 -1
  198. package/dist/server/als-registry.d.ts +32 -4
  199. package/dist/server/als-registry.d.ts.map +1 -1
  200. package/dist/server/build-manifest.d.ts +2 -2
  201. package/dist/server/build-manifest.d.ts.map +1 -1
  202. package/dist/server/debug.d.ts +1 -1
  203. package/dist/server/default-logger.d.ts +22 -0
  204. package/dist/server/default-logger.d.ts.map +1 -0
  205. package/dist/server/deny-page-resolver.d.ts +52 -0
  206. package/dist/server/deny-page-resolver.d.ts.map +1 -0
  207. package/dist/server/deny-renderer.d.ts.map +1 -1
  208. package/dist/server/dev-warnings.d.ts +0 -14
  209. package/dist/server/dev-warnings.d.ts.map +1 -1
  210. package/dist/server/early-hints.d.ts +13 -5
  211. package/dist/server/early-hints.d.ts.map +1 -1
  212. package/dist/server/error-boundary-wrapper.d.ts +7 -1
  213. package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
  214. package/dist/server/fallback-error.d.ts +4 -3
  215. package/dist/server/fallback-error.d.ts.map +1 -1
  216. package/dist/server/flight-injection-state.d.ts +66 -0
  217. package/dist/server/flight-injection-state.d.ts.map +1 -0
  218. package/dist/server/flight-scripts.d.ts +42 -0
  219. package/dist/server/flight-scripts.d.ts.map +1 -0
  220. package/dist/server/flush.d.ts.map +1 -1
  221. package/dist/server/form-data.d.ts +29 -0
  222. package/dist/server/form-data.d.ts.map +1 -1
  223. package/dist/server/html-injectors.d.ts +51 -11
  224. package/dist/server/html-injectors.d.ts.map +1 -1
  225. package/dist/server/index.d.ts +5 -3
  226. package/dist/server/index.d.ts.map +1 -1
  227. package/dist/server/index.js +2176 -1663
  228. package/dist/server/index.js.map +1 -1
  229. package/dist/server/logger.d.ts +25 -7
  230. package/dist/server/logger.d.ts.map +1 -1
  231. package/dist/server/middleware-runner.d.ts +19 -4
  232. package/dist/server/middleware-runner.d.ts.map +1 -1
  233. package/dist/server/node-stream-transforms.d.ts +113 -0
  234. package/dist/server/node-stream-transforms.d.ts.map +1 -0
  235. package/dist/server/page-deny-boundary.d.ts +31 -0
  236. package/dist/server/page-deny-boundary.d.ts.map +1 -0
  237. package/dist/server/pipeline-interception.d.ts +1 -1
  238. package/dist/server/pipeline-interception.d.ts.map +1 -1
  239. package/dist/server/pipeline-metadata.d.ts +6 -0
  240. package/dist/server/pipeline-metadata.d.ts.map +1 -1
  241. package/dist/server/pipeline.d.ts +32 -10
  242. package/dist/server/pipeline.d.ts.map +1 -1
  243. package/dist/server/primitives.d.ts +30 -3
  244. package/dist/server/primitives.d.ts.map +1 -1
  245. package/dist/server/render-timeout.d.ts +51 -0
  246. package/dist/server/render-timeout.d.ts.map +1 -0
  247. package/dist/server/request-context.d.ts +76 -37
  248. package/dist/server/request-context.d.ts.map +1 -1
  249. package/dist/server/route-element-builder.d.ts +27 -1
  250. package/dist/server/route-element-builder.d.ts.map +1 -1
  251. package/dist/server/route-handler.d.ts.map +1 -1
  252. package/dist/server/route-matcher.d.ts +9 -2
  253. package/dist/server/route-matcher.d.ts.map +1 -1
  254. package/dist/server/rsc-entry/api-handler.d.ts +2 -2
  255. package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
  256. package/dist/server/rsc-entry/error-renderer.d.ts +26 -13
  257. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  258. package/dist/server/rsc-entry/helpers.d.ts +48 -5
  259. package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
  260. package/dist/server/rsc-entry/index.d.ts +8 -3
  261. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  262. package/dist/server/rsc-entry/rsc-payload.d.ts +3 -3
  263. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  264. package/dist/server/rsc-entry/rsc-stream.d.ts +10 -1
  265. package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
  266. package/dist/server/rsc-entry/ssr-bridge.d.ts +1 -1
  267. package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
  268. package/dist/server/rsc-entry/ssr-renderer.d.ts +19 -4
  269. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  270. package/dist/server/safe-load.d.ts +46 -0
  271. package/dist/server/safe-load.d.ts.map +1 -0
  272. package/dist/server/sitemap-generator.d.ts +129 -0
  273. package/dist/server/sitemap-generator.d.ts.map +1 -0
  274. package/dist/server/sitemap-handler.d.ts +22 -0
  275. package/dist/server/sitemap-handler.d.ts.map +1 -0
  276. package/dist/server/slot-resolver.d.ts +1 -1
  277. package/dist/server/slot-resolver.d.ts.map +1 -1
  278. package/dist/server/ssr-entry.d.ts +22 -0
  279. package/dist/server/ssr-entry.d.ts.map +1 -1
  280. package/dist/server/ssr-render.d.ts +39 -21
  281. package/dist/server/ssr-render.d.ts.map +1 -1
  282. package/dist/server/ssr-wrappers.d.ts +50 -0
  283. package/dist/server/ssr-wrappers.d.ts.map +1 -0
  284. package/dist/server/status-code-resolver.d.ts +1 -1
  285. package/dist/server/status-code-resolver.d.ts.map +1 -1
  286. package/dist/server/stream-utils.d.ts +36 -0
  287. package/dist/server/stream-utils.d.ts.map +1 -0
  288. package/dist/server/tracing.d.ts +10 -0
  289. package/dist/server/tracing.d.ts.map +1 -1
  290. package/dist/server/tree-builder.d.ts +22 -19
  291. package/dist/server/tree-builder.d.ts.map +1 -1
  292. package/dist/server/types.d.ts +1 -4
  293. package/dist/server/types.d.ts.map +1 -1
  294. package/dist/server/version-skew.d.ts +61 -0
  295. package/dist/server/version-skew.d.ts.map +1 -0
  296. package/dist/server/waituntil-bridge.d.ts.map +1 -1
  297. package/dist/shared/merge-search-params.d.ts +22 -0
  298. package/dist/shared/merge-search-params.d.ts.map +1 -0
  299. package/dist/shims/font-google.d.ts +1 -1
  300. package/dist/shims/font-google.d.ts.map +1 -1
  301. package/dist/shims/font-google.js +42 -0
  302. package/dist/shims/font-google.js.map +1 -0
  303. package/dist/shims/font-local.d.ts +26 -0
  304. package/dist/shims/font-local.d.ts.map +1 -0
  305. package/dist/shims/font-local.js +20 -0
  306. package/dist/shims/font-local.js.map +1 -0
  307. package/dist/shims/navigation-client.d.ts +1 -1
  308. package/dist/shims/navigation-client.d.ts.map +1 -1
  309. package/dist/shims/navigation.d.ts +1 -1
  310. package/dist/shims/navigation.d.ts.map +1 -1
  311. package/dist/utils/directive-parser.d.ts +5 -2
  312. package/dist/utils/directive-parser.d.ts.map +1 -1
  313. package/dist/utils/state-machine.d.ts +80 -0
  314. package/dist/utils/state-machine.d.ts.map +1 -0
  315. package/package.json +37 -17
  316. package/src/adapters/cloudflare-dev.ts +177 -0
  317. package/src/adapters/cloudflare.ts +342 -28
  318. package/src/adapters/compress-module.ts +24 -4
  319. package/src/adapters/nitro.ts +58 -9
  320. package/src/adapters/wrangler.d.ts +7 -0
  321. package/src/cache/cache-api.ts +38 -0
  322. package/src/cache/fast-hash.ts +34 -0
  323. package/src/cache/handler-store.ts +68 -0
  324. package/src/cache/index.ts +9 -5
  325. package/src/cache/singleflight.ts +62 -4
  326. package/src/cache/timber-cache.ts +40 -29
  327. package/src/cli.ts +0 -0
  328. package/src/client/browser-entry.ts +314 -142
  329. package/src/client/error-boundary.tsx +48 -16
  330. package/src/client/error-reconstituter.tsx +65 -0
  331. package/src/client/form.tsx +2 -2
  332. package/src/client/history.ts +26 -4
  333. package/src/client/index.ts +13 -4
  334. package/src/client/link-pending-store.ts +136 -0
  335. package/src/client/link.tsx +346 -105
  336. package/src/client/nav-link-store.ts +47 -0
  337. package/src/client/navigation-api-types.ts +112 -0
  338. package/src/client/navigation-api.ts +332 -0
  339. package/src/client/navigation-context.ts +27 -6
  340. package/src/client/navigation-root.tsx +346 -0
  341. package/src/client/nuqs-adapter.tsx +16 -3
  342. package/src/client/router.ts +302 -77
  343. package/src/client/rsc-fetch.ts +93 -5
  344. package/src/client/segment-cache.ts +1 -1
  345. package/src/client/segment-context.ts +6 -1
  346. package/src/client/segment-merger.ts +2 -8
  347. package/src/client/segment-outlet.tsx +86 -0
  348. package/src/client/ssr-data.ts +13 -5
  349. package/src/client/stale-reload.ts +73 -6
  350. package/src/client/top-loader.tsx +22 -13
  351. package/src/client/use-navigation-pending.ts +1 -1
  352. package/src/client/use-params.ts +7 -5
  353. package/src/client/use-query-states.ts +2 -2
  354. package/src/codec.ts +34 -0
  355. package/src/cookies/define-cookie.ts +72 -21
  356. package/src/cookies/index.ts +7 -0
  357. package/src/fonts/css.ts +2 -1
  358. package/src/index.ts +328 -92
  359. package/src/plugins/adapter-build.ts +8 -2
  360. package/src/plugins/build-manifest.ts +13 -2
  361. package/src/plugins/build-report.ts +3 -3
  362. package/src/plugins/client-chunks.ts +65 -0
  363. package/src/plugins/content.ts +1 -1
  364. package/src/plugins/dev-browser-logs.ts +288 -0
  365. package/src/plugins/dev-error-overlay.ts +70 -1
  366. package/src/plugins/dev-logs.ts +1 -1
  367. package/src/plugins/dev-server.ts +55 -9
  368. package/src/plugins/entries.ts +70 -9
  369. package/src/plugins/fonts.ts +167 -61
  370. package/src/plugins/mdx.ts +1 -1
  371. package/src/plugins/routing.ts +57 -17
  372. package/src/plugins/server-action-exports.ts +1 -1
  373. package/src/plugins/server-bundle.ts +32 -1
  374. package/src/plugins/shims.ts +76 -33
  375. package/src/plugins/static-build.ts +10 -6
  376. package/src/routing/codegen.ts +165 -105
  377. package/src/routing/index.ts +2 -0
  378. package/src/routing/scanner.ts +93 -23
  379. package/src/routing/segment-classify.ts +89 -0
  380. package/src/routing/status-file-lint.ts +3 -2
  381. package/src/routing/types.ts +17 -4
  382. package/src/rsc-runtime/rsc.ts +2 -0
  383. package/src/rsc-runtime/ssr.ts +50 -0
  384. package/src/rsc-runtime/vendor-types.d.ts +7 -0
  385. package/src/{search-params/codecs.ts → schema-bridge.ts} +57 -20
  386. package/src/search-params/define.ts +482 -0
  387. package/src/search-params/index.ts +13 -19
  388. package/src/search-params/registry.ts +1 -1
  389. package/src/search-params/wrappers.ts +85 -0
  390. package/src/segment-params/define.ts +279 -0
  391. package/src/segment-params/index.ts +28 -0
  392. package/src/server/access-gate.tsx +70 -29
  393. package/src/server/action-client.ts +28 -3
  394. package/src/server/action-encryption.ts +144 -0
  395. package/src/server/action-handler.ts +20 -3
  396. package/src/server/actions.ts +10 -9
  397. package/src/server/als-registry.ts +32 -4
  398. package/src/server/build-manifest.ts +10 -4
  399. package/src/server/compress.ts +25 -7
  400. package/src/server/debug.ts +1 -1
  401. package/src/server/default-logger.ts +99 -0
  402. package/src/server/deny-page-resolver.ts +154 -0
  403. package/src/server/deny-renderer.ts +24 -38
  404. package/src/server/dev-warnings.ts +2 -28
  405. package/src/server/early-hints.ts +36 -15
  406. package/src/server/error-boundary-wrapper.ts +74 -22
  407. package/src/server/fallback-error.ts +31 -15
  408. package/src/server/flight-injection-state.ts +113 -0
  409. package/src/server/flight-scripts.ts +62 -0
  410. package/src/server/flush.ts +2 -1
  411. package/src/server/form-data.ts +76 -0
  412. package/src/server/html-injectors.ts +277 -117
  413. package/src/server/index.ts +9 -5
  414. package/src/server/logger.ts +44 -36
  415. package/src/server/middleware-runner.ts +31 -4
  416. package/src/server/node-stream-transforms.ts +509 -0
  417. package/src/server/page-deny-boundary.tsx +56 -0
  418. package/src/server/pipeline-interception.ts +17 -16
  419. package/src/server/pipeline-metadata.ts +13 -0
  420. package/src/server/pipeline.ts +195 -51
  421. package/src/server/primitives.ts +47 -5
  422. package/src/server/render-timeout.ts +108 -0
  423. package/src/server/request-context.ts +240 -117
  424. package/src/server/route-element-builder.ts +284 -197
  425. package/src/server/route-handler.ts +24 -4
  426. package/src/server/route-matcher.ts +24 -20
  427. package/src/server/rsc-entry/api-handler.ts +15 -16
  428. package/src/server/rsc-entry/error-renderer.ts +300 -89
  429. package/src/server/rsc-entry/helpers.ts +134 -5
  430. package/src/server/rsc-entry/index.ts +202 -113
  431. package/src/server/rsc-entry/rsc-payload.ts +100 -21
  432. package/src/server/rsc-entry/rsc-stream.ts +74 -18
  433. package/src/server/rsc-entry/ssr-bridge.ts +14 -5
  434. package/src/server/rsc-entry/ssr-renderer.ts +173 -40
  435. package/src/server/safe-load.ts +60 -0
  436. package/src/server/sitemap-generator.ts +338 -0
  437. package/src/server/sitemap-handler.ts +126 -0
  438. package/src/server/slot-resolver.ts +243 -228
  439. package/src/server/ssr-entry.ts +211 -32
  440. package/src/server/ssr-render.ts +289 -67
  441. package/src/server/ssr-wrappers.tsx +139 -0
  442. package/src/server/status-code-resolver.ts +1 -1
  443. package/src/server/stream-utils.ts +213 -0
  444. package/src/server/tracing.ts +37 -3
  445. package/src/server/tree-builder.ts +92 -58
  446. package/src/server/types.ts +3 -6
  447. package/src/server/version-skew.ts +104 -0
  448. package/src/server/waituntil-bridge.ts +4 -1
  449. package/src/shared/merge-search-params.ts +55 -0
  450. package/src/shims/font-google.ts +1 -1
  451. package/src/shims/font-local.ts +34 -0
  452. package/src/shims/navigation-client.ts +1 -1
  453. package/src/shims/navigation.ts +2 -1
  454. package/src/utils/directive-parser.ts +5 -2
  455. package/src/utils/state-machine.ts +111 -0
  456. package/dist/_chunks/als-registry-B7DbZ2hS.js.map +0 -1
  457. package/dist/_chunks/debug-gwlJkDuf.js.map +0 -1
  458. package/dist/_chunks/format-DviM89f0.js.map +0 -1
  459. package/dist/_chunks/interception-BOoWmLUA.js.map +0 -1
  460. package/dist/_chunks/request-context-DIkVh_jG.js.map +0 -1
  461. package/dist/_chunks/ssr-data-MjmprTmO.js +0 -88
  462. package/dist/_chunks/ssr-data-MjmprTmO.js.map +0 -1
  463. package/dist/_chunks/tracing-Cwn7697K.js.map +0 -1
  464. package/dist/_chunks/use-cookie-DX-l1_5E.js +0 -91
  465. package/dist/_chunks/use-cookie-DX-l1_5E.js.map +0 -1
  466. package/dist/_chunks/use-query-states-D5KaffOK.js.map +0 -1
  467. package/dist/cache/register-cached-function.d.ts +0 -17
  468. package/dist/cache/register-cached-function.d.ts.map +0 -1
  469. package/dist/client/error-boundary.js.map +0 -1
  470. package/dist/client/link-status-provider.d.ts +0 -11
  471. package/dist/client/link-status-provider.d.ts.map +0 -1
  472. package/dist/client/transition-root.d.ts.map +0 -1
  473. package/dist/cookies/index.js.map +0 -1
  474. package/dist/plugins/cache-transform.d.ts +0 -36
  475. package/dist/plugins/cache-transform.d.ts.map +0 -1
  476. package/dist/plugins/dynamic-transform.d.ts +0 -72
  477. package/dist/plugins/dynamic-transform.d.ts.map +0 -1
  478. package/dist/search-params/analyze.d.ts +0 -54
  479. package/dist/search-params/analyze.d.ts.map +0 -1
  480. package/dist/search-params/builtin-codecs.d.ts +0 -105
  481. package/dist/search-params/builtin-codecs.d.ts.map +0 -1
  482. package/dist/search-params/codecs.d.ts +0 -53
  483. package/dist/search-params/codecs.d.ts.map +0 -1
  484. package/dist/search-params/create.d.ts +0 -106
  485. package/dist/search-params/create.d.ts.map +0 -1
  486. package/dist/search-params/index.js.map +0 -1
  487. package/dist/server/prerender.d.ts +0 -77
  488. package/dist/server/prerender.d.ts.map +0 -1
  489. package/dist/server/response-cache.d.ts +0 -53
  490. package/dist/server/response-cache.d.ts.map +0 -1
  491. package/src/cache/register-cached-function.ts +0 -99
  492. package/src/client/link-status-provider.tsx +0 -30
  493. package/src/client/transition-root.tsx +0 -160
  494. package/src/plugins/cache-transform.ts +0 -199
  495. package/src/plugins/dynamic-transform.ts +0 -161
  496. package/src/search-params/analyze.ts +0 -192
  497. package/src/search-params/builtin-codecs.ts +0 -228
  498. package/src/search-params/create.ts +0 -321
  499. package/src/server/prerender.ts +0 -139
  500. package/src/server/response-cache.ts +0 -277
@@ -0,0 +1,72 @@
1
+ import { createContext, createElement, useContext, useMemo } from "react";
2
+ //#region src/shared/merge-search-params.ts
3
+ /**
4
+ * Shared utility for merging preserved search params into a target URL.
5
+ *
6
+ * Used by both <Link> (client) and redirect() (server). Extracted to a shared
7
+ * module to avoid importing client code ('use client') from server modules.
8
+ */
9
+ /**
10
+ * Merge preserved search params from the current URL into a target href.
11
+ *
12
+ * When `preserve` is `true`, all current search params are merged.
13
+ * When `preserve` is a `string[]`, only the named params are merged.
14
+ *
15
+ * The target href's own search params take precedence — preserved params
16
+ * are only added if the target doesn't already define them.
17
+ *
18
+ * @param targetHref - The resolved target href (may already contain query string)
19
+ * @param currentSearch - The current URL's search string (e.g. "?private=access&page=2")
20
+ * @param preserve - `true` to preserve all, or `string[]` to preserve specific params
21
+ * @returns The target href with preserved search params merged in
22
+ */
23
+ function mergePreservedSearchParams(targetHref, currentSearch, preserve) {
24
+ const currentParams = new URLSearchParams(currentSearch);
25
+ if (currentParams.size === 0) return targetHref;
26
+ const hashIdx = targetHref.indexOf("#");
27
+ const hrefWithoutHash = hashIdx >= 0 ? targetHref.slice(0, hashIdx) : targetHref;
28
+ const hash = hashIdx >= 0 ? targetHref.slice(hashIdx) : "";
29
+ const qIdx = hrefWithoutHash.indexOf("?");
30
+ const targetPath = qIdx >= 0 ? hrefWithoutHash.slice(0, qIdx) : hrefWithoutHash;
31
+ const targetParams = new URLSearchParams(qIdx >= 0 ? hrefWithoutHash.slice(qIdx + 1) : "");
32
+ const merged = new URLSearchParams(targetParams);
33
+ for (const [key, value] of currentParams) if (!targetParams.has(key)) {
34
+ if (preserve === true || preserve.includes(key)) merged.append(key, value);
35
+ }
36
+ const qs = merged.toString();
37
+ return (qs ? `${targetPath}?${qs}` : targetPath) + hash;
38
+ }
39
+ //#endregion
40
+ //#region src/client/segment-context.ts
41
+ /**
42
+ * Segment Context — provides layout segment position for useSelectedLayoutSegment hooks.
43
+ *
44
+ * Each layout in the segment tree is wrapped with a SegmentProvider that stores
45
+ * the URL segments from root to the current layout level. The hooks read this
46
+ * context to determine which child segments are active below the calling layout.
47
+ *
48
+ * The context value is intentionally minimal: just the segment path array and
49
+ * parallel route keys. No internal cache details are exposed.
50
+ *
51
+ * Design docs: design/19-client-navigation.md, design/14-ecosystem.md
52
+ */
53
+ var SegmentContext = createContext(null);
54
+ /** Read the segment context. Returns null if no provider is above this component. */
55
+ function useSegmentContext() {
56
+ return useContext(SegmentContext);
57
+ }
58
+ /**
59
+ * Wraps each layout to provide segment position context.
60
+ * Injected by rsc-entry.ts during element tree construction.
61
+ */
62
+ function SegmentProvider({ segments, segmentId: _segmentId, parallelRouteKeys, children }) {
63
+ const value = useMemo(() => ({
64
+ segments,
65
+ parallelRouteKeys
66
+ }), [segments.join("/"), parallelRouteKeys.join(",")]);
67
+ return createElement(SegmentContext.Provider, { value }, children);
68
+ }
69
+ //#endregion
70
+ export { useSegmentContext as n, mergePreservedSearchParams as r, SegmentProvider as t };
71
+
72
+ //# sourceMappingURL=segment-context-hzuJ048X.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"segment-context-hzuJ048X.js","names":[],"sources":["../../src/shared/merge-search-params.ts","../../src/client/segment-context.ts"],"sourcesContent":["/**\n * Shared utility for merging preserved search params into a target URL.\n *\n * Used by both <Link> (client) and redirect() (server). Extracted to a shared\n * module to avoid importing client code ('use client') from server modules.\n */\n\n/**\n * Merge preserved search params from the current URL into a target href.\n *\n * When `preserve` is `true`, all current search params are merged.\n * When `preserve` is a `string[]`, only the named params are merged.\n *\n * The target href's own search params take precedence — preserved params\n * are only added if the target doesn't already define them.\n *\n * @param targetHref - The resolved target href (may already contain query string)\n * @param currentSearch - The current URL's search string (e.g. \"?private=access&page=2\")\n * @param preserve - `true` to preserve all, or `string[]` to preserve specific params\n * @returns The target href with preserved search params merged in\n */\nexport function mergePreservedSearchParams(\n targetHref: string,\n currentSearch: string,\n preserve: true | string[]\n): string {\n const currentParams = new URLSearchParams(currentSearch);\n if (currentParams.size === 0) return targetHref;\n\n // Split hash fragment from target before processing query params.\n // Hash must come after query string: /path?query=value#hash\n const hashIdx = targetHref.indexOf('#');\n const hrefWithoutHash = hashIdx >= 0 ? targetHref.slice(0, hashIdx) : targetHref;\n const hash = hashIdx >= 0 ? targetHref.slice(hashIdx) : '';\n\n // Split target into path and existing query\n const qIdx = hrefWithoutHash.indexOf('?');\n const targetPath = qIdx >= 0 ? hrefWithoutHash.slice(0, qIdx) : hrefWithoutHash;\n const targetParams = new URLSearchParams(qIdx >= 0 ? hrefWithoutHash.slice(qIdx + 1) : '');\n\n // Collect params to preserve (that aren't already in the target)\n const merged = new URLSearchParams(targetParams);\n for (const [key, value] of currentParams) {\n // Only preserve if: (a) not already in target, and (b) included in preserve list\n if (!targetParams.has(key)) {\n if (preserve === true || preserve.includes(key)) {\n merged.append(key, value);\n }\n }\n }\n\n const qs = merged.toString();\n const pathWithQuery = qs ? `${targetPath}?${qs}` : targetPath;\n return pathWithQuery + hash;\n}\n","/**\n * Segment Context — provides layout segment position for useSelectedLayoutSegment hooks.\n *\n * Each layout in the segment tree is wrapped with a SegmentProvider that stores\n * the URL segments from root to the current layout level. The hooks read this\n * context to determine which child segments are active below the calling layout.\n *\n * The context value is intentionally minimal: just the segment path array and\n * parallel route keys. No internal cache details are exposed.\n *\n * Design docs: design/19-client-navigation.md, design/14-ecosystem.md\n */\n\n'use client';\n\nimport { createContext, useContext, createElement, useMemo } from 'react';\n\n// ─── Types ───────────────────────────────────────────────────────\n\nexport interface SegmentContextValue {\n /** URL segments from root to this layout (e.g. ['', 'dashboard', 'settings']) */\n segments: string[];\n /** Parallel route slot keys available at this layout level (e.g. ['sidebar', 'modal']) */\n parallelRouteKeys: string[];\n}\n\n// ─── Context ─────────────────────────────────────────────────────\n\nconst SegmentContext = createContext<SegmentContextValue | null>(null);\n\n/** Read the segment context. Returns null if no provider is above this component. */\nexport function useSegmentContext(): SegmentContextValue | null {\n return useContext(SegmentContext);\n}\n\n// ─── Provider ────────────────────────────────────────────────────\n\ninterface SegmentProviderProps {\n segments: string[];\n /**\n * Unique identifier for this segment, used by the client-side segment\n * merger for element caching. For route groups this includes the group\n * name (e.g., \"/(marketing)\") since groups share their parent's urlPath.\n * Falls back to the reconstructed path from `segments` if not provided.\n */\n segmentId?: string;\n parallelRouteKeys: string[];\n children: React.ReactNode;\n}\n\n/**\n * Wraps each layout to provide segment position context.\n * Injected by rsc-entry.ts during element tree construction.\n */\nexport function SegmentProvider({\n segments,\n segmentId: _segmentId,\n parallelRouteKeys,\n children,\n}: SegmentProviderProps) {\n const value = useMemo(\n () => ({ segments, parallelRouteKeys }),\n // segments and parallelRouteKeys are static per layout — they don't change\n // across navigations. The layout's position in the tree is fixed.\n // Intentionally using derived keys — segments/parallelRouteKeys are static per layout\n [segments.join('/'), parallelRouteKeys.join(',')]\n );\n return createElement(SegmentContext.Provider, { value }, children);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,2BACd,YACA,eACA,UACQ;CACR,MAAM,gBAAgB,IAAI,gBAAgB,cAAc;AACxD,KAAI,cAAc,SAAS,EAAG,QAAO;CAIrC,MAAM,UAAU,WAAW,QAAQ,IAAI;CACvC,MAAM,kBAAkB,WAAW,IAAI,WAAW,MAAM,GAAG,QAAQ,GAAG;CACtE,MAAM,OAAO,WAAW,IAAI,WAAW,MAAM,QAAQ,GAAG;CAGxD,MAAM,OAAO,gBAAgB,QAAQ,IAAI;CACzC,MAAM,aAAa,QAAQ,IAAI,gBAAgB,MAAM,GAAG,KAAK,GAAG;CAChE,MAAM,eAAe,IAAI,gBAAgB,QAAQ,IAAI,gBAAgB,MAAM,OAAO,EAAE,GAAG,GAAG;CAG1F,MAAM,SAAS,IAAI,gBAAgB,aAAa;AAChD,MAAK,MAAM,CAAC,KAAK,UAAU,cAEzB,KAAI,CAAC,aAAa,IAAI,IAAI;MACpB,aAAa,QAAQ,SAAS,SAAS,IAAI,CAC7C,QAAO,OAAO,KAAK,MAAM;;CAK/B,MAAM,KAAK,OAAO,UAAU;AAE5B,SADsB,KAAK,GAAG,WAAW,GAAG,OAAO,cAC5B;;;;;;;;;;;;;;;;ACzBzB,IAAM,iBAAiB,cAA0C,KAAK;;AAGtE,SAAgB,oBAAgD;AAC9D,QAAO,WAAW,eAAe;;;;;;AAsBnC,SAAgB,gBAAgB,EAC9B,UACA,WAAW,YACX,mBACA,YACuB;CACvB,MAAM,QAAQ,eACL;EAAE;EAAU;EAAmB,GAItC,CAAC,SAAS,KAAK,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC,CAClD;AACD,QAAO,cAAc,eAAe,UAAU,EAAE,OAAO,EAAE,SAAS"}
@@ -0,0 +1,64 @@
1
+ //#region src/client/stale-reload.ts
2
+ /**
3
+ * Stale Client Reference Reload
4
+ *
5
+ * When a new deployment ships updated bundles, clients running stale
6
+ * JavaScript may encounter "Could not find the module" errors during
7
+ * RSC Flight stream decoding. This happens because the RSC payload
8
+ * references module IDs from the new bundle that don't exist in the
9
+ * old client bundle.
10
+ *
11
+ * This module detects these specific errors and triggers a full page
12
+ * reload so the browser fetches the new bundle. A sessionStorage flag
13
+ * guards against infinite reload loops.
14
+ *
15
+ * See: LOCAL-332
16
+ */
17
+ var RELOAD_FLAG_KEY = "__timber_stale_reload";
18
+ /**
19
+ * In-memory fallback counter for environments where sessionStorage is
20
+ * unavailable (private browsing, storage full, extension interference).
21
+ * Incremented each time triggerStaleReload() falls into the catch path.
22
+ * If the counter exceeds 0 on a subsequent call, the reload is suppressed
23
+ * to prevent an infinite loop. Resets naturally on page load (module
24
+ * re-evaluates) and can be manually reset via clearStaleReloadFlag().
25
+ */
26
+ var memoryReloadCount = 0;
27
+ /**
28
+ * Trigger a full page reload to pick up new bundles.
29
+ *
30
+ * Sets a sessionStorage flag before reloading. If the flag is already
31
+ * set (meaning we already reloaded once for this reason), we don't
32
+ * reload again — this prevents infinite reload loops if the error
33
+ * persists after reload (e.g., a genuine bug rather than a stale bundle).
34
+ *
35
+ * @returns true if a reload was triggered, false if suppressed (loop guard)
36
+ */
37
+ function triggerStaleReload() {
38
+ try {
39
+ if (sessionStorage.getItem(RELOAD_FLAG_KEY)) {
40
+ console.warn("[timber] Stale client reference detected again after reload. Not reloading to prevent infinite loop. This may indicate a deployment issue — try a hard refresh.");
41
+ return false;
42
+ }
43
+ sessionStorage.setItem(RELOAD_FLAG_KEY, "1");
44
+ console.warn("[timber] Stale client reference detected — the server has been redeployed with new bundles. Reloading to pick up the new version.");
45
+ window.location.reload();
46
+ return true;
47
+ } catch {
48
+ if (document.cookie.includes(RELOAD_FLAG_KEY + "=1") || memoryReloadCount > 0) {
49
+ console.warn("[timber] Stale client reference detected again after reload. Not reloading to prevent infinite loop. This may indicate a deployment issue — try a hard refresh.");
50
+ return false;
51
+ }
52
+ memoryReloadCount++;
53
+ try {
54
+ document.cookie = `${RELOAD_FLAG_KEY}=1; max-age=60; path=/; SameSite=Lax`;
55
+ } catch {}
56
+ console.warn("[timber] Stale client reference detected — the server has been redeployed with new bundles. Reloading to pick up the new version.");
57
+ window.location.reload();
58
+ return true;
59
+ }
60
+ }
61
+ //#endregion
62
+ export { triggerStaleReload };
63
+
64
+ //# sourceMappingURL=stale-reload-BLUC_Pl_.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stale-reload-BLUC_Pl_.js","names":[],"sources":["../../src/client/stale-reload.ts"],"sourcesContent":["/**\n * Stale Client Reference Reload\n *\n * When a new deployment ships updated bundles, clients running stale\n * JavaScript may encounter \"Could not find the module\" errors during\n * RSC Flight stream decoding. This happens because the RSC payload\n * references module IDs from the new bundle that don't exist in the\n * old client bundle.\n *\n * This module detects these specific errors and triggers a full page\n * reload so the browser fetches the new bundle. A sessionStorage flag\n * guards against infinite reload loops.\n *\n * See: LOCAL-332\n */\n\nconst RELOAD_FLAG_KEY = '__timber_stale_reload';\n\n/**\n * In-memory fallback counter for environments where sessionStorage is\n * unavailable (private browsing, storage full, extension interference).\n * Incremented each time triggerStaleReload() falls into the catch path.\n * If the counter exceeds 0 on a subsequent call, the reload is suppressed\n * to prevent an infinite loop. Resets naturally on page load (module\n * re-evaluates) and can be manually reset via clearStaleReloadFlag().\n */\nlet memoryReloadCount = 0;\n\n/**\n * Check if an error is a stale client reference error from React's\n * Flight client. These errors have the message pattern:\n * \"Could not find the module \\\"<id>\\\"\"\n *\n * This is thrown by react-server-dom-webpack's client when the RSC\n * payload references a module ID that doesn't exist in the client's\n * module map — typically because the server has been redeployed with\n * new bundle hashes while the client is still running old JavaScript.\n */\nexport function isStaleClientReference(error: unknown): boolean {\n if (!(error instanceof Error)) return false;\n const msg = error.message;\n return msg.includes('Could not find the module') || msg.includes('client reference not found');\n}\n\n/**\n * Check if an error is a chunk load failure from a dynamic import.\n *\n * After a deployment, old chunk filenames no longer exist. When the client\n * tries to dynamically import a chunk that's been replaced, the browser\n * throws one of these errors:\n *\n * - Chromium: \"Failed to fetch dynamically imported module: <url>\"\n * - Firefox: \"error loading dynamically imported module: <url>\"\n * - Safari: \"Importing a module script failed.\"\n * - Vite/Rollup: \"Unable to preload CSS for <url>\"\n *\n * See TIM-446\n */\nexport function isChunkLoadError(error: unknown): boolean {\n if (!(error instanceof Error)) return false;\n const msg = error.message.toLowerCase();\n return (\n msg.includes('failed to fetch dynamically imported module') ||\n msg.includes('error loading dynamically imported module') ||\n msg.includes('importing a module script failed') ||\n msg.includes('unable to preload css') ||\n // Webpack-style chunk load errors (unlikely in Vite but defensive)\n msg.includes('loading chunk') ||\n msg.includes('loading css chunk')\n );\n}\n\n/**\n * Trigger a full page reload to pick up new bundles.\n *\n * Sets a sessionStorage flag before reloading. If the flag is already\n * set (meaning we already reloaded once for this reason), we don't\n * reload again — this prevents infinite reload loops if the error\n * persists after reload (e.g., a genuine bug rather than a stale bundle).\n *\n * @returns true if a reload was triggered, false if suppressed (loop guard)\n */\nexport function triggerStaleReload(): boolean {\n try {\n // Check if we already reloaded — prevent infinite loop\n if (sessionStorage.getItem(RELOAD_FLAG_KEY)) {\n console.warn(\n '[timber] Stale client reference detected again after reload. ' +\n 'Not reloading to prevent infinite loop. ' +\n 'This may indicate a deployment issue — try a hard refresh.'\n );\n return false;\n }\n\n // Set the flag before reloading\n sessionStorage.setItem(RELOAD_FLAG_KEY, '1');\n\n console.warn(\n '[timber] Stale client reference detected — the server has been ' +\n 'redeployed with new bundles. Reloading to pick up the new version.'\n );\n\n window.location.reload();\n return true;\n } catch {\n // sessionStorage unavailable (private browsing, storage full, etc.)\n // Use document.cookie as a reload-persistent fallback loop guard.\n // Module-level memoryReloadCount resets on every reload, so it can't\n // detect cross-reload loops. Cookies persist across reloads and are\n // available even when sessionStorage is blocked (TIM-576).\n const cookieFlag = document.cookie.includes(RELOAD_FLAG_KEY + '=1');\n if (cookieFlag || memoryReloadCount > 0) {\n console.warn(\n '[timber] Stale client reference detected again after reload. ' +\n 'Not reloading to prevent infinite loop. ' +\n 'This may indicate a deployment issue — try a hard refresh.'\n );\n return false;\n }\n\n memoryReloadCount++;\n // Set a short-lived cookie (60s) as the persistent loop guard.\n // It auto-expires so it won't block future legitimate reloads.\n try {\n document.cookie = `${RELOAD_FLAG_KEY}=1; max-age=60; path=/; SameSite=Lax`;\n } catch {\n // Cookie API unavailable — proceed anyway, memoryReloadCount guards same-page loops\n }\n console.warn(\n '[timber] Stale client reference detected — the server has been ' +\n 'redeployed with new bundles. Reloading to pick up the new version.'\n );\n window.location.reload();\n return true;\n }\n}\n\n/**\n * Clear the stale reload flag. Called on successful bootstrap to reset\n * the loop guard — if the page loaded successfully, the next stale\n * reference error should trigger a fresh reload attempt.\n */\nexport function clearStaleReloadFlag(): void {\n memoryReloadCount = 0;\n try {\n sessionStorage.removeItem(RELOAD_FLAG_KEY);\n } catch {\n // sessionStorage unavailable — nothing to clear\n }\n // Also clear the cookie fallback\n try {\n document.cookie = `${RELOAD_FLAG_KEY}=; max-age=0; path=/; SameSite=Lax`;\n } catch {\n // Cookie API unavailable\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAgBA,IAAM,kBAAkB;;;;;;;;;AAUxB,IAAI,oBAAoB;;;;;;;;;;;AAwDxB,SAAgB,qBAA8B;AAC5C,KAAI;AAEF,MAAI,eAAe,QAAQ,gBAAgB,EAAE;AAC3C,WAAQ,KACN,kKAGD;AACD,UAAO;;AAIT,iBAAe,QAAQ,iBAAiB,IAAI;AAE5C,UAAQ,KACN,oIAED;AAED,SAAO,SAAS,QAAQ;AACxB,SAAO;SACD;AAON,MADmB,SAAS,OAAO,SAAS,kBAAkB,KAAK,IACjD,oBAAoB,GAAG;AACvC,WAAQ,KACN,kKAGD;AACD,UAAO;;AAGT;AAGA,MAAI;AACF,YAAS,SAAS,GAAG,gBAAgB;UAC/B;AAGR,UAAQ,KACN,oIAED;AACD,SAAO,SAAS,QAAQ;AACxB,SAAO"}
@@ -106,4 +106,4 @@ function bindUseQueryStates(definition) {
106
106
  //#endregion
107
107
  export { registerSearchParams as i, useQueryStates$1 as n, getSearchParams as r, bindUseQueryStates as t };
108
108
 
109
- //# sourceMappingURL=use-query-states-D5KaffOK.js.map
109
+ //# sourceMappingURL=use-query-states-DAhgj8Gx.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-query-states-DAhgj8Gx.js","names":[],"sources":["../../src/search-params/registry.ts","../../src/client/use-query-states.ts"],"sourcesContent":["/**\n * Runtime registry for route-scoped search params definitions.\n *\n * When a route's modules load, the framework registers its search-params\n * definition here. useQueryStates('/route') resolves codecs from this map.\n *\n * Design doc: design/23-search-params.md §\"Runtime: Registration at Route Load\"\n */\n\nimport type { SearchParamsDefinition } from './define.js';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst registry = new Map<string, SearchParamsDefinition<any>>();\n\n/**\n * Register a route's search params definition.\n * Called by the generated route manifest loader when a route's modules load.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function registerSearchParams(route: string, definition: SearchParamsDefinition<any>): void {\n registry.set(route, definition);\n}\n\n/**\n * Look up a route's search params definition.\n * Returns undefined if the route hasn't been loaded yet.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function getSearchParams(route: string): SearchParamsDefinition<any> | undefined {\n return registry.get(route);\n}\n","/**\n * useQueryStates — client-side hook for URL-synced search params.\n *\n * Delegates to nuqs for URL synchronization, batching, React 19 transitions,\n * and throttled URL writes. Bridges timber's SearchParamCodec protocol to\n * nuqs-compatible parsers.\n *\n * Design doc: design/23-search-params.md §\"Codec Bridge\"\n */\n\n'use client';\n\nimport { useQueryStates as nuqsUseQueryStates } from 'nuqs';\nimport type { SingleParser } from 'nuqs';\nimport type {\n SearchParamCodec,\n SearchParamsDefinition,\n SetParams,\n QueryStatesOptions,\n} from '../search-params/define.js';\nimport { getSearchParams } from '../search-params/registry.js';\n\n// ─── Codec Bridge ─────────────────────────────────────────────────\n\n/**\n * Bridge a timber SearchParamCodec to a nuqs-compatible SingleParser.\n *\n * nuqs parsers: { parse(string) → T|null, serialize?(T) → string, eq?, defaultValue? }\n * timber codecs: { parse(string|string[]|undefined) → T, serialize(T) → string|null }\n */\nfunction bridgeCodec<T>(codec: SearchParamCodec<T>): SingleParser<T> & { defaultValue: T } {\n return {\n parse: (v: string) => codec.parse(v),\n serialize: (v: T) => codec.serialize(v) ?? '',\n defaultValue: codec.parse(undefined) as T,\n eq: (a: T, b: T) => codec.serialize(a) === codec.serialize(b),\n };\n}\n\n/**\n * Bridge an entire codec map to nuqs-compatible parsers.\n */\nfunction bridgeCodecs<T extends Record<string, unknown>>(codecs: {\n [K in keyof T]: SearchParamCodec<T[K]>;\n}) {\n const result: Record<string, SingleParser<unknown> & { defaultValue: unknown }> = {};\n for (const key of Object.keys(codecs)) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n result[key] = bridgeCodec(codecs[key as keyof T]) as any;\n }\n return result as { [K in keyof T]: SingleParser<T[K]> & { defaultValue: T[K] } };\n}\n\n// ─── Hook ─────────────────────────────────────────────────────────\n\n/**\n * Read and write typed search params from/to the URL.\n *\n * Delegates to nuqs internally. The timber nuqs adapter (auto-injected in\n * browser-entry.ts) handles RSC navigation on non-shallow updates.\n *\n * Usage:\n * ```ts\n * // Via a SearchParamsDefinition\n * const [params, setParams] = definition.useQueryStates()\n *\n * // Standalone with inline codecs\n * const [params, setParams] = useQueryStates({\n * page: fromSchema(z.coerce.number().int().min(1).default(1)),\n * })\n * ```\n */\nexport function useQueryStates<T extends Record<string, unknown>>(\n codecsOrRoute: { [K in keyof T]: SearchParamCodec<T[K]> } | string,\n _options?: QueryStatesOptions,\n urlKeys?: Readonly<Record<string, string>>\n): [T, SetParams<T>] {\n // Route-string overload: resolve codecs from the registry\n let codecs: { [K in keyof T]: SearchParamCodec<T[K]> };\n let resolvedUrlKeys = urlKeys;\n if (typeof codecsOrRoute === 'string') {\n const definition = getSearchParams(codecsOrRoute);\n if (!definition) {\n throw new Error(\n `useQueryStates('${codecsOrRoute}'): no search params registered for this route. ` +\n `Either the route has no search-params.ts file, or it hasn't been loaded yet. ` +\n `For cross-route usage, import the definition explicitly.`\n );\n }\n codecs = definition.codecs as { [K in keyof T]: SearchParamCodec<T[K]> };\n resolvedUrlKeys = definition.urlKeys;\n } else {\n codecs = codecsOrRoute;\n }\n\n const bridged = bridgeCodecs(codecs);\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const nuqsOptions: any = {};\n if (resolvedUrlKeys && Object.keys(resolvedUrlKeys).length > 0) {\n nuqsOptions.urlKeys = resolvedUrlKeys;\n }\n\n let values: Record<string, unknown>;\n let setValues: Function;\n try {\n [values, setValues] = nuqsUseQueryStates(bridged, nuqsOptions);\n } catch (err) {\n if (\n err instanceof Error &&\n /Invalid hook call|cannot be called|Cannot read properties of null/i.test(err.message)\n ) {\n throw new Error(\n 'useQueryStates is a client component hook and cannot be called outside a React component. ' +\n 'Use definition.parse(searchParams) in server components instead.'\n );\n }\n throw err;\n }\n\n // Wrap the nuqs setter to match timber's SetParams<T> signature.\n // nuqs's setter accepts Partial<Nullable<Values>> | UpdaterFn | null.\n // timber's setter accepts Partial<T> with optional SetParamsOptions.\n const setParams: SetParams<T> = (partial, setOptions?) => {\n const nuqsSetOptions: Record<string, unknown> = {};\n if (setOptions?.shallow !== undefined) nuqsSetOptions.shallow = setOptions.shallow;\n if (setOptions?.scroll !== undefined) nuqsSetOptions.scroll = setOptions.scroll;\n if (setOptions?.history !== undefined) nuqsSetOptions.history = setOptions.history;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n void setValues(partial as any, nuqsSetOptions);\n };\n\n return [values as T, setParams];\n}\n\n// ─── Definition binding ───────────────────────────────────────────\n\n/**\n * Create a useQueryStates binding for a SearchParamsDefinition.\n * This is used internally by SearchParamsDefinition.useQueryStates().\n */\nexport function bindUseQueryStates<T extends Record<string, unknown>>(\n definition: SearchParamsDefinition<T>\n): (options?: QueryStatesOptions) => [T, SetParams<T>] {\n return (options?: QueryStatesOptions) => {\n return useQueryStates<T>(definition.codecs, options, definition.urlKeys);\n };\n}\n"],"mappings":";;AAYA,IAAM,2BAAW,IAAI,KAA0C;;;;;AAO/D,SAAgB,qBAAqB,OAAe,YAA+C;AACjG,UAAS,IAAI,OAAO,WAAW;;;;;;AAQjC,SAAgB,gBAAgB,OAAwD;AACtF,QAAO,SAAS,IAAI,MAAM;;;;;;;;;;;;;;;;;;;ACC5B,SAAS,YAAe,OAAmE;AACzF,QAAO;EACL,QAAQ,MAAc,MAAM,MAAM,EAAE;EACpC,YAAY,MAAS,MAAM,UAAU,EAAE,IAAI;EAC3C,cAAc,MAAM,MAAM,KAAA,EAAU;EACpC,KAAK,GAAM,MAAS,MAAM,UAAU,EAAE,KAAK,MAAM,UAAU,EAAE;EAC9D;;;;;AAMH,SAAS,aAAgD,QAEtD;CACD,MAAM,SAA4E,EAAE;AACpF,MAAK,MAAM,OAAO,OAAO,KAAK,OAAO,CAEnC,QAAO,OAAO,YAAY,OAAO,KAAgB;AAEnD,QAAO;;;;;;;;;;;;;;;;;;;AAsBT,SAAgB,iBACd,eACA,UACA,SACmB;CAEnB,IAAI;CACJ,IAAI,kBAAkB;AACtB,KAAI,OAAO,kBAAkB,UAAU;EACrC,MAAM,aAAa,gBAAgB,cAAc;AACjD,MAAI,CAAC,WACH,OAAM,IAAI,MACR,mBAAmB,cAAc,uLAGlC;AAEH,WAAS,WAAW;AACpB,oBAAkB,WAAW;OAE7B,UAAS;CAGX,MAAM,UAAU,aAAa,OAAO;CAGpC,MAAM,cAAmB,EAAE;AAC3B,KAAI,mBAAmB,OAAO,KAAK,gBAAgB,CAAC,SAAS,EAC3D,aAAY,UAAU;CAGxB,IAAI;CACJ,IAAI;AACJ,KAAI;AACF,GAAC,QAAQ,aAAa,eAAmB,SAAS,YAAY;UACvD,KAAK;AACZ,MACE,eAAe,SACf,qEAAqE,KAAK,IAAI,QAAQ,CAEtF,OAAM,IAAI,MACR,6JAED;AAEH,QAAM;;CAMR,MAAM,aAA2B,SAAS,eAAgB;EACxD,MAAM,iBAA0C,EAAE;AAClD,MAAI,YAAY,YAAY,KAAA,EAAW,gBAAe,UAAU,WAAW;AAC3E,MAAI,YAAY,WAAW,KAAA,EAAW,gBAAe,SAAS,WAAW;AACzE,MAAI,YAAY,YAAY,KAAA,EAAW,gBAAe,UAAU,WAAW;AAEtE,YAAU,SAAgB,eAAe;;AAGhD,QAAO,CAAC,QAAa,UAAU;;;;;;AASjC,SAAgB,mBACd,YACqD;AACrD,SAAQ,YAAiC;AACvC,SAAO,iBAAkB,WAAW,QAAQ,SAAS,WAAW,QAAQ"}
@@ -0,0 +1,63 @@
1
+ //#region src/search-params/wrappers.ts
2
+ /**
3
+ * Wrap a nullable codec with a default value. When the inner codec returns
4
+ * null, the default is used instead. The output type becomes non-nullable.
5
+ *
6
+ * Works with any codec — nuqs parsers, custom codecs, fromSchema results.
7
+ *
8
+ * ```ts
9
+ * import { parseAsInteger } from 'nuqs'
10
+ * import { withDefault } from '@timber-js/app/search-params'
11
+ *
12
+ * const page = withDefault(parseAsInteger, 1)
13
+ * // page.parse(undefined) → 1 (not null)
14
+ * // page.parse('5') → 5
15
+ * ```
16
+ */
17
+ function withDefault(codec, defaultValue) {
18
+ return {
19
+ parse(value) {
20
+ const result = codec.parse(value);
21
+ return result === null ? defaultValue : result;
22
+ },
23
+ serialize(value) {
24
+ return codec.serialize(value);
25
+ }
26
+ };
27
+ }
28
+ /**
29
+ * Attach a URL key alias to a codec. The alias determines what query
30
+ * parameter key is used in the URL, while the TypeScript property name
31
+ * stays descriptive.
32
+ *
33
+ * Aliases travel with codecs through object spread composition — when
34
+ * you spread a bundle containing aliased codecs into defineSearchParams,
35
+ * the aliases come along automatically.
36
+ *
37
+ * ```ts
38
+ * import { parseAsString } from 'nuqs'
39
+ * import { withUrlKey } from '@timber-js/app/search-params'
40
+ *
41
+ * export const searchable = {
42
+ * q: withUrlKey(parseAsString, 'search'),
43
+ * // ?search=shoes → { q: 'shoes' }
44
+ * }
45
+ * ```
46
+ *
47
+ * Composes with withDefault:
48
+ * ```ts
49
+ * import { parseAsInteger } from 'nuqs'
50
+ * withUrlKey(withDefault(parseAsInteger, 1), 'p')
51
+ * ```
52
+ */
53
+ function withUrlKey(codec, urlKey) {
54
+ return {
55
+ parse: codec.parse.bind(codec),
56
+ serialize: codec.serialize.bind(codec),
57
+ urlKey
58
+ };
59
+ }
60
+ //#endregion
61
+ export { withUrlKey as n, withDefault as t };
62
+
63
+ //# sourceMappingURL=wrappers-LZbghvn0.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wrappers-LZbghvn0.js","names":[],"sources":["../../src/search-params/wrappers.ts"],"sourcesContent":["/**\n * Codec wrappers — withDefault and withUrlKey.\n *\n * These are timber-specific utilities that work with any SearchParamCodec.\n * For actual codecs (string, integer, boolean, etc.), use nuqs parsers\n * or Standard Schema objects (Zod, Valibot, ArkType) with auto-detection.\n *\n * Design doc: design/23-search-params.md\n */\n\nimport type { SearchParamCodec, SearchParamCodecWithUrlKey } from './define.js';\n\n// ---------------------------------------------------------------------------\n// withDefault\n// ---------------------------------------------------------------------------\n\n/**\n * Wrap a nullable codec with a default value. When the inner codec returns\n * null, the default is used instead. The output type becomes non-nullable.\n *\n * Works with any codec — nuqs parsers, custom codecs, fromSchema results.\n *\n * ```ts\n * import { parseAsInteger } from 'nuqs'\n * import { withDefault } from '@timber-js/app/search-params'\n *\n * const page = withDefault(parseAsInteger, 1)\n * // page.parse(undefined) → 1 (not null)\n * // page.parse('5') → 5\n * ```\n */\nexport function withDefault<T>(\n codec: SearchParamCodec<T | null>,\n defaultValue: T\n): SearchParamCodec<T> {\n return {\n parse(value: string | string[] | undefined): T {\n const result = codec.parse(value);\n return result === null ? defaultValue : result;\n },\n serialize(value: T): string | null {\n return codec.serialize(value);\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// withUrlKey\n// ---------------------------------------------------------------------------\n\n/**\n * Attach a URL key alias to a codec. The alias determines what query\n * parameter key is used in the URL, while the TypeScript property name\n * stays descriptive.\n *\n * Aliases travel with codecs through object spread composition — when\n * you spread a bundle containing aliased codecs into defineSearchParams,\n * the aliases come along automatically.\n *\n * ```ts\n * import { parseAsString } from 'nuqs'\n * import { withUrlKey } from '@timber-js/app/search-params'\n *\n * export const searchable = {\n * q: withUrlKey(parseAsString, 'search'),\n * // ?search=shoes → { q: 'shoes' }\n * }\n * ```\n *\n * Composes with withDefault:\n * ```ts\n * import { parseAsInteger } from 'nuqs'\n * withUrlKey(withDefault(parseAsInteger, 1), 'p')\n * ```\n */\nexport function withUrlKey<T>(\n codec: SearchParamCodec<T>,\n urlKey: string\n): SearchParamCodecWithUrlKey<T> {\n return {\n parse: codec.parse.bind(codec),\n serialize: codec.serialize.bind(codec),\n urlKey,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA+BA,SAAgB,YACd,OACA,cACqB;AACrB,QAAO;EACL,MAAM,OAAyC;GAC7C,MAAM,SAAS,MAAM,MAAM,MAAM;AACjC,UAAO,WAAW,OAAO,eAAe;;EAE1C,UAAU,OAAyB;AACjC,UAAO,MAAM,UAAU,MAAM;;EAEhC;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCH,SAAgB,WACd,OACA,QAC+B;AAC/B,QAAO;EACL,OAAO,MAAM,MAAM,KAAK,MAAM;EAC9B,WAAW,MAAM,UAAU,KAAK,MAAM;EACtC;EACD"}
@@ -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 { runWithBindings } from "./cloudflare.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;AAC/F,KAAI;AACF,SAAO,MAAM,OAAO;SACd;AACN,QAAM,IAAI,MACR,uIAGD;;;;;;;;;;AAsBL,IAAa,0BAA0B,OAAO,IAAI,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8D/E,SAAgB,sBAAsB,UAAwC,EAAE,EAAU;AACxF,QAAO;EACL,MAAM;EAMN,OAAO;EAEP,MAAM,gBAAgB,QAAuB;GAG3C,MAAM,EAAE,qBAAqB,OAAO,QAAQ,iBAAiB,eAAe;GAG5E,MAAM,eAAwC,EAC5C,SAAS,QAAQ,WAAW,MAC7B;AACD,OAAI,QAAQ,WACV,cAAa,aAAa,QAAQ;AAEpC,OAAI,QAAQ,YACV,cAAa,cAAc,QAAQ;GAGrC,MAAM,QAAQ,MAAM,iBAAiB,aAAa;AAMjD,UAAe,4BAA+B,OAAmB;AAChE,WAAO,gBAAgB,MAAM,KAAgC,GAAG;;AAKlE,UAAO,YAAY,GAAG,eAAe;AACnC,UAAM,SAAS,CAAC,YAAY,GAE1B;KACF;;EAEL"}