@farm.js/core 0.1.0-beta.95 → 0.1.0-beta.97

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 (317) hide show
  1. package/dist/after.cjs +1 -1
  2. package/dist/after.mjs +1 -1
  3. package/dist/agent-runtime.d.mts +3 -2
  4. package/dist/agent-runtime.d.ts +3 -2
  5. package/dist/api/route-manager.cjs +43 -4
  6. package/dist/api/route-manager.d.mts +4 -3
  7. package/dist/api/route-manager.d.ts +4 -3
  8. package/dist/api/route-manager.mjs +7 -7
  9. package/dist/api/runtime.cjs +43 -4
  10. package/dist/api/runtime.d.mts +1 -1
  11. package/dist/api/runtime.d.ts +1 -1
  12. package/dist/api/runtime.mjs +5 -5
  13. package/dist/api.cjs +352 -109
  14. package/dist/api.d.mts +7 -6
  15. package/dist/api.d.ts +7 -6
  16. package/dist/api.mjs +19 -12
  17. package/dist/{app-CIIEvA4r.d.ts → app-CIOx3LvY.d.ts} +4 -4
  18. package/dist/{app-O4AEC1OH.d.mts → app-DBd6437H.d.mts} +4 -4
  19. package/dist/app-markdown.d.mts +4 -3
  20. package/dist/app-markdown.d.ts +4 -3
  21. package/dist/cache.cjs +42 -4
  22. package/dist/cache.d.mts +68 -1
  23. package/dist/cache.d.ts +68 -1
  24. package/dist/cache.mjs +3 -3
  25. package/dist/{chunk-AXVJCMVF.mjs → chunk-2HDOV47R.mjs} +3 -3
  26. package/dist/chunk-2HDOV47R.mjs.map +1 -0
  27. package/dist/{chunk-RBRLLZL5.mjs → chunk-34IAPZBG.mjs} +16 -3
  28. package/dist/chunk-34IAPZBG.mjs.map +1 -0
  29. package/dist/{chunk-VV24CC42.mjs → chunk-35NPLKQJ.mjs} +2 -2
  30. package/dist/{chunk-D7QH7MDU.mjs → chunk-3TWQERDE.mjs} +5 -4
  31. package/dist/chunk-3TWQERDE.mjs.map +1 -0
  32. package/dist/{chunk-RWYRFCLG.mjs → chunk-4X57GXQA.mjs} +2 -2
  33. package/dist/{chunk-KOTSX5JH.mjs → chunk-52BR7LTX.mjs} +30 -21
  34. package/dist/chunk-52BR7LTX.mjs.map +1 -0
  35. package/dist/{chunk-SALMKQXH.mjs → chunk-6EJHNHH4.mjs} +80 -27
  36. package/dist/chunk-6EJHNHH4.mjs.map +1 -0
  37. package/dist/{chunk-ZFNK77WN.mjs → chunk-6JNGOC37.mjs} +2 -2
  38. package/dist/{after.cjs.map → chunk-6JNGOC37.mjs.map} +1 -1
  39. package/dist/{chunk-MOW47IF5.mjs → chunk-6UYVU46O.mjs} +2 -2
  40. package/dist/{chunk-7MABZJIM.mjs → chunk-7PYVLJ4J.mjs} +1 -1
  41. package/dist/chunk-7PYVLJ4J.mjs.map +1 -0
  42. package/dist/{chunk-FLHLPB57.mjs → chunk-D7F7YZ7L.mjs} +93 -67
  43. package/dist/chunk-D7F7YZ7L.mjs.map +1 -0
  44. package/dist/chunk-DU3PKDVQ.mjs +35 -0
  45. package/dist/chunk-DU3PKDVQ.mjs.map +1 -0
  46. package/dist/{chunk-SCFX4UTD.mjs → chunk-EHTUKVSW.mjs} +1 -1
  47. package/dist/chunk-EHTUKVSW.mjs.map +1 -0
  48. package/dist/{chunk-KWCNQUH5.mjs → chunk-EPDIF432.mjs} +526 -50
  49. package/dist/chunk-EPDIF432.mjs.map +1 -0
  50. package/dist/{chunk-A3636IHN.mjs → chunk-FP5Q67FO.mjs} +167 -96
  51. package/dist/chunk-FP5Q67FO.mjs.map +1 -0
  52. package/dist/{chunk-HHZAOTQD.mjs → chunk-GJ7W6LNK.mjs} +7 -6
  53. package/dist/chunk-GJ7W6LNK.mjs.map +1 -0
  54. package/dist/{chunk-RLGUZ3HS.mjs → chunk-I3OOUWO5.mjs} +3 -3
  55. package/dist/{chunk-75CGAL6E.mjs → chunk-IZBX2TEU.mjs} +217 -105
  56. package/dist/chunk-IZBX2TEU.mjs.map +1 -0
  57. package/dist/{chunk-22VG4DFJ.mjs → chunk-J3MPQ4MQ.mjs} +2 -2
  58. package/dist/{chunk-22VG4DFJ.mjs.map → chunk-J3MPQ4MQ.mjs.map} +1 -1
  59. package/dist/{chunk-2LS3KKE7.mjs → chunk-JV7JUD7Q.mjs} +4 -4
  60. package/dist/{chunk-Q3OX763A.mjs → chunk-LXDASSTE.mjs} +2 -2
  61. package/dist/{chunk-ZRBCBOEX.mjs → chunk-N2FY2QZ7.mjs} +28 -3
  62. package/dist/chunk-N2FY2QZ7.mjs.map +1 -0
  63. package/dist/{chunk-MRVJCLYQ.mjs → chunk-PSQ7N4XP.mjs} +4 -2
  64. package/dist/chunk-PSQ7N4XP.mjs.map +1 -0
  65. package/dist/{chunk-HVG3HLQZ.mjs → chunk-Q7WGOOAI.mjs} +3 -3
  66. package/dist/{chunk-WTYAPO5I.mjs → chunk-RCNWMEBT.mjs} +3 -2
  67. package/dist/{chunk-WTYAPO5I.mjs.map → chunk-RCNWMEBT.mjs.map} +1 -1
  68. package/dist/{chunk-3INDBMUU.mjs → chunk-TGDIACZT.mjs} +2 -2
  69. package/dist/{chunk-WB75GIX2.mjs → chunk-TQTB33JS.mjs} +14 -3
  70. package/dist/chunk-TQTB33JS.mjs.map +1 -0
  71. package/dist/{chunk-MH27UH72.mjs → chunk-TT3E2JOF.mjs} +3 -3
  72. package/dist/{chunk-UWRGX3J3.mjs → chunk-UMUWR5XA.mjs} +2 -2
  73. package/dist/{chunk-XTLLHCWU.mjs → chunk-V4VRLVLW.mjs} +52 -31
  74. package/dist/chunk-V4VRLVLW.mjs.map +1 -0
  75. package/dist/{chunk-EXCGBERG.mjs → chunk-WD2EBM3I.mjs} +79 -17
  76. package/dist/chunk-WD2EBM3I.mjs.map +1 -0
  77. package/dist/{chunk-DLBUAJTK.mjs → chunk-WMJGA32P.mjs} +74 -5
  78. package/dist/chunk-WMJGA32P.mjs.map +1 -0
  79. package/dist/{chunk-TKQCJMY7.mjs → chunk-X4SFHKFH.mjs} +7 -4
  80. package/dist/{chunk-TKQCJMY7.mjs.map → chunk-X4SFHKFH.mjs.map} +1 -1
  81. package/dist/{chunk-Q7GPJZCO.mjs → chunk-YIBV77KZ.mjs} +26 -7
  82. package/dist/chunk-YIBV77KZ.mjs.map +1 -0
  83. package/dist/client/lifecycle.mjs +2 -2
  84. package/dist/{client-mcMC334J.d.mts → client-DWoLZ3QU.d.mts} +52 -5
  85. package/dist/{client-d5ONQ-Pd.d.ts → client-DuQuQC1h.d.ts} +52 -5
  86. package/dist/client-cache-BMxuFqwH.d.ts +18 -0
  87. package/dist/client-cache-CCK-fCe0.d.mts +18 -0
  88. package/dist/{client-plugins-BvClItiL.d.mts → client-plugins-B6-07YmP.d.mts} +52 -99
  89. package/dist/{client-plugins-B9Sq-iMg.d.ts → client-plugins-By6MVUX-.d.ts} +52 -99
  90. package/dist/client-plugins.cjs +1 -1
  91. package/dist/client-plugins.d.mts +3 -2
  92. package/dist/client-plugins.d.ts +3 -2
  93. package/dist/client-plugins.mjs +2 -2
  94. package/dist/client.cjs +1046 -211
  95. package/dist/client.d.mts +136 -18
  96. package/dist/client.d.ts +136 -18
  97. package/dist/client.mjs +32 -15
  98. package/dist/config.d.mts +3 -2
  99. package/dist/config.d.ts +3 -2
  100. package/dist/{devtools-S52RRRMN.mjs → devtools-XWZX6CCL.mjs} +5 -5
  101. package/dist/{devtools-client-3XRTBND5.mjs → devtools-client-Z7QQA3Q2.mjs} +56 -17
  102. package/dist/devtools-client-Z7QQA3Q2.mjs.map +1 -0
  103. package/dist/{devtools-ui-NJKFORTG.mjs → devtools-ui-2HG5M4EL.mjs} +3 -1
  104. package/dist/devtools-ui-2HG5M4EL.mjs.map +1 -0
  105. package/dist/docs.cjs +24 -5
  106. package/dist/docs.mjs +5 -5
  107. package/dist/i18n/server.cjs +13 -2
  108. package/dist/i18n/server.d.mts +2 -2
  109. package/dist/i18n/server.d.ts +2 -2
  110. package/dist/i18n/server.mjs +1 -1
  111. package/dist/index.cjs +1928 -894
  112. package/dist/index.d.mts +139 -21
  113. package/dist/index.d.ts +139 -21
  114. package/dist/index.mjs +57 -34
  115. package/dist/index.mjs.map +1 -1
  116. package/dist/integration-api-BT024nuJ.d.mts +97 -0
  117. package/dist/integration-api-BT024nuJ.d.ts +97 -0
  118. package/dist/integrations.d.mts +3 -2
  119. package/dist/integrations.d.ts +3 -2
  120. package/dist/internal/build-runtime.cjs +764 -547
  121. package/dist/internal/build-runtime.d.mts +5 -4
  122. package/dist/internal/build-runtime.d.ts +5 -4
  123. package/dist/internal/build-runtime.mjs +16 -16
  124. package/dist/internal/client-runtime.cjs +1 -1
  125. package/dist/internal/client-runtime.mjs +2 -2
  126. package/dist/internal/config-runtime.cjs +4 -1
  127. package/dist/internal/config-runtime.d.mts +4 -3
  128. package/dist/internal/config-runtime.d.ts +4 -3
  129. package/dist/internal/config-runtime.mjs +4 -4
  130. package/dist/internal/product-telemetry-runtime.cjs +1 -1
  131. package/dist/internal/product-telemetry-runtime.mjs +1 -1
  132. package/dist/internal/production-runtime.cjs +29 -3
  133. package/dist/internal/production-runtime.d.mts +8 -7
  134. package/dist/internal/production-runtime.d.ts +8 -7
  135. package/dist/internal/production-runtime.mjs +5 -5
  136. package/dist/{metadata-route-yV4U6X8h.d.ts → metadata-route-8_V3UonT.d.ts} +1 -1
  137. package/dist/{metadata-route-p4K1l92V.d.mts → metadata-route-CWP_HjGU.d.mts} +1 -1
  138. package/dist/middleware.cjs +28 -2
  139. package/dist/middleware.d.mts +5 -4
  140. package/dist/middleware.d.ts +5 -4
  141. package/dist/middleware.mjs +4 -4
  142. package/dist/navigation.cjs +3 -1
  143. package/dist/navigation.mjs +3 -3
  144. package/dist/observability.cjs +27 -2
  145. package/dist/observability.mjs +1 -1
  146. package/dist/plugin.cjs +528 -349
  147. package/dist/plugin.d.mts +3 -2
  148. package/dist/plugin.d.ts +3 -2
  149. package/dist/plugin.mjs +13 -13
  150. package/dist/{production-runtime-IkB0Qj4i.d.mts → production-runtime-BGRH1dKG.d.mts} +1 -1
  151. package/dist/{production-runtime-0JTch4_d.d.ts → production-runtime-CdmzsDax.d.ts} +1 -1
  152. package/dist/query/client.cjs +68 -29
  153. package/dist/query/client.mjs +69 -30
  154. package/dist/query/client.mjs.map +1 -1
  155. package/dist/{render-plan-Dc8CjNI7.d.ts → render-plan-0GeHiGVZ.d.ts} +1 -1
  156. package/dist/{render-plan-CU31j-Jk.d.mts → render-plan-DLxJYAA5.d.mts} +1 -1
  157. package/dist/renderer-client.cjs +169 -26
  158. package/dist/renderer-client.d.mts +7 -6
  159. package/dist/renderer-client.d.ts +7 -6
  160. package/dist/renderer-client.mjs +16 -19
  161. package/dist/renderer-client.mjs.map +1 -1
  162. package/dist/{request-BXa1KY8i.d.mts → request-BCNXSXLh.d.mts} +1 -1
  163. package/dist/{request-CUUBujZt.d.ts → request-BstWbZ6O.d.ts} +1 -1
  164. package/dist/request.d.mts +4 -3
  165. package/dist/request.d.ts +4 -3
  166. package/dist/{route-Y8lfz1wF.d.ts → route-4pd-EVtw.d.ts} +45 -50
  167. package/dist/{route-Cq3aObmj.d.mts → route-CvEr4Uc9.d.mts} +45 -50
  168. package/dist/routes.cjs +27 -2
  169. package/dist/routes.d.mts +3 -2
  170. package/dist/routes.d.ts +3 -2
  171. package/dist/routes.mjs +4 -4
  172. package/dist/{runtime-j1S3sDTh.d.ts → runtime-BgDQzBiu.d.ts} +1 -0
  173. package/dist/{runtime-DDwvDtS4.d.mts → runtime-CV2UCV-5.d.mts} +1 -0
  174. package/dist/server-action-security.mjs +2 -2
  175. package/dist/server-fn-client.cjs +102 -26
  176. package/dist/server-fn-client.d.mts +6 -0
  177. package/dist/server-fn-client.d.ts +6 -0
  178. package/dist/server-fn-client.mjs +2 -1
  179. package/dist/server-fn.cjs +42 -4
  180. package/dist/server-fn.mjs +5 -5
  181. package/dist/server-plugins.d.mts +4 -3
  182. package/dist/server-plugins.d.ts +4 -3
  183. package/dist/server-query-client.cjs +195 -34
  184. package/dist/server-query-client.d.mts +3 -3
  185. package/dist/server-query-client.d.ts +3 -3
  186. package/dist/server-query-client.mjs +7 -7
  187. package/dist/{server-query-runtime-3zAj77yv.d.ts → server-query-runtime-DXRNhX_3.d.ts} +2 -0
  188. package/dist/{server-query-runtime-B50KAcj5.d.mts → server-query-runtime-aP52iuL5.d.mts} +2 -0
  189. package/dist/server-query.cjs +44 -5
  190. package/dist/server-query.d.mts +4 -0
  191. package/dist/server-query.d.ts +4 -0
  192. package/dist/server-query.mjs +7 -7
  193. package/dist/server.cjs +553 -370
  194. package/dist/server.d.mts +11 -10
  195. package/dist/server.d.ts +11 -10
  196. package/dist/server.mjs +17 -17
  197. package/dist/{spa-router-CyLkwst6.d.mts → spa-router-BeyAVSc6.d.mts} +1 -1
  198. package/dist/{spa-router-BkqGXaV_.d.ts → spa-router-COgu4txb.d.ts} +1 -1
  199. package/dist/testing.cjs +27 -2
  200. package/dist/testing.d.mts +3 -2
  201. package/dist/testing.d.ts +3 -2
  202. package/dist/testing.mjs +9 -9
  203. package/dist/{utils-NKR6SoNv.d.mts → utils-DL2VwDQl.d.mts} +1 -1
  204. package/dist/{utils-B2OHrb9F.d.ts → utils-DkU2c_1B.d.ts} +1 -1
  205. package/dist/version.cjs +1 -1
  206. package/dist/version.mjs +1 -1
  207. package/dist/vite.cjs +536 -353
  208. package/dist/vite.d.mts +3 -2
  209. package/dist/vite.d.ts +3 -2
  210. package/dist/vite.mjs +17 -13
  211. package/package.json +17 -17
  212. package/types/client.d.ts +115 -10
  213. package/dist/agent-runtime.cjs.map +0 -1
  214. package/dist/api/route-manager.cjs.map +0 -1
  215. package/dist/api/runtime.cjs.map +0 -1
  216. package/dist/api.cjs.map +0 -1
  217. package/dist/app-markdown.cjs.map +0 -1
  218. package/dist/cache.cjs.map +0 -1
  219. package/dist/chunk-75CGAL6E.mjs.map +0 -1
  220. package/dist/chunk-7MABZJIM.mjs.map +0 -1
  221. package/dist/chunk-A3636IHN.mjs.map +0 -1
  222. package/dist/chunk-AXVJCMVF.mjs.map +0 -1
  223. package/dist/chunk-D7QH7MDU.mjs.map +0 -1
  224. package/dist/chunk-DLBUAJTK.mjs.map +0 -1
  225. package/dist/chunk-EXCGBERG.mjs.map +0 -1
  226. package/dist/chunk-FLHLPB57.mjs.map +0 -1
  227. package/dist/chunk-HHZAOTQD.mjs.map +0 -1
  228. package/dist/chunk-KOTSX5JH.mjs.map +0 -1
  229. package/dist/chunk-KWCNQUH5.mjs.map +0 -1
  230. package/dist/chunk-MRVJCLYQ.mjs.map +0 -1
  231. package/dist/chunk-Q7GPJZCO.mjs.map +0 -1
  232. package/dist/chunk-RBRLLZL5.mjs.map +0 -1
  233. package/dist/chunk-SALMKQXH.mjs.map +0 -1
  234. package/dist/chunk-SCFX4UTD.mjs.map +0 -1
  235. package/dist/chunk-WB75GIX2.mjs.map +0 -1
  236. package/dist/chunk-XTLLHCWU.mjs.map +0 -1
  237. package/dist/chunk-ZFNK77WN.mjs.map +0 -1
  238. package/dist/chunk-ZRBCBOEX.mjs.map +0 -1
  239. package/dist/client/lifecycle.cjs.map +0 -1
  240. package/dist/client-cache-CopR_MaI.d.mts +0 -6
  241. package/dist/client-cache-Djy_TlE8.d.ts +0 -6
  242. package/dist/client-plugins.cjs.map +0 -1
  243. package/dist/client.cjs.map +0 -1
  244. package/dist/config.cjs.map +0 -1
  245. package/dist/cron.cjs.map +0 -1
  246. package/dist/deferred.cjs.map +0 -1
  247. package/dist/deployment.cjs.map +0 -1
  248. package/dist/devtools-client-3XRTBND5.mjs.map +0 -1
  249. package/dist/devtools-ui-NJKFORTG.mjs.map +0 -1
  250. package/dist/docs.cjs.map +0 -1
  251. package/dist/env-types.cjs.map +0 -1
  252. package/dist/env.cjs.map +0 -1
  253. package/dist/environment/vite.cjs.map +0 -1
  254. package/dist/environment.cjs.map +0 -1
  255. package/dist/font.cjs.map +0 -1
  256. package/dist/headers.cjs.map +0 -1
  257. package/dist/i18n/client.cjs.map +0 -1
  258. package/dist/i18n/index.cjs.map +0 -1
  259. package/dist/i18n/server.cjs.map +0 -1
  260. package/dist/image/server.cjs.map +0 -1
  261. package/dist/image/sharp.cjs.map +0 -1
  262. package/dist/image.cjs.map +0 -1
  263. package/dist/index.cjs.map +0 -1
  264. package/dist/instrumentation.cjs.map +0 -1
  265. package/dist/integrations.cjs.map +0 -1
  266. package/dist/internal/build-runtime.cjs.map +0 -1
  267. package/dist/internal/client-runtime.cjs.map +0 -1
  268. package/dist/internal/config-runtime.cjs.map +0 -1
  269. package/dist/internal/isolated-boundary.cjs.map +0 -1
  270. package/dist/internal/metadata-image-runtime.cjs.map +0 -1
  271. package/dist/internal/product-telemetry-runtime.cjs.map +0 -1
  272. package/dist/internal/production-node-env.cjs.map +0 -1
  273. package/dist/internal/production-runtime.cjs.map +0 -1
  274. package/dist/markdown.cjs.map +0 -1
  275. package/dist/middleware.cjs.map +0 -1
  276. package/dist/navigation.cjs.map +0 -1
  277. package/dist/observability.cjs.map +0 -1
  278. package/dist/plugin.cjs.map +0 -1
  279. package/dist/query/client.cjs.map +0 -1
  280. package/dist/query/index.cjs.map +0 -1
  281. package/dist/query/parsers.cjs.map +0 -1
  282. package/dist/query/server.cjs.map +0 -1
  283. package/dist/renderer/react/client.cjs.map +0 -1
  284. package/dist/renderer/react/server.cjs.map +0 -1
  285. package/dist/renderer/react/vite.cjs.map +0 -1
  286. package/dist/renderer-client.cjs.map +0 -1
  287. package/dist/renderer.cjs.map +0 -1
  288. package/dist/request.cjs.map +0 -1
  289. package/dist/router.cjs.map +0 -1
  290. package/dist/routes.cjs.map +0 -1
  291. package/dist/server-action-security.cjs.map +0 -1
  292. package/dist/server-fn-client.cjs.map +0 -1
  293. package/dist/server-fn.cjs.map +0 -1
  294. package/dist/server-plugins.cjs.map +0 -1
  295. package/dist/server-query-client.cjs.map +0 -1
  296. package/dist/server-query.cjs.map +0 -1
  297. package/dist/server.cjs.map +0 -1
  298. package/dist/storage.cjs.map +0 -1
  299. package/dist/testing.cjs.map +0 -1
  300. package/dist/theme/client.cjs.map +0 -1
  301. package/dist/theme/index.cjs.map +0 -1
  302. package/dist/theme/runtime.cjs.map +0 -1
  303. package/dist/theme/server.cjs.map +0 -1
  304. package/dist/version.cjs.map +0 -1
  305. package/dist/vite.cjs.map +0 -1
  306. package/dist/workflows.cjs.map +0 -1
  307. /package/dist/{chunk-VV24CC42.mjs.map → chunk-35NPLKQJ.mjs.map} +0 -0
  308. /package/dist/{chunk-RWYRFCLG.mjs.map → chunk-4X57GXQA.mjs.map} +0 -0
  309. /package/dist/{chunk-MOW47IF5.mjs.map → chunk-6UYVU46O.mjs.map} +0 -0
  310. /package/dist/{chunk-RLGUZ3HS.mjs.map → chunk-I3OOUWO5.mjs.map} +0 -0
  311. /package/dist/{chunk-2LS3KKE7.mjs.map → chunk-JV7JUD7Q.mjs.map} +0 -0
  312. /package/dist/{chunk-Q3OX763A.mjs.map → chunk-LXDASSTE.mjs.map} +0 -0
  313. /package/dist/{chunk-HVG3HLQZ.mjs.map → chunk-Q7WGOOAI.mjs.map} +0 -0
  314. /package/dist/{chunk-3INDBMUU.mjs.map → chunk-TGDIACZT.mjs.map} +0 -0
  315. /package/dist/{chunk-MH27UH72.mjs.map → chunk-TT3E2JOF.mjs.map} +0 -0
  316. /package/dist/{chunk-UWRGX3J3.mjs.map → chunk-UMUWR5XA.mjs.map} +0 -0
  317. /package/dist/{devtools-S52RRRMN.mjs.map → devtools-XWZX6CCL.mjs.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/query/client.ts","../../src/query/sync.ts"],"sourcesContent":["/**\n * Farm.js Client-Side Query State Management\n *\n * Type-safe URL search parameter state management - Like useState, but stored in the URL query string.\n * Client-only hooks for managing query parameters in the browser.\n * Inspired by nuqs implementation patterns.\n */\n\nimport { useState, useEffect, useCallback, useRef } from \"react\";\nimport {\n notifyHistoryChange,\n subscribeHistoryChange,\n writeFarmURLSearchHistory,\n} from \"../client/history-sync\";\nimport { _resolveCurrentRequest } from \"../server/request-bridge\";\nimport { emitter } from \"./sync\";\nexport { parseRouteParams, loadRouteParams, type RouteParamsInput } from \"./params\";\n\nimport { asString as asStringClient, asInteger as asIntegerClient, type Parser } from \"./parsers\";\n\nexport {\n asString,\n asInteger,\n asFloat,\n asBoolean,\n asArrayOf,\n asJson,\n asIsoDate,\n asIsoDateTime,\n createParser,\n type ArrayParserOptions,\n type Parser,\n type inferParserType,\n} from \"./parsers\";\n\nexport type UrlUpdateType = \"push\" | \"replace\";\nexport type HistoryMethod = \"pushState\" | \"replaceState\";\n\nexport interface Options {\n history?: HistoryMethod;\n shallow?: boolean;\n scroll?: boolean;\n throttleMs?: number;\n}\n\nconst getCurrentSearchParams = (): URLSearchParams => {\n if (typeof window !== \"undefined\") return new URLSearchParams(window.location.search);\n\n // Server rendering used to see an empty query string here, so a hook read one\n // value on the server and another in the browser. React reports that as a\n // hydration mismatch and discards the server rendered markup for the branch.\n const request = _resolveCurrentRequest();\n if (!request) return new URLSearchParams();\n try {\n return new URL(request.url).searchParams;\n } catch {\n return new URLSearchParams();\n }\n};\n\nconst readSearchParam = (searchParams: URLSearchParams, key: string): string => {\n const values = searchParams.getAll(key);\n return values.length > 1 ? values.join(\",\") : (values[0] ?? \"\");\n};\n\nconst throttleTimers = new Map<string, ReturnType<typeof setTimeout>>();\n\nfunction getUpdateKey(updates: Record<string, unknown>): string {\n return JSON.stringify(Object.keys(updates).sort());\n}\n\nconst compareStructuredValues = (\n current: unknown,\n next: unknown,\n seen = new WeakMap<object, object>(),\n): boolean | undefined => {\n if (Object.is(current, next)) return true;\n if (current === null || next === null || typeof current !== typeof next) return false;\n if (typeof current !== \"object\" || typeof next !== \"object\") return false;\n if (current instanceof Date || next instanceof Date) {\n return current instanceof Date && next instanceof Date && current.getTime() === next.getTime();\n }\n if (Array.isArray(current) || Array.isArray(next)) {\n if (!Array.isArray(current) || !Array.isArray(next) || current.length !== next.length) {\n return false;\n }\n const knownNext = seen.get(current);\n if (knownNext) return knownNext === next;\n seen.set(current, next);\n for (let index = 0; index < current.length; index++) {\n const equal = compareStructuredValues(current[index], next[index], seen);\n if (equal !== true) return equal;\n }\n return true;\n }\n\n const currentPrototype = Object.getPrototypeOf(current);\n const nextPrototype = Object.getPrototypeOf(next);\n if (currentPrototype !== nextPrototype) return false;\n if (currentPrototype !== Object.prototype && currentPrototype !== null) return undefined;\n\n const knownNext = seen.get(current);\n if (knownNext) return knownNext === next;\n seen.set(current, next);\n\n const currentKeys = Object.keys(current);\n const nextKeys = Object.keys(next);\n if (\n currentKeys.length !== nextKeys.length ||\n currentKeys.some((key) => !Object.prototype.hasOwnProperty.call(next, key))\n ) {\n return false;\n }\n for (const key of currentKeys) {\n const equal = compareStructuredValues(\n (current as Record<string, unknown>)[key],\n (next as Record<string, unknown>)[key],\n seen,\n );\n if (equal !== true) return equal;\n }\n return true;\n};\n\nconst areParsedValuesEqual = <T>(parser: Parser<T>, current: T | null, next: T | null) => {\n if (Object.is(current, next)) return true;\n const structuredResult = compareStructuredValues(current, next);\n if (structuredResult === false) return false;\n if (current === null || next === null) return false;\n\n try {\n return parser.serialize(current) === parser.serialize(next);\n } catch {\n return structuredResult === true;\n }\n};\n\nconst applyChange = (\n searchParams: URLSearchParams,\n updates: Record<string, string | null>,\n keepExisting = true,\n): URLSearchParams => {\n const newParams = keepExisting ? new URLSearchParams(searchParams) : new URLSearchParams();\n\n Object.entries(updates).forEach(([key, value]) => {\n if (value === null || value === undefined || value === \"\") {\n newParams.delete(key);\n } else {\n newParams.set(key, value);\n }\n });\n\n return newParams;\n};\n\nconst commitURLUpdate = (\n updates: Record<string, string | null>,\n options: Options,\n emitUpdate: boolean,\n) => {\n const { history = \"pushState\", shallow = true, scroll = false } = options;\n const url = new URL(window.location.href);\n const newSearchParams = applyChange(url.searchParams, updates);\n const newSearch = newSearchParams.toString();\n const newUrl = url.pathname + (newSearch ? `?${newSearch}` : \"\") + url.hash;\n const currentUrl = url.pathname + url.search + url.hash;\n\n if (newUrl === currentUrl) return;\n\n const historyAction = history === \"replaceState\" ? \"replace\" : \"push\";\n if (!writeFarmURLSearchHistory(historyAction, newUrl)) {\n const historyState = window.history.state;\n const nextHistoryState =\n historyState && typeof historyState === \"object\" && \"path\" in historyState\n ? { ...historyState, path: newUrl }\n : historyState;\n window.history[history](nextHistoryState, \"\", newUrl);\n }\n\n if (emitUpdate) {\n const actualSearchParams = new URLSearchParams(window.location.search);\n emitter.emitUpdate(actualSearchParams);\n }\n\n if (shallow) notifyHistoryChange(\"url-search\");\n\n if (scroll) {\n window.scrollTo(0, 0);\n }\n};\n\nconst updateURL = (\n updates: Record<string, string | null>,\n options: Options = {},\n emitUpdate = true,\n): (() => void) | undefined => {\n if (typeof window === \"undefined\") return;\n\n const { throttleMs } = options;\n if (!throttleMs || throttleMs <= 0) {\n commitURLUpdate(updates, options, emitUpdate);\n return;\n }\n\n const throttleKey = getUpdateKey(updates);\n const existingTimeout = throttleTimers.get(throttleKey);\n if (existingTimeout) {\n clearTimeout(existingTimeout);\n throttleTimers.delete(throttleKey);\n }\n\n const currentUrl = new URL(window.location.href);\n const nextSearch = applyChange(currentUrl.searchParams, updates).toString();\n if (nextSearch === currentUrl.searchParams.toString()) return;\n\n const timeout = setTimeout(() => {\n if (throttleTimers.get(throttleKey) === timeout) {\n throttleTimers.delete(throttleKey);\n }\n commitURLUpdate(updates, options, emitUpdate);\n }, throttleMs);\n\n throttleTimers.set(throttleKey, timeout);\n return () => {\n if (throttleTimers.get(throttleKey) !== timeout) return;\n clearTimeout(timeout);\n throttleTimers.delete(throttleKey);\n };\n};\n\nexport function useQueryState<TParser extends Parser<any>>(\n key: string,\n parser: TParser,\n options?: Options,\n): [\n NonNullable<ReturnType<TParser[\"parse\"]>> | null,\n (value: NonNullable<ReturnType<TParser[\"parse\"]>> | null) => void,\n];\nexport function useQueryState<T>(\n key: string,\n parser: Parser<T>,\n options?: Options,\n): [T | null, (value: T | null) => void];\nexport function useQueryState<TParser extends Parser<any>>(\n key: string,\n parser: TParser,\n options?: Options,\n): [\n NonNullable<ReturnType<TParser[\"parse\"]>> | null,\n (value: NonNullable<ReturnType<TParser[\"parse\"]>> | null) => void,\n] {\n type T = NonNullable<ReturnType<TParser[\"parse\"]>>;\n const [state, setState] = useState<T | null>(() => {\n const searchParams = getCurrentSearchParams();\n const parsed = parser.parse(readSearchParam(searchParams, key));\n return parsed;\n });\n\n const stateRef = useRef(state);\n const stateKeyRef = useRef(key);\n const isInternalUpdateRef = useRef(false);\n const cancelPendingUpdateRef = useRef<(() => void) | undefined>(undefined);\n stateRef.current = state;\n\n const setValue = useCallback(\n (value: T | null) => {\n isInternalUpdateRef.current = true;\n\n setState(value);\n stateRef.current = value;\n\n const serialized = value === null ? null : parser.serialize(value);\n\n emitter.emitKey(key, { state: value, query: serialized });\n\n cancelPendingUpdateRef.current?.();\n cancelPendingUpdateRef.current = updateURL({ [key]: serialized }, options, true);\n\n setTimeout(() => {\n isInternalUpdateRef.current = false;\n }, 10);\n },\n [key, parser, options],\n );\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n\n const onPopState = () => {\n const searchParams = getCurrentSearchParams();\n const parsed = parser.parse(readSearchParam(searchParams, key));\n const sourceChanged = stateKeyRef.current !== key;\n stateKeyRef.current = key;\n if (sourceChanged || !areParsedValuesEqual(parser, stateRef.current, parsed)) {\n setState(parsed);\n stateRef.current = parsed;\n }\n };\n\n const onEmitterUpdate = (searchParams: URLSearchParams) => {\n if (isInternalUpdateRef.current) {\n return;\n }\n\n const parsed = parser.parse(readSearchParam(searchParams, key));\n if (!areParsedValuesEqual(parser, stateRef.current, parsed)) {\n setState(parsed);\n stateRef.current = parsed;\n }\n };\n\n const onKeyUpdate = (payload: { state: any; query: string | null }) => {\n if (isInternalUpdateRef.current) {\n return;\n }\n\n if (!areParsedValuesEqual(parser, stateRef.current, payload.state)) {\n setState(payload.state);\n stateRef.current = payload.state;\n }\n };\n\n // Page-state writes with an href can change the query string without a\n // popstate, so listen through the shared history channel (real\n // back/forward events included). Self-updates no-op via the Object.is\n // comparison above.\n onPopState();\n const unsubscribeHistory = subscribeHistoryChange(onPopState);\n emitter.on(\"update\", onEmitterUpdate);\n emitter.onKey(key, onKeyUpdate);\n\n return () => {\n unsubscribeHistory();\n emitter.off(\"update\", onEmitterUpdate);\n emitter.offKey(key, onKeyUpdate);\n };\n }, [key, parser]);\n\n useEffect(\n () => () => {\n cancelPendingUpdateRef.current?.();\n cancelPendingUpdateRef.current = undefined;\n },\n [key],\n );\n\n return [state, setValue];\n}\n\nexport function useQueryStates<T extends Record<string, Parser<any>>>(\n parsers: T,\n options: Options = {},\n): [\n { [K in keyof T]: ReturnType<T[K][\"parse\"]> },\n (updates: Partial<{ [K in keyof T]: ReturnType<T[K][\"parse\"]> | null }>) => void,\n] {\n const keys = Object.keys(parsers);\n const watchKeys = JSON.stringify(keys);\n\n const [state, setState] = useState<{ [K in keyof T]: ReturnType<T[K][\"parse\"]> }>(() => {\n const searchParams = getCurrentSearchParams();\n const result = {} as { [K in keyof T]: ReturnType<T[K][\"parse\"]> };\n\n Object.entries(parsers).forEach(([key, parser]) => {\n result[key as keyof T] = parser.parse(readSearchParam(searchParams, key));\n });\n\n return result;\n });\n\n const stateRef = useRef(state);\n const pendingUpdatesRef = useRef(new Map<string, () => void>());\n stateRef.current = state;\n\n const setValues = useCallback(\n (updates: Partial<{ [K in keyof T]: ReturnType<T[K][\"parse\"]> | null }>) => {\n const newState = { ...stateRef.current, ...updates };\n setState(newState);\n stateRef.current = newState;\n\n Object.entries(updates).forEach(([key, value]) => {\n const parser = parsers[key];\n if (parser) {\n const serialized = value === null ? null : parser.serialize(value);\n emitter.emitKey(key, { state: value, query: serialized });\n }\n });\n\n const urlUpdates: Record<string, string | null> = {};\n Object.entries(updates).forEach(([key, value]) => {\n const parser = parsers[key];\n if (parser) {\n const serialized = value === null ? null : parser.serialize(value);\n urlUpdates[key] = serialized;\n }\n });\n\n const updateKey = getUpdateKey(urlUpdates);\n pendingUpdatesRef.current.get(updateKey)?.();\n const cancelPendingUpdate = updateURL(urlUpdates, options, true);\n if (cancelPendingUpdate) {\n pendingUpdatesRef.current.set(updateKey, cancelPendingUpdate);\n } else {\n pendingUpdatesRef.current.delete(updateKey);\n }\n },\n [parsers, options],\n );\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n\n const applyChange = (searchParams: URLSearchParams) => {\n const result = {} as { [K in keyof T]: ReturnType<T[K][\"parse\"]> };\n const currentKeys = Object.keys(stateRef.current);\n let hasChanged =\n currentKeys.length !== keys.length ||\n currentKeys.some((key) => !Object.prototype.hasOwnProperty.call(parsers, key));\n\n Object.entries(parsers).forEach(([key, parser]) => {\n const parsed = parser.parse(readSearchParam(searchParams, key));\n const currentValue = stateRef.current[key as keyof T];\n\n if (!areParsedValuesEqual(parser, currentValue, parsed)) {\n hasChanged = true;\n }\n result[key as keyof T] = parsed;\n });\n\n if (hasChanged) {\n setState(result);\n stateRef.current = result;\n }\n };\n\n const onPopState = () => {\n const searchParams = getCurrentSearchParams();\n applyChange(searchParams);\n };\n\n const onEmitterUpdate = (searchParams: URLSearchParams) => {\n applyChange(searchParams);\n };\n\n applyChange(getCurrentSearchParams());\n const unsubscribeHistory = subscribeHistoryChange(onPopState);\n emitter.on(\"update\", onEmitterUpdate);\n\n return () => {\n unsubscribeHistory();\n emitter.off(\"update\", onEmitterUpdate);\n };\n }, [watchKeys, parsers]);\n\n useEffect(\n () => () => {\n for (const cancelPendingUpdate of pendingUpdatesRef.current.values()) {\n cancelPendingUpdate();\n }\n pendingUpdatesRef.current.clear();\n },\n [watchKeys],\n );\n\n return [state, setValues];\n}\n\nexport function usePagination(options?: {\n defaultPage?: number;\n defaultLimit?: number;\n pageKey?: string;\n limitKey?: string;\n}) {\n const {\n defaultPage = 1,\n defaultLimit = 10,\n pageKey = \"page\",\n limitKey = \"limit\",\n } = options || {};\n\n const [page, setPage] = useQueryState(pageKey, asIntegerClient.withDefault!(defaultPage));\n const [limit, setLimit] = useQueryState(limitKey, asIntegerClient.withDefault!(defaultLimit));\n\n const currentPage = page ?? defaultPage;\n const currentLimit = limit ?? defaultLimit;\n const offset = ((currentPage as number) - 1) * (currentLimit as number);\n\n return {\n page: currentPage,\n setPage,\n limit: currentLimit,\n setLimit,\n offset,\n resetPagination: () => {\n setPage(defaultPage);\n setLimit(defaultLimit);\n },\n };\n}\n\nexport function useSearchFilters<T extends Record<string, any>>(options?: {\n searchKey?: string;\n defaultFilters?: T;\n filterKeys?: (keyof T)[];\n}) {\n const {\n searchKey = \"search\",\n defaultFilters = {} as T,\n filterKeys = Object.keys(defaultFilters) as (keyof T)[],\n } = options || {};\n\n const [search, setSearch] = useQueryState(searchKey, asStringClient);\n\n const filterParsers = filterKeys.reduce(\n (acc, key) => {\n acc[key as string] = asStringClient;\n return acc;\n },\n {} as Record<string, Parser<string>>,\n );\n\n const [filters, setFilters] = useQueryStates(filterParsers);\n\n const clearFilters = () => {\n setSearch(null);\n const clearedFilters = filterKeys.reduce(\n (acc, key) => {\n acc[key as string] = null;\n return acc;\n },\n {} as Record<string, null>,\n );\n setFilters(clearedFilters);\n };\n\n return {\n search,\n setSearch,\n filters: filters as T,\n setFilters,\n clearFilters,\n };\n}\n","/**\n * Cross-hook synchronization system for query state\n * Inspired by nuqs implementation\n */\n\ntype Listener = (searchParams: URLSearchParams) => void;\ntype KeyListener = (payload: { state: any; query: string | null }) => void;\n\nclass Emitter {\n private listeners: Map<string, Set<Listener>> = new Map();\n private keyListeners: Map<string, Set<KeyListener>> = new Map();\n\n /**\n * Emit a global update event (all hooks should sync)\n */\n emitUpdate(searchParams: URLSearchParams): void {\n const listeners = this.listeners.get(\"update\") || new Set();\n listeners.forEach((listener) => listener(searchParams));\n }\n\n /**\n * Emit a key-specific update (for cross-hook sync)\n */\n emitKey(key: string, payload: { state: any; query: string | null }): void {\n const listeners = this.keyListeners.get(key) || new Set();\n listeners.forEach((listener) => listener(payload));\n }\n\n /**\n * Subscribe to global updates\n */\n on(event: \"update\", listener: Listener): void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n this.listeners.get(event)!.add(listener);\n }\n\n /**\n * Subscribe to key-specific updates\n */\n onKey(key: string, listener: KeyListener): void {\n if (!this.keyListeners.has(key)) {\n this.keyListeners.set(key, new Set());\n }\n this.keyListeners.get(key)!.add(listener);\n }\n\n /**\n * Unsubscribe from global updates\n */\n off(event: \"update\", listener: Listener): void {\n const listeners = this.listeners.get(event);\n if (listeners) {\n listeners.delete(listener);\n }\n }\n\n /**\n * Unsubscribe from key-specific updates\n */\n offKey(key: string, listener: KeyListener): void {\n const listeners = this.keyListeners.get(key);\n if (listeners) {\n listeners.delete(listener);\n }\n }\n}\n\nexport const emitter = new Emitter();\n"],"mappings":"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","names":["knownNext","applyChange"]}
1
+ {"version":3,"sources":["../../src/query/client.ts","../../src/query/sync.ts"],"sourcesContent":["/**\n * Farm.js Client-Side Query State Management\n *\n * Type-safe URL search parameter state management - Like useState, but stored in the URL query string.\n * Client-only hooks for managing query parameters in the browser.\n * Inspired by nuqs implementation patterns.\n */\n\nimport { useState, useEffect, useCallback, useRef } from \"react\";\nimport {\n notifyHistoryChange,\n subscribeHistoryChange,\n writeFarmURLSearchHistory,\n} from \"../client/history-sync\";\nimport { _resolveCurrentRequest } from \"../server/request-bridge\";\nimport { emitter, type KeyUpdate } from \"./sync\";\nexport { parseRouteParams, loadRouteParams, type RouteParamsInput } from \"./params\";\n\nimport { asString as asStringClient, asInteger as asIntegerClient, type Parser } from \"./parsers\";\n\nexport {\n asString,\n asInteger,\n asFloat,\n asBoolean,\n asArrayOf,\n asJson,\n asIsoDate,\n asIsoDateTime,\n createParser,\n type ArrayParserOptions,\n type Parser,\n type inferParserType,\n} from \"./parsers\";\n\nexport type UrlUpdateType = \"push\" | \"replace\";\nexport type HistoryMethod = \"pushState\" | \"replaceState\";\n\nexport interface Options {\n history?: HistoryMethod;\n shallow?: boolean;\n scroll?: boolean;\n throttleMs?: number;\n}\n\nconst getCurrentSearchParams = (): URLSearchParams => {\n if (typeof window !== \"undefined\") {\n discardDepartedURLUpdates();\n let params = new URLSearchParams(window.location.search);\n // Draft values belong to the existing throttle queue, not to a parser's\n // identity. Inline parsers and newly mounted consumers see the same draft.\n for (const pending of throttleTimers.values()) {\n if (pending.href === window.location.href) params = applyChange(params, pending.updates);\n }\n return params;\n }\n\n // Server rendering used to see an empty query string here, so a hook read one\n // value on the server and another in the browser. React reports that as a\n // hydration mismatch and discards the server rendered markup for the branch.\n const request = _resolveCurrentRequest();\n if (!request) return new URLSearchParams();\n try {\n return new URL(request.url).searchParams;\n } catch {\n return new URLSearchParams();\n }\n};\n\nconst readSearchParam = (searchParams: URLSearchParams, key: string): string => {\n const values = searchParams.getAll(key);\n return values.length > 1 ? values.join(\",\") : (values[0] ?? \"\");\n};\n\nconst throttleTimers = new Map<\n string,\n {\n timer: ReturnType<typeof setTimeout>;\n updates: Record<string, string | null>;\n href: string;\n }\n>();\n\nfunction discardDepartedURLUpdates(): void {\n for (const [key, pending] of throttleTimers) {\n if (pending.href === window.location.href) continue;\n clearTimeout(pending.timer);\n throttleTimers.delete(key);\n }\n}\n\nfunction getUpdateKey(updates: Record<string, unknown>): string {\n return JSON.stringify(Object.keys(updates).sort());\n}\n\nfunction supersedeQueuedKeys(updates: Record<string, string | null>): void {\n const keys = Object.keys(updates);\n for (const [queueKey, pending] of throttleTimers) {\n for (const key of keys) delete pending.updates[key];\n if (Object.keys(pending.updates).length > 0) continue;\n clearTimeout(pending.timer);\n throttleTimers.delete(queueKey);\n }\n}\n\nconst compareStructuredValues = (\n current: unknown,\n next: unknown,\n seen = new WeakMap<object, object>(),\n): boolean | undefined => {\n if (Object.is(current, next)) return true;\n if (current === null || next === null || typeof current !== typeof next) return false;\n if (typeof current !== \"object\" || typeof next !== \"object\") return false;\n if (current instanceof Date || next instanceof Date) {\n return current instanceof Date && next instanceof Date && current.getTime() === next.getTime();\n }\n if (Array.isArray(current) || Array.isArray(next)) {\n if (!Array.isArray(current) || !Array.isArray(next) || current.length !== next.length) {\n return false;\n }\n const knownNext = seen.get(current);\n if (knownNext) return knownNext === next;\n seen.set(current, next);\n for (let index = 0; index < current.length; index++) {\n const equal = compareStructuredValues(current[index], next[index], seen);\n if (equal !== true) return equal;\n }\n return true;\n }\n\n const currentPrototype = Object.getPrototypeOf(current);\n const nextPrototype = Object.getPrototypeOf(next);\n if (currentPrototype !== nextPrototype) return false;\n if (currentPrototype !== Object.prototype && currentPrototype !== null) return undefined;\n\n const knownNext = seen.get(current);\n if (knownNext) return knownNext === next;\n seen.set(current, next);\n\n const currentKeys = Object.keys(current);\n const nextKeys = Object.keys(next);\n if (\n currentKeys.length !== nextKeys.length ||\n currentKeys.some((key) => !Object.prototype.hasOwnProperty.call(next, key))\n ) {\n return false;\n }\n for (const key of currentKeys) {\n const equal = compareStructuredValues(\n (current as Record<string, unknown>)[key],\n (next as Record<string, unknown>)[key],\n seen,\n );\n if (equal !== true) return equal;\n }\n return true;\n};\n\nconst areParsedValuesEqual = <T>(parser: Parser<T>, current: T | null, next: T | null) => {\n if (Object.is(current, next)) return true;\n const structuredResult = compareStructuredValues(current, next);\n if (structuredResult === false) return false;\n if (current === null || next === null) return false;\n\n try {\n return parser.serialize(current) === parser.serialize(next);\n } catch {\n return structuredResult === true;\n }\n};\n\nconst applyChange = (\n searchParams: URLSearchParams,\n updates: Record<string, string | null>,\n keepExisting = true,\n): URLSearchParams => {\n const newParams = keepExisting ? new URLSearchParams(searchParams) : new URLSearchParams();\n\n Object.entries(updates).forEach(([key, value]) => {\n if (value === null || value === undefined || value === \"\") {\n newParams.delete(key);\n } else {\n newParams.set(key, value);\n }\n });\n\n return newParams;\n};\n\nconst commitURLUpdate = (\n updates: Record<string, string | null>,\n options: Options,\n emitUpdate: boolean,\n) => {\n const { history = \"pushState\", shallow = true, scroll = false } = options;\n const url = new URL(window.location.href);\n const newSearchParams = applyChange(url.searchParams, updates);\n const newSearch = newSearchParams.toString();\n const newUrl = url.pathname + (newSearch ? `?${newSearch}` : \"\") + url.hash;\n const currentUrl = url.pathname + url.search + url.hash;\n\n if (newUrl === currentUrl) return;\n\n const historyAction = history === \"replaceState\" ? \"replace\" : \"push\";\n if (!writeFarmURLSearchHistory(historyAction, newUrl)) {\n const historyState = window.history.state;\n const nextHistoryState =\n historyState && typeof historyState === \"object\" && \"path\" in historyState\n ? { ...historyState, path: newUrl }\n : historyState;\n window.history[history](nextHistoryState, \"\", newUrl);\n }\n\n if (emitUpdate) {\n // Composing one queued key must not discard drafts for other keys. Only\n // carry drafts forward across this write, never across unrelated navigation.\n for (const pending of throttleTimers.values()) {\n if (pending.href === url.href) pending.href = window.location.href;\n }\n emitter.emitUpdate(getCurrentSearchParams());\n }\n\n if (shallow) notifyHistoryChange(\"url-search\");\n\n if (scroll) {\n window.scrollTo(0, 0);\n }\n};\n\nconst updateURL = (\n updates: Record<string, string | null>,\n options: Options = {},\n emitUpdate = true,\n): (() => boolean) | undefined => {\n if (typeof window === \"undefined\") return;\n\n discardDepartedURLUpdates();\n\n const { throttleMs } = options;\n // Latest intent owns each key, including immediate writes and URL no-ops.\n // Keep unrelated keys in an older batch scheduled with their original owner.\n supersedeQueuedKeys(updates);\n if (!throttleMs || throttleMs <= 0) {\n commitURLUpdate(updates, options, emitUpdate);\n return;\n }\n\n const throttleKey = getUpdateKey(updates);\n\n const currentUrl = new URL(window.location.href);\n const nextSearch = applyChange(currentUrl.searchParams, updates).toString();\n if (nextSearch === currentUrl.searchParams.toString()) return;\n\n const timeout = setTimeout(() => {\n const pending = throttleTimers.get(throttleKey);\n if (pending?.timer !== timeout) return;\n throttleTimers.delete(throttleKey);\n if (pending.href !== window.location.href) return;\n commitURLUpdate(updates, options, emitUpdate);\n }, throttleMs);\n\n throttleTimers.set(throttleKey, { timer: timeout, updates, href: currentUrl.href });\n return () => {\n if (throttleTimers.get(throttleKey)?.timer !== timeout) return false;\n clearTimeout(timeout);\n throttleTimers.delete(throttleKey);\n return true;\n };\n};\n\nexport function useQueryState<TParser extends Parser<any>>(\n key: string,\n parser: TParser,\n options?: Options,\n): [\n NonNullable<ReturnType<TParser[\"parse\"]>> | null,\n (value: NonNullable<ReturnType<TParser[\"parse\"]>> | null) => void,\n];\nexport function useQueryState<T>(\n key: string,\n parser: Parser<T>,\n options?: Options,\n): [T | null, (value: T | null) => void];\nexport function useQueryState<TParser extends Parser<any>>(\n key: string,\n parser: TParser,\n options?: Options,\n): [\n NonNullable<ReturnType<TParser[\"parse\"]>> | null,\n (value: NonNullable<ReturnType<TParser[\"parse\"]>> | null) => void,\n] {\n type T = NonNullable<ReturnType<TParser[\"parse\"]>>;\n const [state, setState] = useState<T | null>(() => {\n const searchParams = getCurrentSearchParams();\n const parsed = parser.parse(readSearchParam(searchParams, key));\n return parsed;\n });\n\n const stateRef = useRef(state);\n const stateKeyRef = useRef(key);\n const cancelPendingUpdateRef = useRef<(() => boolean) | undefined>(undefined);\n stateRef.current = state;\n\n const setValue = useCallback(\n (value: T | null) => {\n setState(value);\n stateRef.current = value;\n\n const serialized = value === null ? null : parser.serialize(value);\n\n emitter.emitKey(key, { state: value, query: serialized, source: stateRef });\n\n cancelPendingUpdateRef.current?.();\n cancelPendingUpdateRef.current = updateURL({ [key]: serialized }, options, true);\n },\n [key, parser, options],\n );\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n\n const onPopState = () => {\n const searchParams = getCurrentSearchParams();\n const parsed = parser.parse(readSearchParam(searchParams, key));\n const sourceChanged = stateKeyRef.current !== key;\n stateKeyRef.current = key;\n if (sourceChanged || !areParsedValuesEqual(parser, stateRef.current, parsed)) {\n setState(parsed);\n stateRef.current = parsed;\n }\n };\n\n const onEmitterUpdate = (searchParams: URLSearchParams) => {\n const parsed = parser.parse(readSearchParam(searchParams, key));\n if (!areParsedValuesEqual(parser, stateRef.current, parsed)) {\n setState(parsed);\n stateRef.current = parsed;\n }\n };\n\n const onKeyUpdate = (payload: KeyUpdate) => {\n // Skip only this hook's synchronous echo, never a peer's newer edit.\n // The ref identity is stable across renders and is not serialized.\n if (payload.source === stateRef) {\n return;\n }\n\n // Consumers may use different parsers for the same URL key.\n const parsed = parser.parse(payload.query ?? \"\");\n if (!areParsedValuesEqual(parser, stateRef.current, parsed)) {\n setState(parsed);\n stateRef.current = parsed;\n }\n };\n\n // Page-state writes with an href can change the query string without a\n // popstate, so listen through the shared history channel (real\n // back/forward events included). Self-updates no-op via the Object.is\n // comparison above.\n onPopState();\n const unsubscribeHistory = subscribeHistoryChange(onPopState);\n emitter.on(\"update\", onEmitterUpdate);\n emitter.onKey(key, onKeyUpdate);\n\n return () => {\n unsubscribeHistory();\n emitter.off(\"update\", onEmitterUpdate);\n emitter.offKey(key, onKeyUpdate);\n };\n }, [key, parser]);\n\n useEffect(\n () => () => {\n const canceledPendingWrite = cancelPendingUpdateRef.current?.() ?? false;\n cancelPendingUpdateRef.current = undefined;\n // A throttled write is discarded on unmount, but its value was already\n // broadcast to peers via emitKey. Peers that adopted the optimistic draft\n // get no other reconciliation signal (unmount fires no history event), so\n // tell them to re-read the URL, which no longer carries this draft.\n if (canceledPendingWrite && typeof window !== \"undefined\") {\n emitter.emitUpdate(getCurrentSearchParams());\n }\n },\n [key],\n );\n\n return [state, setValue];\n}\n\nexport function useQueryStates<T extends Record<string, Parser<any>>>(\n parsers: T,\n options: Options = {},\n): [\n { [K in keyof T]: ReturnType<T[K][\"parse\"]> },\n (updates: Partial<{ [K in keyof T]: ReturnType<T[K][\"parse\"]> | null }>) => void,\n] {\n const keys = Object.keys(parsers);\n const watchKeys = JSON.stringify(keys);\n\n const [state, setState] = useState<{ [K in keyof T]: ReturnType<T[K][\"parse\"]> }>(() => {\n const searchParams = getCurrentSearchParams();\n const result = {} as { [K in keyof T]: ReturnType<T[K][\"parse\"]> };\n\n Object.entries(parsers).forEach(([key, parser]) => {\n result[key as keyof T] = parser.parse(readSearchParam(searchParams, key));\n });\n\n return result;\n });\n\n const stateRef = useRef(state);\n const pendingUpdatesRef = useRef(new Map<string, () => boolean>());\n stateRef.current = state;\n\n const setValues = useCallback(\n (updates: Partial<{ [K in keyof T]: ReturnType<T[K][\"parse\"]> | null }>) => {\n const newState = { ...stateRef.current, ...updates };\n setState(newState);\n stateRef.current = newState;\n\n Object.entries(updates).forEach(([key, value]) => {\n const parser = parsers[key];\n if (parser) {\n const serialized = value === null ? null : parser.serialize(value);\n emitter.emitKey(key, { state: value, query: serialized, source: stateRef });\n }\n });\n\n const urlUpdates: Record<string, string | null> = {};\n Object.entries(updates).forEach(([key, value]) => {\n const parser = parsers[key];\n if (parser) {\n const serialized = value === null ? null : parser.serialize(value);\n urlUpdates[key] = serialized;\n }\n });\n\n const updateKey = getUpdateKey(urlUpdates);\n pendingUpdatesRef.current.get(updateKey)?.();\n const cancelPendingUpdate = updateURL(urlUpdates, options, true);\n if (cancelPendingUpdate) {\n pendingUpdatesRef.current.set(updateKey, cancelPendingUpdate);\n } else {\n pendingUpdatesRef.current.delete(updateKey);\n }\n },\n [parsers, options],\n );\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n\n const applyChange = (searchParams: URLSearchParams) => {\n const result = {} as { [K in keyof T]: ReturnType<T[K][\"parse\"]> };\n const currentKeys = Object.keys(stateRef.current);\n let hasChanged =\n currentKeys.length !== keys.length ||\n currentKeys.some((key) => !Object.prototype.hasOwnProperty.call(parsers, key));\n\n Object.entries(parsers).forEach(([key, parser]) => {\n const parsed = parser.parse(readSearchParam(searchParams, key));\n const currentValue = stateRef.current[key as keyof T];\n\n if (!areParsedValuesEqual(parser, currentValue, parsed)) {\n hasChanged = true;\n }\n result[key as keyof T] = parsed;\n });\n\n if (hasChanged) {\n setState(result);\n stateRef.current = result;\n }\n };\n\n const onPopState = () => {\n const searchParams = getCurrentSearchParams();\n applyChange(searchParams);\n };\n\n const onEmitterUpdate = (searchParams: URLSearchParams) => {\n applyChange(searchParams);\n };\n\n applyChange(getCurrentSearchParams());\n const unsubscribeHistory = subscribeHistoryChange(onPopState);\n emitter.on(\"update\", onEmitterUpdate);\n const unsubscribeKeys = Object.entries(parsers).map(([key, parser]) => {\n const onKeyUpdate = (payload: KeyUpdate) => {\n if (payload.source === stateRef) return;\n const parsed = parser.parse(payload.query ?? \"\");\n if (areParsedValuesEqual(parser, stateRef.current[key as keyof T], parsed)) return;\n\n // Update only this key, preserving local drafts for the other fields.\n const next = { ...stateRef.current, [key]: parsed };\n stateRef.current = next;\n setState(next);\n };\n emitter.onKey(key, onKeyUpdate);\n return () => emitter.offKey(key, onKeyUpdate);\n });\n\n return () => {\n unsubscribeHistory();\n emitter.off(\"update\", onEmitterUpdate);\n for (const unsubscribe of unsubscribeKeys) unsubscribe();\n };\n }, [watchKeys, parsers]);\n\n useEffect(\n () => () => {\n let canceledPendingWrite = false;\n for (const cancelPendingUpdate of pendingUpdatesRef.current.values()) {\n if (cancelPendingUpdate()) canceledPendingWrite = true;\n }\n pendingUpdatesRef.current.clear();\n // Discarded throttled writes were already broadcast to peers via emitKey;\n // reconcile any peer that adopted a now-cancelled draft (see useQueryState).\n if (canceledPendingWrite && typeof window !== \"undefined\") {\n emitter.emitUpdate(getCurrentSearchParams());\n }\n },\n [watchKeys],\n );\n\n return [state, setValues];\n}\n\nexport function usePagination(options?: {\n defaultPage?: number;\n defaultLimit?: number;\n pageKey?: string;\n limitKey?: string;\n}) {\n const {\n defaultPage = 1,\n defaultLimit = 10,\n pageKey = \"page\",\n limitKey = \"limit\",\n } = options || {};\n\n const [page, setPage] = useQueryState(pageKey, asIntegerClient.withDefault!(defaultPage));\n const [limit, setLimit] = useQueryState(limitKey, asIntegerClient.withDefault!(defaultLimit));\n\n const currentPage = page ?? defaultPage;\n const currentLimit = limit ?? defaultLimit;\n const offset = ((currentPage as number) - 1) * (currentLimit as number);\n\n return {\n page: currentPage,\n setPage,\n limit: currentLimit,\n setLimit,\n offset,\n resetPagination: () => {\n setPage(defaultPage);\n setLimit(defaultLimit);\n },\n };\n}\n\nexport function useSearchFilters<T extends Record<string, any>>(options?: {\n searchKey?: string;\n defaultFilters?: T;\n filterKeys?: (keyof T)[];\n}) {\n const {\n searchKey = \"search\",\n defaultFilters = {} as T,\n filterKeys = Object.keys(defaultFilters) as (keyof T)[],\n } = options || {};\n\n const [search, setSearch] = useQueryState(searchKey, asStringClient);\n\n const filterParsers = filterKeys.reduce(\n (acc, key) => {\n acc[key as string] = asStringClient;\n return acc;\n },\n {} as Record<string, Parser<string>>,\n );\n\n const [filters, setFilters] = useQueryStates(filterParsers);\n\n const clearFilters = () => {\n setSearch(null);\n const clearedFilters = filterKeys.reduce(\n (acc, key) => {\n acc[key as string] = null;\n return acc;\n },\n {} as Record<string, null>,\n );\n setFilters(clearedFilters);\n };\n\n return {\n search,\n setSearch,\n filters: filters as T,\n setFilters,\n clearFilters,\n };\n}\n","/**\n * Cross-hook synchronization system for query state\n * Inspired by nuqs implementation\n */\n\ntype Listener = (searchParams: URLSearchParams) => void;\nexport type KeyUpdate = { state: any; query: string | null; source?: object };\ntype KeyListener = (payload: KeyUpdate) => void;\n\nclass Emitter {\n private listeners: Map<string, Set<Listener>> = new Map();\n private keyListeners: Map<string, Set<KeyListener>> = new Map();\n\n /**\n * Emit a global update event (all hooks should sync)\n */\n emitUpdate(searchParams: URLSearchParams): void {\n const listeners = this.listeners.get(\"update\") || new Set();\n listeners.forEach((listener) => listener(searchParams));\n }\n\n /**\n * Emit a key-specific update (for cross-hook sync)\n */\n emitKey(key: string, payload: KeyUpdate): void {\n const listeners = this.keyListeners.get(key) || new Set();\n listeners.forEach((listener) => listener(payload));\n }\n\n /**\n * Subscribe to global updates\n */\n on(event: \"update\", listener: Listener): void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n this.listeners.get(event)!.add(listener);\n }\n\n /**\n * Subscribe to key-specific updates\n */\n onKey(key: string, listener: KeyListener): void {\n if (!this.keyListeners.has(key)) {\n this.keyListeners.set(key, new Set());\n }\n this.keyListeners.get(key)!.add(listener);\n }\n\n /**\n * Unsubscribe from global updates\n */\n off(event: \"update\", listener: Listener): void {\n const listeners = this.listeners.get(event);\n if (listeners) {\n listeners.delete(listener);\n }\n }\n\n /**\n * Unsubscribe from key-specific updates\n */\n offKey(key: string, listener: KeyListener): void {\n const listeners = this.keyListeners.get(key);\n if (listeners) {\n listeners.delete(listener);\n }\n }\n}\n\nexport const emitter = new Emitter();\n"],"mappings":"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","names":["knownNext","applyChange"]}
@@ -1,5 +1,5 @@
1
1
  import { F as FarmIslandStrategy } from './island-CfGru1MO.js';
2
- import './client-plugins-B9Sq-iMg.js';
2
+ import './client-plugins-By6MVUX-.js';
3
3
 
4
4
  /**
5
5
  * A build-time rendering decision consumed by the browser router.
@@ -1,5 +1,5 @@
1
1
  import { F as FarmIslandStrategy } from './island-CfGru1MO.mjs';
2
- import './client-plugins-BvClItiL.mjs';
2
+ import './client-plugins-B6-07YmP.mjs';
3
3
 
4
4
  /**
5
5
  * A build-time rendering decision consumed by the browser router.
@@ -1398,7 +1398,9 @@ var _SPARouter = class _SPARouter {
1398
1398
  if (this.onNavigate) {
1399
1399
  await this.onNavigate(pageData);
1400
1400
  }
1401
- if (this.options.scrollRestoration) {
1401
+ if (window.location.hash) {
1402
+ getHashTargetElement(window.location.hash)?.scrollIntoView();
1403
+ } else if (this.options.scrollRestoration) {
1402
1404
  this.restoreScrollPosition(window.location.pathname + window.location.search);
1403
1405
  }
1404
1406
  if (clientNavigation) {
@@ -1723,7 +1725,13 @@ function recordFarmEventTrace(event) {
1723
1725
  activeSpan.addEvent(event.type, toEventAttributes(event), event.timestamp);
1724
1726
  }
1725
1727
  const error = event.type === "request.error" ? void 0 : getEventError(event);
1726
- if (error !== void 0) recordSpanError(activeSpan, error);
1728
+ if (error !== void 0) {
1729
+ if (event.type === "render.error") {
1730
+ recordSpanException(activeSpan, error);
1731
+ } else {
1732
+ recordSpanError(activeSpan, error);
1733
+ }
1734
+ }
1727
1735
  }
1728
1736
  const completedTraceContext = recordCompletedEventSpan(event, activeContext);
1729
1737
  return traceContext ?? completedTraceContext;
@@ -1820,12 +1828,26 @@ function getCompletedSpanDescriptor(event) {
1820
1828
  }
1821
1829
  }
1822
1830
  __name(getCompletedSpanDescriptor, "getCompletedSpanDescriptor");
1831
+ function hashFarmCacheKey(value) {
1832
+ let hash = 2166136261;
1833
+ for (let index = 0; index < value.length; index++) {
1834
+ hash ^= value.charCodeAt(index);
1835
+ hash = Math.imul(hash, 16777619);
1836
+ }
1837
+ return (hash >>> 0).toString(16).padStart(8, "0");
1838
+ }
1839
+ __name(hashFarmCacheKey, "hashFarmCacheKey");
1823
1840
  function toEventAttributes(event) {
1824
1841
  const attributes = {};
1842
+ const redactKey = typeof event.type === "string" && event.type.startsWith("cache.");
1825
1843
  for (const [key, value] of Object.entries(event)) {
1826
1844
  if (key === "timestamp" || key === "level" || key === "error" || key === "traceId" || key === "spanId" || key === "traceSampled" || value === void 0) {
1827
1845
  continue;
1828
1846
  }
1847
+ if (redactKey && key === "key" && typeof value === "string") {
1848
+ attributes["farm.key_hash"] = hashFarmCacheKey(value);
1849
+ continue;
1850
+ }
1829
1851
  if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
1830
1852
  attributes[`farm.${key}`] = value;
1831
1853
  } else if (Array.isArray(value)) {
@@ -1845,9 +1867,14 @@ function getEventError(event) {
1845
1867
  return "error" in event ? event.error : void 0;
1846
1868
  }
1847
1869
  __name(getEventError, "getEventError");
1848
- function recordSpanError(span, error) {
1870
+ function recordSpanException(span, error) {
1849
1871
  const normalized = error instanceof Error ? error : new Error(String(error));
1850
1872
  span.recordException(normalized);
1873
+ return normalized;
1874
+ }
1875
+ __name(recordSpanException, "recordSpanException");
1876
+ function recordSpanError(span, error) {
1877
+ const normalized = recordSpanException(span, error);
1851
1878
  span.setStatus({ code: import_api.SpanStatusCode.ERROR, message: normalized.message });
1852
1879
  }
1853
1880
  __name(recordSpanError, "recordSpanError");
@@ -2659,6 +2686,31 @@ function stableSerialize(value, seen = /* @__PURE__ */ new WeakSet()) {
2659
2686
  __name(stableSerialize, "stableSerialize");
2660
2687
 
2661
2688
  // src/client-cache.ts
2689
+ var invalidationTrackers = /* @__PURE__ */ new WeakMap();
2690
+ function trackFarmClientCacheInvalidations(cache) {
2691
+ let trackers = invalidationTrackers.get(cache);
2692
+ if (!trackers) {
2693
+ trackers = /* @__PURE__ */ new Set();
2694
+ invalidationTrackers.set(cache, trackers);
2695
+ }
2696
+ const keys = /* @__PURE__ */ new Set();
2697
+ trackers.add(keys);
2698
+ return {
2699
+ has(key) {
2700
+ const resolved = cache.resolveKey(key);
2701
+ for (const invalidated of keys) {
2702
+ if (cache.resolveKey(invalidated) === resolved) return true;
2703
+ }
2704
+ return false;
2705
+ },
2706
+ dispose() {
2707
+ if (!trackers.delete(keys)) return;
2708
+ keys.clear();
2709
+ if (trackers.size === 0) invalidationTrackers.delete(cache);
2710
+ }
2711
+ };
2712
+ }
2713
+ __name(trackFarmClientCacheInvalidations, "trackFarmClientCacheInvalidations");
2662
2714
  var cacheFinalizer = typeof FinalizationRegistry === "function" ? new FinalizationRegistry((unsubscribe) => unsubscribe()) : void 0;
2663
2715
  function subscribeWeakCache(reference) {
2664
2716
  const unsubscribe = subscribeFarmCacheInvalidation((key) => {
@@ -2674,6 +2726,7 @@ function subscribeWeakCache(reference) {
2674
2726
  return dispose;
2675
2727
  }
2676
2728
  __name(subscribeWeakCache, "subscribeWeakCache");
2729
+ var DEFAULT_GC_SWEEP_INTERVAL_MS = 3e4;
2677
2730
  var _FarmClientDataCache = class _FarmClientDataCache {
2678
2731
  constructor(options = {}) {
2679
2732
  this.entries = /* @__PURE__ */ new Map();
@@ -2681,6 +2734,7 @@ var _FarmClientDataCache = class _FarmClientDataCache {
2681
2734
  this.invalidatedAt = /* @__PURE__ */ new Map();
2682
2735
  this.listeners = /* @__PURE__ */ new Map();
2683
2736
  this.inflight = /* @__PURE__ */ new Map();
2737
+ this.gcSweepIntervalMs = options.gcSweepIntervalMs ?? DEFAULT_GC_SWEEP_INTERVAL_MS;
2684
2738
  if (options.subscribeToInvalidation !== false) {
2685
2739
  if (typeof WeakRef === "function") {
2686
2740
  const reference = new WeakRef(this);
@@ -2697,6 +2751,10 @@ var _FarmClientDataCache = class _FarmClientDataCache {
2697
2751
  get size() {
2698
2752
  return this.entries.size;
2699
2753
  }
2754
+ /** @internal Attach or detach the persistence engine's observation sink. */
2755
+ attachPersistence(sink) {
2756
+ this.persistence = sink;
2757
+ }
2700
2758
  resolveKey(key) {
2701
2759
  let resolved = key;
2702
2760
  const seen = /* @__PURE__ */ new Set();
@@ -2712,6 +2770,7 @@ var _FarmClientDataCache = class _FarmClientDataCache {
2712
2770
  if (!entry) return void 0;
2713
2771
  if (entry.gcAt !== void 0 && now >= entry.gcAt) {
2714
2772
  this.entries.delete(resolved);
2773
+ this.persistence?.onDelete(resolved);
2715
2774
  this.emit(resolved);
2716
2775
  return void 0;
2717
2776
  }
@@ -2725,6 +2784,8 @@ var _FarmClientDataCache = class _FarmClientDataCache {
2725
2784
  this.invalidatedAt.delete(resolved);
2726
2785
  }
2727
2786
  this.entries.set(resolved, nextEntry);
2787
+ if (nextEntry.gcAt !== void 0) this.scheduleGcSweep();
2788
+ this.persistence?.onSet(resolved, nextEntry);
2728
2789
  this.emit(resolved);
2729
2790
  return this;
2730
2791
  }
@@ -2732,6 +2793,7 @@ var _FarmClientDataCache = class _FarmClientDataCache {
2732
2793
  const resolved = this.resolveKey(key);
2733
2794
  const deleted = this.entries.delete(resolved);
2734
2795
  this.inflight.delete(resolved);
2796
+ if (deleted) this.persistence?.onDelete(resolved);
2735
2797
  this.emit(resolved);
2736
2798
  return deleted;
2737
2799
  }
@@ -2741,11 +2803,16 @@ var _FarmClientDataCache = class _FarmClientDataCache {
2741
2803
  this.aliases.clear();
2742
2804
  this.invalidatedAt.clear();
2743
2805
  this.inflight.clear();
2806
+ this.persistence?.onClear();
2744
2807
  for (const key of keys) this.emit(key);
2745
2808
  }
2746
2809
  dispose() {
2747
2810
  this.unsubscribeInvalidation?.();
2748
2811
  this.unsubscribeInvalidation = void 0;
2812
+ if (this.gcTimer !== void 0) {
2813
+ clearTimeout(this.gcTimer);
2814
+ this.gcTimer = void 0;
2815
+ }
2749
2816
  this.clear();
2750
2817
  }
2751
2818
  isStale(key, now = Date.now()) {
@@ -2754,6 +2821,7 @@ var _FarmClientDataCache = class _FarmClientDataCache {
2754
2821
  }
2755
2822
  invalidate(key, now = Date.now()) {
2756
2823
  const resolved = this.resolveKey(key);
2824
+ for (const keys of invalidationTrackers.get(this) ?? []) keys.add(resolved);
2757
2825
  this.invalidatedAt.set(resolved, now);
2758
2826
  const entry = this.entries.get(resolved);
2759
2827
  if (entry) {
@@ -2773,8 +2841,9 @@ var _FarmClientDataCache = class _FarmClientDataCache {
2773
2841
  const resolvedInvalidatedAt = this.invalidatedAt.get(resolved);
2774
2842
  if (aliasEntry && !this.entries.has(resolved)) {
2775
2843
  this.entries.set(resolved, aliasEntry);
2844
+ this.persistence?.onSet(resolved, aliasEntry);
2776
2845
  }
2777
- this.entries.delete(alias);
2846
+ if (this.entries.delete(alias)) this.persistence?.onDelete(alias);
2778
2847
  this.invalidatedAt.delete(alias);
2779
2848
  const invalidatedAt = [aliasInvalidatedAt, resolvedInvalidatedAt].reduce(
2780
2849
  (latest, value) => value === void 0 ? latest : latest === void 0 ? value : Math.max(latest, value),
@@ -2814,7 +2883,9 @@ var _FarmClientDataCache = class _FarmClientDataCache {
2814
2883
  listeners2.add(listener);
2815
2884
  return () => {
2816
2885
  listeners2.delete(listener);
2817
- if (listeners2.size === 0) this.listeners.delete(key);
2886
+ if (listeners2.size === 0 && this.listeners.get(key) === listeners2) {
2887
+ this.listeners.delete(key);
2888
+ }
2818
2889
  };
2819
2890
  }
2820
2891
  getInflight(key) {
@@ -2826,6 +2897,30 @@ var _FarmClientDataCache = class _FarmClientDataCache {
2826
2897
  deleteInflight(key) {
2827
2898
  this.inflight.delete(this.resolveKey(key));
2828
2899
  }
2900
+ scheduleGcSweep() {
2901
+ if (this.gcSweepIntervalMs === false || this.gcTimer !== void 0) return;
2902
+ const timer = setTimeout(() => {
2903
+ this.gcTimer = void 0;
2904
+ this.sweepExpiredEntries();
2905
+ }, this.gcSweepIntervalMs);
2906
+ timer.unref?.();
2907
+ this.gcTimer = timer;
2908
+ }
2909
+ sweepExpiredEntries(now = Date.now()) {
2910
+ const watched = /* @__PURE__ */ new Set();
2911
+ for (const key of this.listeners.keys()) watched.add(this.resolveKey(key));
2912
+ let remaining = false;
2913
+ for (const [key, entry] of this.entries) {
2914
+ if (entry.gcAt === void 0) continue;
2915
+ if (now < entry.gcAt || entry.fetching || this.inflight.has(key) || watched.has(key)) {
2916
+ remaining = true;
2917
+ continue;
2918
+ }
2919
+ this.entries.delete(key);
2920
+ this.persistence?.onDelete(key);
2921
+ }
2922
+ if (remaining) this.scheduleGcSweep();
2923
+ }
2829
2924
  emit(key, event) {
2830
2925
  this.notifyListeners(key, event);
2831
2926
  for (const [alias, target] of this.aliases) {
@@ -2850,6 +2945,21 @@ function getFarmClientDataCache() {
2850
2945
  }
2851
2946
  __name(getFarmClientDataCache, "getFarmClientDataCache");
2852
2947
 
2948
+ // src/client-revalidation.ts
2949
+ function attachRevalidationListeners(refresh, options = {}) {
2950
+ if (typeof window === "undefined") return () => {
2951
+ };
2952
+ const onFocus = options.refetchOnWindowFocus === false ? void 0 : refresh;
2953
+ const onOnline = options.refetchOnReconnect === false ? void 0 : refresh;
2954
+ if (onFocus) window.addEventListener("focus", onFocus);
2955
+ if (onOnline) window.addEventListener("online", onOnline);
2956
+ return () => {
2957
+ if (onFocus) window.removeEventListener("focus", onFocus);
2958
+ if (onOnline) window.removeEventListener("online", onOnline);
2959
+ };
2960
+ }
2961
+ __name(attachRevalidationListeners, "attachRevalidationListeners");
2962
+
2853
2963
  // src/server-query-runtime.ts
2854
2964
  var FARM_SERVER_QUERY_CLIENT_STATE = /* @__PURE__ */ Symbol.for("farm.serverQueryClientState");
2855
2965
  var serverQueryClientGlobal = globalThis;
@@ -2857,9 +2967,30 @@ var serverQueryClientState = serverQueryClientGlobal[FARM_SERVER_QUERY_CLIENT_ST
2857
2967
  functionIds: /* @__PURE__ */ new WeakMap(),
2858
2968
  nextFunctionId: 0,
2859
2969
  active: [],
2860
- latestOwners: /* @__PURE__ */ new Map()
2970
+ latestOwners: /* @__PURE__ */ new Map(),
2971
+ owners: /* @__PURE__ */ new Set()
2861
2972
  });
2862
2973
  serverQueryClientState.latestOwners ?? (serverQueryClientState.latestOwners = /* @__PURE__ */ new Map());
2974
+ serverQueryClientState.owners ?? (serverQueryClientState.owners = /* @__PURE__ */ new Set());
2975
+ function isServerQueryOwnerSuperseded(owner, key) {
2976
+ const cache = getFarmClientDataCache();
2977
+ const resolved = cache.resolveKey(key);
2978
+ for (const superseded of owner.supersededKeys ?? []) {
2979
+ if (cache.resolveKey(superseded) === resolved) return true;
2980
+ }
2981
+ return false;
2982
+ }
2983
+ __name(isServerQueryOwnerSuperseded, "isServerQueryOwnerSuperseded");
2984
+ function claimServerQueryKey(owner, key) {
2985
+ if (isServerQueryOwnerSuperseded(owner, key)) return false;
2986
+ const resolved = getFarmClientDataCache().resolveKey(key);
2987
+ for (const older of serverQueryClientState.owners) {
2988
+ if (older === owner) break;
2989
+ older.supersededKeys.add(resolved);
2990
+ }
2991
+ return true;
2992
+ }
2993
+ __name(claimServerQueryKey, "claimServerQueryKey");
2863
2994
  var RAW_SERVER_QUERY_SYMBOL = /* @__PURE__ */ Symbol.for("farm.server-query");
2864
2995
  function assertNotRawServerQueryInBrowser(query) {
2865
2996
  if (typeof window === "undefined" || typeof document === "undefined") return;
@@ -2873,6 +3004,10 @@ function assertNotRawServerQueryInBrowser(query) {
2873
3004
  );
2874
3005
  }
2875
3006
  __name(assertNotRawServerQueryInBrowser, "assertNotRawServerQueryInBrowser");
3007
+ function isCurrentServerQueryOwner(provisionalKey, owner) {
3008
+ return serverQueryClientState.latestOwners.get(provisionalKey) === owner && !isServerQueryOwnerSuperseded(owner, provisionalKey);
3009
+ }
3010
+ __name(isCurrentServerQueryOwner, "isCurrentServerQueryOwner");
2876
3011
  function createServerQueryCallKey(query, input) {
2877
3012
  let id = serverQueryClientState.functionIds.get(query);
2878
3013
  if (!id) {
@@ -2888,12 +3023,14 @@ async function fetchServerQuery(query, input, options = {}) {
2888
3023
  const entry = cache.get(provisionalKey);
2889
3024
  const stale = cache.isStale(provisionalKey);
2890
3025
  const inflight = cache.getInflight(provisionalKey);
2891
- if (inflight && !options.force) return inflight;
2892
- if (!options.force && entry && !stale && entry.status !== "error") return entry.data;
2893
- if (!options.force && entry && stale && entry.status !== "pending" && entry.status !== "error" && (options.swr ?? true)) {
2894
- void executeServerQuery(query, input, provisionalKey, options).catch(() => void 0);
3026
+ if (!options.force && entry && stale && (entry.status !== "pending" || entry.updatedAt !== 0) && entry.status !== "error" && (options.swr ?? true)) {
3027
+ if (!inflight) {
3028
+ void executeServerQuery(query, input, provisionalKey, options).catch(() => void 0);
3029
+ }
2895
3030
  return entry.data;
2896
3031
  }
3032
+ if (inflight && !options.force) return inflight;
3033
+ if (!options.force && entry && !stale && entry.status !== "error") return entry.data;
2897
3034
  return executeServerQuery(query, input, provisionalKey, options);
2898
3035
  }
2899
3036
  __name(fetchServerQuery, "fetchServerQuery");
@@ -2902,8 +3039,13 @@ async function executeServerQuery(query, input, provisionalKey, options) {
2902
3039
  const cache = getFarmClientDataCache();
2903
3040
  const inflight = cache.getInflight(provisionalKey);
2904
3041
  if (inflight && !options.force) return inflight;
2905
- const owner = {};
3042
+ const owner = {
3043
+ invalidations: trackFarmClientCacheInvalidations(cache),
3044
+ supersededKeys: /* @__PURE__ */ new Set()
3045
+ };
2906
3046
  serverQueryClientState.latestOwners.set(provisionalKey, owner);
3047
+ serverQueryClientState.owners.add(owner);
3048
+ claimServerQueryKey(owner, provisionalKey);
2907
3049
  const previous = cache.get(provisionalKey);
2908
3050
  cache.set(provisionalKey, {
2909
3051
  data: previous?.data,
@@ -2928,12 +3070,12 @@ async function executeServerQuery(query, input, provisionalKey, options) {
2928
3070
  }
2929
3071
  const data = await pending;
2930
3072
  const transported = cache.get(provisionalKey);
2931
- if (serverQueryClientState.latestOwners.get(provisionalKey) === owner && (!transported || transported.fetching)) {
3073
+ if (isCurrentServerQueryOwner(provisionalKey, owner) && (!transported || transported.fetching)) {
2932
3074
  const updatedAt = Date.now();
2933
3075
  cache.set(provisionalKey, {
2934
3076
  data,
2935
3077
  updatedAt,
2936
- staleAt: options.staleTime === false ? Number.POSITIVE_INFINITY : updatedAt + (options.staleTime ?? 0),
3078
+ staleAt: owner.invalidations.has(provisionalKey) ? 0 : options.staleTime === false ? Number.POSITIVE_INFINITY : updatedAt + (options.staleTime ?? 0),
2937
3079
  status: "success",
2938
3080
  error: null,
2939
3081
  fetching: false
@@ -2942,7 +3084,7 @@ async function executeServerQuery(query, input, provisionalKey, options) {
2942
3084
  return data;
2943
3085
  } catch (cause) {
2944
3086
  const error = normalizeServerQueryError(cause);
2945
- if (serverQueryClientState.latestOwners.get(provisionalKey) === owner) {
3087
+ if (isCurrentServerQueryOwner(provisionalKey, owner)) {
2946
3088
  const current = cache.get(provisionalKey);
2947
3089
  cache.set(provisionalKey, {
2948
3090
  data: current?.data,
@@ -2957,12 +3099,17 @@ async function executeServerQuery(query, input, provisionalKey, options) {
2957
3099
  }
2958
3100
  throw error;
2959
3101
  } finally {
3102
+ const invalidated = isCurrentServerQueryOwner(provisionalKey, owner) && owner.invalidations.has(provisionalKey);
3103
+ owner.invalidations.dispose();
3104
+ serverQueryClientState.owners.delete(owner);
3105
+ owner.supersededKeys.clear();
2960
3106
  if (cache.getInflight(provisionalKey) === promise) {
2961
3107
  cache.deleteInflight(provisionalKey);
2962
3108
  }
2963
3109
  if (serverQueryClientState.latestOwners.get(provisionalKey) === owner) {
2964
3110
  serverQueryClientState.latestOwners.delete(provisionalKey);
2965
3111
  }
3112
+ if (invalidated) cache.invalidate(provisionalKey);
2966
3113
  }
2967
3114
  })();
2968
3115
  cache.setInflight(provisionalKey, promise);
@@ -3190,19 +3337,15 @@ function createRendererQuery(query, input, options = {}) {
3190
3337
  for (const listener of listeners2) listener();
3191
3338
  });
3192
3339
  if (!cache.get(key) || cache.isStale(key)) void run().catch(() => void 0);
3193
- if (typeof window !== "undefined") {
3194
- const refresh = /* @__PURE__ */ __name(() => {
3340
+ cleanupBrowser = attachRevalidationListeners(
3341
+ () => {
3195
3342
  if (cache.isStale(key)) void run().catch(() => void 0);
3196
- }, "refresh");
3197
- const onFocus = options.refetchOnWindowFocus === false ? void 0 : refresh;
3198
- const onOnline = options.refetchOnReconnect === false ? void 0 : refresh;
3199
- if (onFocus) window.addEventListener("focus", onFocus);
3200
- if (onOnline) window.addEventListener("online", onOnline);
3201
- cleanupBrowser = /* @__PURE__ */ __name(() => {
3202
- if (onFocus) window.removeEventListener("focus", onFocus);
3203
- if (onOnline) window.removeEventListener("online", onOnline);
3204
- }, "cleanupBrowser");
3205
- }
3343
+ },
3344
+ {
3345
+ refetchOnWindowFocus: options.refetchOnWindowFocus,
3346
+ refetchOnReconnect: options.refetchOnReconnect
3347
+ }
3348
+ );
3206
3349
  }, "ensureStarted");
3207
3350
  return {
3208
3351
  getSnapshot() {
@@ -1,16 +1,16 @@
1
1
  import { FarmRouterRouteInput } from './router.mjs';
2
- import { F as FarmNavigationState, a as FarmNavigateOptions } from './spa-router-CyLkwst6.mjs';
3
- import { F as FarmClientCacheStatus } from './client-cache-CopR_MaI.mjs';
2
+ import { F as FarmNavigationState, a as FarmNavigateOptions } from './spa-router-BeyAVSc6.mjs';
3
+ import { F as FarmClientCacheStatus } from './client-cache-CCK-fCe0.mjs';
4
4
  import { ServerFn } from './server-fn.mjs';
5
5
  import { ServerQuery } from './server-query.mjs';
6
- import { S as ServerQueryFetchOptions } from './server-query-runtime-B50KAcj5.mjs';
6
+ import { S as ServerQueryFetchOptions } from './server-query-runtime-aP52iuL5.mjs';
7
7
  import { F as FarmThemeSnapshot, a as FarmThemePreference } from './types-DQnyD3VD.mjs';
8
8
  import { F as FarmI18nClientSnapshot, a as FarmTranslator, b as FarmI18nLocale } from './types-CnH8DOqo.mjs';
9
9
  import './lifecycle-De0vQG45.mjs';
10
10
  import './island-CfGru1MO.mjs';
11
- import './render-plan-CU31j-Jk.mjs';
12
- import './client-plugins-BvClItiL.mjs';
13
- import './route-Cq3aObmj.mjs';
11
+ import './render-plan-DLxJYAA5.mjs';
12
+ import './client-plugins-B6-07YmP.mjs';
13
+ import './route-CvEr4Uc9.mjs';
14
14
  import './cache.mjs';
15
15
  import './renderer.mjs';
16
16
  import 'http';
@@ -18,6 +18,7 @@ import './types-Cc8l9IqS.mjs';
18
18
  import 'db0';
19
19
  import 'unstorage';
20
20
  import 'react';
21
+ import './integration-api-BT024nuJ.mjs';
21
22
  import '@farming-labs/orm';
22
23
  import './types-CKwggz9n.mjs';
23
24
  import '@farming-labs/docs';
@@ -1,16 +1,16 @@
1
1
  import { FarmRouterRouteInput } from './router.js';
2
- import { F as FarmNavigationState, a as FarmNavigateOptions } from './spa-router-BkqGXaV_.js';
3
- import { F as FarmClientCacheStatus } from './client-cache-Djy_TlE8.js';
2
+ import { F as FarmNavigationState, a as FarmNavigateOptions } from './spa-router-COgu4txb.js';
3
+ import { F as FarmClientCacheStatus } from './client-cache-BMxuFqwH.js';
4
4
  import { ServerFn } from './server-fn.js';
5
5
  import { ServerQuery } from './server-query.js';
6
- import { S as ServerQueryFetchOptions } from './server-query-runtime-3zAj77yv.js';
6
+ import { S as ServerQueryFetchOptions } from './server-query-runtime-DXRNhX_3.js';
7
7
  import { F as FarmThemeSnapshot, a as FarmThemePreference } from './types-DQnyD3VD.js';
8
8
  import { F as FarmI18nClientSnapshot, a as FarmTranslator, b as FarmI18nLocale } from './types-CnH8DOqo.js';
9
9
  import './lifecycle-De0vQG45.js';
10
10
  import './island-CfGru1MO.js';
11
- import './render-plan-Dc8CjNI7.js';
12
- import './client-plugins-B9Sq-iMg.js';
13
- import './route-Y8lfz1wF.js';
11
+ import './render-plan-0GeHiGVZ.js';
12
+ import './client-plugins-By6MVUX-.js';
13
+ import './route-4pd-EVtw.js';
14
14
  import './cache.js';
15
15
  import './renderer.js';
16
16
  import 'http';
@@ -18,6 +18,7 @@ import './types-Cc8l9IqS.js';
18
18
  import 'db0';
19
19
  import 'unstorage';
20
20
  import 'react';
21
+ import './integration-api-BT024nuJ.js';
21
22
  import '@farming-labs/orm';
22
23
  import './types-CKwggz9n.js';
23
24
  import '@farming-labs/docs';