@noy-db/hub 0.7.0 → 0.8.0-pre.0

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 (616) hide show
  1. package/CHANGELOG.md +105 -14
  2. package/LICENSE +202 -21
  3. package/NOTICE +1 -0
  4. package/README.md +27 -10
  5. package/codemods/0.8.0-pre.json +61 -0
  6. package/dist/api-GVYEKSJE.js +19 -0
  7. package/dist/as/index.js +11 -11
  8. package/dist/at/index.js +9 -9
  9. package/dist/attestation/index.js +20 -20
  10. package/dist/{backup-IJTB4S4M.js → backup-7TFRVFLH.js} +21 -15
  11. package/dist/backup-7TFRVFLH.js.map +1 -0
  12. package/dist/blobs/index.js +13 -13
  13. package/dist/broker/index.js +12 -12
  14. package/dist/by/index.js +2 -2
  15. package/dist/cargo/index.js +39 -36
  16. package/dist/{chunk-7O3Y4PPD.js → chunk-244VXYPG.js} +140 -16
  17. package/dist/chunk-244VXYPG.js.map +1 -0
  18. package/dist/{chunk-BUE2D7PX.js → chunk-32YV3TJT.js} +2 -2
  19. package/dist/{chunk-3RCJJBNR.js → chunk-3ELRMVJK.js} +12 -12
  20. package/dist/{chunk-6GMZ7HEE.js → chunk-3F7GLNAE.js} +6 -6
  21. package/dist/{chunk-2Y4IMKA6.js → chunk-3H5KLDZN.js} +4 -4
  22. package/dist/{chunk-VTFVLCUH.js → chunk-3JWHAR6E.js} +2 -2
  23. package/dist/{chunk-YMUFFJCO.js → chunk-3TDUWVWB.js} +5 -2
  24. package/dist/chunk-3TDUWVWB.js.map +1 -0
  25. package/dist/{chunk-JBDFMYKQ.js → chunk-4AF3TUMP.js} +2 -2
  26. package/dist/{chunk-ZORTV6NH.js → chunk-4I522ERM.js} +88 -4
  27. package/dist/chunk-4I522ERM.js.map +1 -0
  28. package/dist/{chunk-MUM7IANK.js → chunk-4MXI3ODD.js} +4 -4
  29. package/dist/chunk-4MXI3ODD.js.map +1 -0
  30. package/dist/{chunk-BLN54W3L.js → chunk-5FDLC6G7.js} +56 -3
  31. package/dist/chunk-5FDLC6G7.js.map +1 -0
  32. package/dist/chunk-5O7D6ZTW.js +53 -0
  33. package/dist/chunk-5O7D6ZTW.js.map +1 -0
  34. package/dist/{chunk-J6FXAEUG.js → chunk-6B3VNR4P.js} +12 -12
  35. package/dist/{chunk-TUFM4UZP.js → chunk-6K7DPM7D.js} +2 -2
  36. package/dist/{chunk-K6LHRFBL.js → chunk-6LMQ5R26.js} +7 -7
  37. package/dist/{chunk-SPXXX5E4.js → chunk-6LNL42F5.js} +94 -32
  38. package/dist/chunk-6LNL42F5.js.map +1 -0
  39. package/dist/{chunk-XLMEZIAJ.js → chunk-6OWXYZK2.js} +2 -2
  40. package/dist/{chunk-BOWNCWZT.js → chunk-6QSQQLSE.js} +3 -3
  41. package/dist/chunk-7JE7BDYJ.js +1558 -0
  42. package/dist/chunk-7JE7BDYJ.js.map +1 -0
  43. package/dist/{chunk-KG7TZKZG.js → chunk-7VCXZDA4.js} +5 -5
  44. package/dist/chunk-7VCXZDA4.js.map +1 -0
  45. package/dist/{chunk-NQKIUNW5.js → chunk-A6IJU4TK.js} +2 -2
  46. package/dist/{chunk-BM5TWITZ.js → chunk-ANWPSTZU.js} +38 -9
  47. package/dist/chunk-ANWPSTZU.js.map +1 -0
  48. package/dist/{chunk-QIZPZMUI.js → chunk-AOWGXU6D.js} +2 -2
  49. package/dist/{chunk-CUZLNGD5.js → chunk-B2YY6WDD.js} +1 -1
  50. package/dist/chunk-B2YY6WDD.js.map +1 -0
  51. package/dist/{chunk-SFAWCTEM.js → chunk-B57AFBY2.js} +2 -2
  52. package/dist/{chunk-GPEQUXHL.js → chunk-B6SJIBQK.js} +4 -4
  53. package/dist/chunk-BJ2IXQ5Q.js +100 -0
  54. package/dist/chunk-BJ2IXQ5Q.js.map +1 -0
  55. package/dist/{chunk-Q2PU57HC.js → chunk-BK2HHQGN.js} +2 -2
  56. package/dist/chunk-BKT776R5.js +1 -0
  57. package/dist/{chunk-KUX3OB6D.js → chunk-BP6DARYA.js} +33 -5
  58. package/dist/chunk-BP6DARYA.js.map +1 -0
  59. package/dist/{chunk-FXBIP2WD.js → chunk-BUDAGWL5.js} +6 -6
  60. package/dist/chunk-CF5UU4S7.js +757 -0
  61. package/dist/chunk-CF5UU4S7.js.map +1 -0
  62. package/dist/{chunk-BOET4NA4.js → chunk-CKNGS5MH.js} +3 -3
  63. package/dist/chunk-CY2CYVWZ.js +41 -0
  64. package/dist/chunk-CY2CYVWZ.js.map +1 -0
  65. package/dist/{chunk-2577DKXB.js → chunk-DC5QVPV7.js} +2 -2
  66. package/dist/chunk-DC5QVPV7.js.map +1 -0
  67. package/dist/{chunk-YSRUYAVU.js → chunk-DE4DH2RZ.js} +2 -2
  68. package/dist/{chunk-6I2RQCET.js → chunk-DF73H4UN.js} +4 -4
  69. package/dist/{chunk-4GVM6QZA.js → chunk-ENAG3IY7.js} +2 -2
  70. package/dist/chunk-ENAG3IY7.js.map +1 -0
  71. package/dist/{chunk-K7NTTA6P.js → chunk-EOVMT6TB.js} +2 -2
  72. package/dist/chunk-F24ZZTHQ.js +193 -0
  73. package/dist/chunk-F24ZZTHQ.js.map +1 -0
  74. package/dist/chunk-F2TDU7MQ.js +456 -0
  75. package/dist/chunk-F2TDU7MQ.js.map +1 -0
  76. package/dist/chunk-F6NCB7KT.js +13 -0
  77. package/dist/chunk-F6NCB7KT.js.map +1 -0
  78. package/dist/{chunk-SPYWXKJN.js → chunk-F7XGHL5O.js} +3 -3
  79. package/dist/chunk-F7XGHL5O.js.map +1 -0
  80. package/dist/{chunk-XTXOCYOJ.js → chunk-FCKWQE2H.js} +5 -5
  81. package/dist/{chunk-U4FOQDY4.js → chunk-FH2L2E34.js} +4 -4
  82. package/dist/chunk-FH2L2E34.js.map +1 -0
  83. package/dist/{chunk-4OZNXTO4.js → chunk-FN5EBVTQ.js} +2 -2
  84. package/dist/chunk-FQ54DWUQ.js +270 -0
  85. package/dist/chunk-FQ54DWUQ.js.map +1 -0
  86. package/dist/{chunk-NKHRDYOR.js → chunk-FQ5VRHIB.js} +4 -4
  87. package/dist/{chunk-FAHMLERK.js → chunk-FW22ZCXT.js} +2 -2
  88. package/dist/chunk-FXQBGFOX.js +524 -0
  89. package/dist/chunk-FXQBGFOX.js.map +1 -0
  90. package/dist/{chunk-AO42KJO6.js → chunk-GF5BZ7D4.js} +45 -9
  91. package/dist/chunk-GF5BZ7D4.js.map +1 -0
  92. package/dist/{chunk-TRGTKX5E.js → chunk-GHLTDZRS.js} +5 -3
  93. package/dist/{chunk-TRGTKX5E.js.map → chunk-GHLTDZRS.js.map} +1 -1
  94. package/dist/{chunk-5WDXHNSW.js → chunk-HBPPGWUM.js} +5 -5
  95. package/dist/chunk-HBPPGWUM.js.map +1 -0
  96. package/dist/{chunk-KTFRCC5C.js → chunk-HBRLNOHL.js} +82 -8
  97. package/dist/chunk-HBRLNOHL.js.map +1 -0
  98. package/dist/chunk-HLEK5VAN.js +275 -0
  99. package/dist/chunk-HLEK5VAN.js.map +1 -0
  100. package/dist/{chunk-RMS3NEA3.js → chunk-HT2AHGQI.js} +2 -2
  101. package/dist/{chunk-CHJBLCOG.js → chunk-HVSCEIYL.js} +7 -7
  102. package/dist/{chunk-UXWB3FPF.js → chunk-I3JDRCMW.js} +150 -22
  103. package/dist/chunk-I3JDRCMW.js.map +1 -0
  104. package/dist/{chunk-GY4WYNNG.js → chunk-ID6Z6E66.js} +2 -2
  105. package/dist/{chunk-EYBQEIUY.js → chunk-IEX7NK2K.js} +3 -3
  106. package/dist/{chunk-KUJDV5QH.js → chunk-ISZQJBML.js} +5 -5
  107. package/dist/{chunk-LWBCUYZW.js → chunk-IT22PWKV.js} +2 -2
  108. package/dist/{chunk-EQEYOJBM.js → chunk-IUWCVHQ7.js} +3 -3
  109. package/dist/chunk-IUWCVHQ7.js.map +1 -0
  110. package/dist/{chunk-7V4TP3AF.js → chunk-J6UOHJY5.js} +4 -4
  111. package/dist/{chunk-JMGDHKQF.js → chunk-JCN44NCY.js} +2 -2
  112. package/dist/{chunk-CARABLSQ.js → chunk-K6W7BVZ6.js} +3 -3
  113. package/dist/{chunk-77K4PG6P.js → chunk-KJFW62P4.js} +29 -11
  114. package/dist/chunk-KJFW62P4.js.map +1 -0
  115. package/dist/{chunk-453F654R.js → chunk-L7DOS3TE.js} +2 -2
  116. package/dist/chunk-LGNDFRYC.js +23 -0
  117. package/dist/chunk-LGNDFRYC.js.map +1 -0
  118. package/dist/{chunk-WEQEYLCS.js → chunk-LGRLME4M.js} +7 -7
  119. package/dist/{chunk-RMF67KCG.js → chunk-LQ4ZHOKP.js} +2 -2
  120. package/dist/{chunk-ZVO4QVPD.js → chunk-M522UYZ2.js} +5 -5
  121. package/dist/{chunk-G56KBWFY.js → chunk-M7NI3IWE.js} +45 -12
  122. package/dist/chunk-M7NI3IWE.js.map +1 -0
  123. package/dist/chunk-MDWKM2XC.js +293 -0
  124. package/dist/chunk-MDWKM2XC.js.map +1 -0
  125. package/dist/chunk-MKXXMNJH.js +204 -0
  126. package/dist/chunk-MKXXMNJH.js.map +1 -0
  127. package/dist/{chunk-SKGMN35F.js → chunk-MLPHLJIQ.js} +3 -3
  128. package/dist/chunk-MLPHLJIQ.js.map +1 -0
  129. package/dist/{chunk-2N4GY74U.js → chunk-MTL7MXGR.js} +6 -6
  130. package/dist/{chunk-TFR7DSOV.js → chunk-MVZ2TPVP.js} +2 -2
  131. package/dist/{chunk-CPWQB3N5.js → chunk-N5DNADLQ.js} +7 -7
  132. package/dist/{chunk-ELNXJMGB.js → chunk-NNARWO72.js} +6 -6
  133. package/dist/{chunk-PT43Y56J.js → chunk-NRT6QZQB.js} +102 -16
  134. package/dist/chunk-NRT6QZQB.js.map +1 -0
  135. package/dist/{chunk-QIBVIOXO.js → chunk-NWHBJQAL.js} +99 -8
  136. package/dist/chunk-NWHBJQAL.js.map +1 -0
  137. package/dist/chunk-NYMLINRP.js +28 -0
  138. package/dist/chunk-NYMLINRP.js.map +1 -0
  139. package/dist/{chunk-7MG7SJT7.js → chunk-ODVPTDPK.js} +1 -1
  140. package/dist/chunk-ODVPTDPK.js.map +1 -0
  141. package/dist/chunk-ORDURZBU.js +461 -0
  142. package/dist/chunk-ORDURZBU.js.map +1 -0
  143. package/dist/{chunk-6YXCPL4T.js → chunk-PDCG6PR5.js} +2 -2
  144. package/dist/{chunk-REDOOY2Q.js → chunk-PSIV7CJV.js} +2 -2
  145. package/dist/{chunk-NA2NIJZI.js → chunk-QBBUZ3I3.js} +126 -19
  146. package/dist/chunk-QBBUZ3I3.js.map +1 -0
  147. package/dist/{chunk-5VCRVKOZ.js → chunk-QOOUUR4A.js} +6 -4
  148. package/dist/{chunk-5VCRVKOZ.js.map → chunk-QOOUUR4A.js.map} +1 -1
  149. package/dist/{chunk-ANATMFIO.js → chunk-QWFHIOD2.js} +5 -5
  150. package/dist/{chunk-X2DLENDQ.js → chunk-QWGU66MP.js} +3 -3
  151. package/dist/chunk-RHVMZSUU.js +7 -0
  152. package/dist/chunk-RHVMZSUU.js.map +1 -0
  153. package/dist/{chunk-BSFNRLK2.js → chunk-S57HTZ6X.js} +5 -5
  154. package/dist/{chunk-SZJ3DLZA.js → chunk-SEE332EV.js} +2 -2
  155. package/dist/{chunk-YYP7WSEB.js → chunk-SI3V7D4G.js} +2 -2
  156. package/dist/{chunk-UGTBXF5U.js → chunk-SOIQ4MM4.js} +3 -3
  157. package/dist/chunk-SUZKW6UR.js +25 -0
  158. package/dist/chunk-SUZKW6UR.js.map +1 -0
  159. package/dist/{chunk-VXGSWL6L.js → chunk-SYVZW77S.js} +6 -6
  160. package/dist/{chunk-6GOE5PGN.js → chunk-T2LBQ5DV.js} +883 -227
  161. package/dist/chunk-T2LBQ5DV.js.map +1 -0
  162. package/dist/chunk-T52GX4SA.js +215 -0
  163. package/dist/chunk-T52GX4SA.js.map +1 -0
  164. package/dist/{chunk-MVMXZYXT.js → chunk-TKUOEU2F.js} +2 -2
  165. package/dist/chunk-TOPYQ6GA.js +31 -0
  166. package/dist/chunk-TOPYQ6GA.js.map +1 -0
  167. package/dist/{chunk-SMH6SRX7.js → chunk-TROR3ALR.js} +2 -2
  168. package/dist/{chunk-2C3AQB46.js → chunk-UD5EVGZ7.js} +42 -389
  169. package/dist/chunk-UD5EVGZ7.js.map +1 -0
  170. package/dist/{chunk-KJIMGIWO.js → chunk-UPD5NWI5.js} +65 -17
  171. package/dist/chunk-UPD5NWI5.js.map +1 -0
  172. package/dist/{chunk-SL3JAAKN.js → chunk-UYB234ZR.js} +30 -2
  173. package/dist/chunk-UYB234ZR.js.map +1 -0
  174. package/dist/chunk-VHM7HCKB.js +220 -0
  175. package/dist/chunk-VHM7HCKB.js.map +1 -0
  176. package/dist/{chunk-DGOZ4UZD.js → chunk-VNNRUGMM.js} +2 -2
  177. package/dist/{chunk-HDOU6I2Y.js → chunk-VNPEWFPD.js} +4 -4
  178. package/dist/{chunk-L7CIOOBW.js → chunk-WNJ4AVGE.js} +2 -2
  179. package/dist/{chunk-FMZY5Q6L.js → chunk-WX5ADGTZ.js} +3 -3
  180. package/dist/{chunk-VXANTWBJ.js → chunk-WY2XXTET.js} +92 -6
  181. package/dist/{chunk-VXANTWBJ.js.map → chunk-WY2XXTET.js.map} +1 -1
  182. package/dist/{chunk-6X6SEMEE.js → chunk-X25NWUZB.js} +33 -8
  183. package/dist/chunk-X25NWUZB.js.map +1 -0
  184. package/dist/{chunk-Q7HZX3IF.js → chunk-X4773RBR.js} +2 -2
  185. package/dist/chunk-XBKH4FOC.js +195 -0
  186. package/dist/chunk-XBKH4FOC.js.map +1 -0
  187. package/dist/{chunk-ANSIZYEG.js → chunk-YNIUIERI.js} +3 -3
  188. package/dist/chunk-YSK2CU2Q.js +936 -0
  189. package/dist/chunk-YSK2CU2Q.js.map +1 -0
  190. package/dist/{chunk-UXVWEX5L.js → chunk-Z5HTYMMQ.js} +6 -2
  191. package/dist/chunk-Z5HTYMMQ.js.map +1 -0
  192. package/dist/{chunk-RRNRNANG.js → chunk-ZE4CHIED.js} +66 -75
  193. package/dist/chunk-ZE4CHIED.js.map +1 -0
  194. package/dist/chunk-ZSX4S5XB.js +1289 -0
  195. package/dist/chunk-ZSX4S5XB.js.map +1 -0
  196. package/dist/{chunk-BZ3534YM.js → chunk-ZUVBC32X.js} +2 -2
  197. package/dist/{chunk-L742JPKZ.js → chunk-ZXABPVM6.js} +6 -6
  198. package/dist/classified/index.js +5 -5
  199. package/dist/{classified-marker-LI2SF2E4.js → classified-marker-W3USLL5M.js} +3 -3
  200. package/dist/collection-facade-QU6IJBN3.js +48 -0
  201. package/dist/{computed-VPOKQK4N.js → computed-TPFBX7U4.js} +3 -3
  202. package/dist/consent/index.js +9 -9
  203. package/dist/cover/index.js +10 -10
  204. package/dist/coverage/index.js +306 -0
  205. package/dist/coverage/index.js.map +1 -0
  206. package/dist/custody/index.js +12 -12
  207. package/dist/{dead-filter-TSWZQRR5.js → dead-filter-U2UYKSZL.js} +2 -2
  208. package/dist/debug/index.js +1 -1
  209. package/dist/{delegation-OVIFFPG4.js → delegation-S3AEPW2T.js} +11 -11
  210. package/dist/derivations/index.js +25 -22
  211. package/dist/derive-OX7F6TGG.js +21 -0
  212. package/dist/directory/index.js +10 -10
  213. package/dist/{dispatch-WC6X2M6C.js → dispatch-3CQDJV5Q.js} +5 -5
  214. package/dist/{dispatch-S73TK3IY.js → dispatch-RH4LHKBH.js} +21 -21
  215. package/dist/{enclave-KJOTOH7X.js → enclave-27SMF6GF.js} +15 -9
  216. package/dist/executor-B6SRO2QS.js +36 -0
  217. package/dist/executor-BI5CHWRY.js +8 -0
  218. package/dist/executor-RBKM5W5K.js +8 -0
  219. package/dist/export-accessible-VMA3YM5V.js +22 -0
  220. package/dist/extract-partition-NF7PXGPP.js +37 -0
  221. package/dist/{fanout-sidecar-WUFXNYP4.js → fanout-sidecar-OT6RYLOL.js} +9 -9
  222. package/dist/find-LZMP26KF.js +10 -0
  223. package/dist/forget/index.js +9 -9
  224. package/dist/guards/index.js +4 -4
  225. package/dist/history/index.js +13 -13
  226. package/dist/i18n/index.js +14 -14
  227. package/dist/index.d.ts +29 -6
  228. package/dist/index.js +999 -191
  229. package/dist/index.js.map +1 -1
  230. package/dist/indexing/index.js +13 -5
  231. package/dist/indexing/index.js.map +1 -1
  232. package/dist/introspection/index.js +11 -11
  233. package/dist/issue-IHARXWW5.js +18 -0
  234. package/dist/ivf-flat-UZ6DQDLS.js +314 -0
  235. package/dist/ivf-flat-UZ6DQDLS.js.map +1 -0
  236. package/dist/{json-schema-V3M5MUCM.js → json-schema-3SHX72CC.js} +2 -1
  237. package/dist/json-schema-3SHX72CC.js.map +1 -0
  238. package/dist/kernel/collection-config.d.ts +4 -20
  239. package/dist/kernel/collection.d.ts +29 -8
  240. package/dist/kernel/enclave/crypto.d.ts +16 -0
  241. package/dist/kernel/enclave/index.d.ts +1 -1
  242. package/dist/kernel/enclave/record-keys/record-codec.d.ts +25 -0
  243. package/dist/kernel/errors.d.ts +227 -36
  244. package/dist/kernel/generation-map.d.ts +48 -0
  245. package/dist/kernel/memory-store.d.ts +35 -7
  246. package/dist/kernel/noydb.d.ts +6 -1
  247. package/dist/kernel/present-cache.d.ts +58 -0
  248. package/dist/kernel/query/all.d.ts +7 -0
  249. package/dist/kernel/query/builder.d.ts +601 -270
  250. package/dist/kernel/query/civil-date.d.ts +64 -0
  251. package/dist/kernel/query/cursor.d.ts +40 -0
  252. package/dist/kernel/query/distinct-key.d.ts +98 -0
  253. package/dist/kernel/query/hydration.d.ts +76 -0
  254. package/dist/kernel/query/index.d.ts +31 -15
  255. package/dist/kernel/query/internal/core.d.ts +30 -0
  256. package/dist/kernel/query/internal/hooks.d.ts +22 -0
  257. package/dist/kernel/query/internal/maintenance.d.ts +43 -0
  258. package/dist/kernel/query/live/incremental.d.ts +314 -0
  259. package/dist/kernel/query/live/index.d.ts +22 -0
  260. package/dist/kernel/query/live/install.d.ts +2 -0
  261. package/dist/kernel/query/{live.d.ts → live/live.d.ts} +39 -9
  262. package/dist/kernel/query/live/methods.d.ts +107 -0
  263. package/dist/kernel/query/predicate.d.ts +119 -1
  264. package/dist/kernel/query/reduce/date-trunc.d.ts +75 -0
  265. package/dist/kernel/query/reduce/index.d.ts +36 -0
  266. package/dist/kernel/query/reduce/install.d.ts +2 -0
  267. package/dist/kernel/query/reduce/methods.d.ts +259 -0
  268. package/dist/kernel/query/reduce/scan-methods.d.ts +121 -0
  269. package/dist/kernel/query/relate/explain.d.ts +199 -0
  270. package/dist/kernel/query/relate/index.d.ts +48 -0
  271. package/dist/kernel/query/relate/install.d.ts +2 -0
  272. package/dist/kernel/query/relate/join-on.d.ts +126 -0
  273. package/dist/kernel/query/relate/join-reduce.d.ts +16 -0
  274. package/dist/kernel/query/relate/join.d.ts +452 -0
  275. package/dist/kernel/query/relate/methods.d.ts +426 -0
  276. package/dist/kernel/query/relate/partition.d.ts +87 -0
  277. package/dist/kernel/query/relate/scan-methods.d.ts +163 -0
  278. package/dist/kernel/query/relate/traverse.d.ts +109 -0
  279. package/dist/kernel/query/scan-builder.d.ts +79 -176
  280. package/dist/kernel/query/sort-key.d.ts +52 -0
  281. package/dist/kernel/tx-write-gate.d.ts +77 -0
  282. package/dist/kernel/types.d.ts +71 -3
  283. package/dist/kernel/validation.d.ts +27 -10
  284. package/dist/kernel/vault.d.ts +9 -4
  285. package/dist/kernel/via/compose.d.ts +3 -0
  286. package/dist/kernel/via/index.d.ts +56 -0
  287. package/dist/kernel/via/pipeline.d.ts +48 -0
  288. package/dist/{ledger-F33ZVMTK.js → ledger-KZPCMVZY.js} +11 -11
  289. package/dist/liberate-GRLCZMW4.js +24 -0
  290. package/dist/link-set-JCMJ7ULP.js +30 -0
  291. package/dist/{managed-secret-PQYKSR6T.js → managed-secret-S3MQ6SH6.js} +10 -10
  292. package/dist/materialized-views/index.js +30 -23
  293. package/dist/{migrate-cek-5ENH64AA.js → migrate-cek-V7GKJZ7O.js} +2 -2
  294. package/dist/money/index.js +5 -5
  295. package/dist/noydb-SWQJ3MZS.js +97 -0
  296. package/dist/overlay-views/index.js +4 -4
  297. package/dist/periods/index.js +12 -12
  298. package/dist/pod/index.js +75 -68
  299. package/dist/{pod-handle-Q736KYON.js → pod-handle-WGDFB4C2.js} +9 -9
  300. package/dist/policy/index.js +10 -10
  301. package/dist/port/with/blob-strategy.d.ts +9 -0
  302. package/dist/port/with/collection-options.d.ts +5 -0
  303. package/dist/port/with/coverage-strategy.d.ts +83 -0
  304. package/dist/port/with/service-bus.d.ts +46 -0
  305. package/dist/port/with/strategies.d.ts +2 -0
  306. package/dist/portability/index.js +8 -8
  307. package/dist/{post-register-LNE2FE2A.js → post-register-SLSXIPBV.js} +6 -6
  308. package/dist/query/all/index.js +31 -0
  309. package/dist/query/index.js +20 -32
  310. package/dist/query/live/index.js +21 -0
  311. package/dist/query/live/index.js.map +1 -0
  312. package/dist/query/reduce/index.js +33 -0
  313. package/dist/query/reduce/index.js.map +1 -0
  314. package/dist/query/relate/index.js +56 -0
  315. package/dist/query/relate/index.js.map +1 -0
  316. package/dist/reduce/index.js +72 -18
  317. package/dist/reduce/index.js.map +1 -1
  318. package/dist/register-F3OYE7MJ.js +31 -0
  319. package/dist/registry-CILQFXFK.js +8 -0
  320. package/dist/registry-XNNYQVKV.js +8 -0
  321. package/dist/registry-YCDZV3VW.js +35 -0
  322. package/dist/registry-ZGYS33TE.js +24 -0
  323. package/dist/request-withdrawal-Z5NC6TXT.js +30 -0
  324. package/dist/{reveal-67RDQRIN.js → reveal-4BCKPEC2.js} +6 -6
  325. package/dist/revoke-ZL62WC2D.js +23 -0
  326. package/dist/satellites/index.js +1 -1
  327. package/dist/schema-update/index.js +2 -2
  328. package/dist/sealed-record/index.js +12 -12
  329. package/dist/search/index.js +11 -5
  330. package/dist/{seed-G42JYN56.js → seed-4JS2RJ4A.js} +12 -12
  331. package/dist/sequence/index.js +9 -9
  332. package/dist/session/index.js +9 -9
  333. package/dist/shadow/index.js +2 -2
  334. package/dist/signer-MBZZMXTC.js +24 -0
  335. package/dist/snapshots/index.js +10 -10
  336. package/dist/{stale-DDL7WQEZ.js → stale-TJ3DYZMQ.js} +10 -10
  337. package/dist/storage-SVMKRGCW.js +22 -0
  338. package/dist/{store-coordination-provider-MEQ2MJQG.js → store-coordination-provider-2O2VUHKW.js} +10 -10
  339. package/dist/sync/index.js +10 -10
  340. package/dist/team/index.js +17 -15
  341. package/dist/tiers/index.js +13 -11
  342. package/dist/to/index.js +2 -2
  343. package/dist/transactions/index.js +3 -3
  344. package/dist/util/index.js +1 -1
  345. package/dist/vault-head/index.js +8 -8
  346. package/dist/{verify-KOV2G5D6.js → verify-RVT67IMH.js} +5 -5
  347. package/dist/via/blob/index.d.ts +1 -0
  348. package/dist/via/geo/binding.d.ts +31 -0
  349. package/dist/via/geo/descriptor.d.ts +54 -0
  350. package/dist/via/geo/geohash.d.ts +95 -0
  351. package/dist/via/geo/index.d.ts +13 -0
  352. package/dist/via/geo/where.d.ts +50 -0
  353. package/dist/via/i18n/core.d.ts +1 -1
  354. package/dist/via/lookup/registry.d.ts +1 -1
  355. package/dist/via/lookup/snapshot.d.ts +3 -3
  356. package/dist/walk-HJ42EISE.js +21 -0
  357. package/dist/walk-HJ42EISE.js.map +1 -0
  358. package/dist/with-audit/coverage/accounting.d.ts +112 -0
  359. package/dist/with-audit/coverage/active.d.ts +29 -0
  360. package/dist/with-audit/coverage/index.d.ts +61 -0
  361. package/dist/with-audit/coverage/sketch.d.ts +75 -0
  362. package/dist/with-audit/periods/periods.d.ts +55 -7
  363. package/dist/with-audit/periods/reserved-collections.d.ts +3 -0
  364. package/dist/with-audit/periods/vault-facade.d.ts +17 -0
  365. package/dist/with-audit/tiers/index.d.ts +51 -0
  366. package/dist/with-audit/tiers/strategy.d.ts +8 -0
  367. package/dist/with-cargo/floor.d.ts +2 -2
  368. package/dist/with-commit/tx/invariants.d.ts +1 -1
  369. package/dist/with-commit/tx/transaction.d.ts +13 -3
  370. package/dist/with-formula/materialized-views/dependency-analyzer.d.ts +4 -3
  371. package/dist/with-formula/materialized-views/emit-memo.d.ts +40 -0
  372. package/dist/with-formula/materialized-views/executor.d.ts +8 -0
  373. package/dist/with-formula/materialized-views/index.d.ts +1 -1
  374. package/dist/with-formula/materialized-views/registry.d.ts +15 -0
  375. package/dist/with-formula/materialized-views/types.d.ts +106 -14
  376. package/dist/with-formula/materialized-views/window-stage.d.ts +11 -0
  377. package/dist/with-formula/overlay-views/types.d.ts +1 -1
  378. package/dist/with-formula/overlay-views/virtual-collection.d.ts +13 -4
  379. package/dist/with-lookup/embeddings/chunks.d.ts +79 -0
  380. package/dist/with-lookup/embeddings/descriptor.d.ts +21 -0
  381. package/dist/with-lookup/embeddings/index.d.ts +3 -0
  382. package/dist/with-lookup/embeddings/ivf-flat.d.ts +93 -0
  383. package/dist/with-lookup/embeddings/vector-index.d.ts +73 -0
  384. package/dist/with-lookup/embeddings/vector-set.d.ts +94 -1
  385. package/dist/with-lookup/embeddings/with-vector-index.d.ts +67 -0
  386. package/dist/with-lookup/indexing/collection-facade.d.ts +85 -2
  387. package/dist/with-lookup/indexing/compound-indexes.d.ts +129 -0
  388. package/dist/with-lookup/indexing/eager-indexes.d.ts +170 -1
  389. package/dist/with-lookup/indexing/index-snapshot.d.ts +62 -0
  390. package/dist/with-lookup/indexing/lazy-builder.d.ts +33 -0
  391. package/dist/with-lookup/indexing/persisted-field-indexes.d.ts +104 -0
  392. package/dist/with-lookup/indexing/persisted-indexes.d.ts +12 -0
  393. package/dist/with-lookup/indexing/sorted-indexes.d.ts +117 -0
  394. package/dist/with-lookup/indexing/unique-constraints.d.ts +106 -23
  395. package/dist/with-lookup/reduce/active.d.ts +2 -24
  396. package/dist/with-lookup/reduce/group-core.d.ts +43 -0
  397. package/dist/with-lookup/reduce/groupby.d.ts +195 -36
  398. package/dist/with-lookup/reduce/incremental-group.d.ts +153 -0
  399. package/dist/with-lookup/reduce/index.d.ts +26 -5
  400. package/dist/with-lookup/reduce/reducers.d.ts +255 -1
  401. package/dist/with-lookup/reduce/reduction.d.ts +44 -13
  402. package/dist/with-lookup/reduce/strategy.d.ts +43 -3
  403. package/dist/with-lookup/reduce/window.d.ts +262 -0
  404. package/dist/with-lookup/search/collection-facade.d.ts +44 -8
  405. package/dist/with-lookup/search/index-store.d.ts +5 -3
  406. package/dist/with-lookup/search/index.d.ts +4 -2
  407. package/dist/with-lookup/search/inverted-index.d.ts +38 -2
  408. package/dist/with-lookup/search/persisted-index-store.d.ts +5 -2
  409. package/dist/with-lookup/search/phrase.d.ts +28 -0
  410. package/dist/with-lookup/search/retrieve-types.d.ts +57 -1
  411. package/dist/with-lookup/search/serialize.d.ts +29 -3
  412. package/dist/with-lookup/search/strategy.d.ts +2 -6
  413. package/dist/with-party/directory/cover/index.d.ts +1 -1
  414. package/dist/with-party/directory/cover/storage.d.ts +1 -1
  415. package/dist/with-party/directory/cover/types.d.ts +1 -1
  416. package/dist/with-party/directory/index.d.ts +1 -1
  417. package/dist/with-party/directory/types.d.ts +1 -1
  418. package/dist/with-party/directory/user-envelope/api.d.ts +1 -1
  419. package/dist/with-party/policy/engine.d.ts +1 -1
  420. package/dist/with-party/policy/index.d.ts +1 -1
  421. package/dist/with-party/policy/presets.d.ts +1 -1
  422. package/dist/with-party/team/authenticators.d.ts +91 -1
  423. package/dist/with-party/team/index.d.ts +3 -2
  424. package/dist/with-party/team/keyring.d.ts +13 -6
  425. package/dist/with-party/team/managed-secret.d.ts +1 -1
  426. package/dist/with-party/team/noydb-facade.d.ts +12 -3
  427. package/dist/with-party/team/wrapped-deks.d.ts +4 -4
  428. package/dist/with-pod/format.d.ts +1 -1
  429. package/dist/with-pod/pod.d.ts +5 -5
  430. package/dist/with-shape/blobs/blob-compaction.d.ts +16 -0
  431. package/dist/with-shape/blobs/blob-set.d.ts +21 -2
  432. package/dist/with-shape/blobs/legacy-sweep.d.ts +35 -0
  433. package/dist/with-shape/introspection/describe.d.ts +6 -0
  434. package/dist/with-shape/introspection/field-meta.d.ts +18 -0
  435. package/dist/with-shape/introspection/types.d.ts +57 -1
  436. package/dist/with-shape/links/vault-facade.d.ts +1 -1
  437. package/dist/with-store/partitioned/index.d.ts +337 -0
  438. package/dist/with-sync/change-broadcast.d.ts +153 -0
  439. package/dist/withdraw-accessible-5NZUPAVA.js +27 -0
  440. package/dist/withdraw-accessible-5NZUPAVA.js.map +1 -0
  441. package/package.json +37 -10
  442. package/dist/api-TXFOVOXX.js +0 -19
  443. package/dist/backup-IJTB4S4M.js.map +0 -1
  444. package/dist/chunk-2577DKXB.js.map +0 -1
  445. package/dist/chunk-2C3AQB46.js.map +0 -1
  446. package/dist/chunk-4GVM6QZA.js.map +0 -1
  447. package/dist/chunk-5WDXHNSW.js.map +0 -1
  448. package/dist/chunk-6GOE5PGN.js.map +0 -1
  449. package/dist/chunk-6X6SEMEE.js.map +0 -1
  450. package/dist/chunk-77K4PG6P.js.map +0 -1
  451. package/dist/chunk-7MG2LHO5.js +0 -1616
  452. package/dist/chunk-7MG2LHO5.js.map +0 -1
  453. package/dist/chunk-7MG7SJT7.js.map +0 -1
  454. package/dist/chunk-7O3Y4PPD.js.map +0 -1
  455. package/dist/chunk-AO42KJO6.js.map +0 -1
  456. package/dist/chunk-ATL3ZVXT.js +0 -151
  457. package/dist/chunk-ATL3ZVXT.js.map +0 -1
  458. package/dist/chunk-BLN54W3L.js.map +0 -1
  459. package/dist/chunk-BM5TWITZ.js.map +0 -1
  460. package/dist/chunk-CUZLNGD5.js.map +0 -1
  461. package/dist/chunk-EQEYOJBM.js.map +0 -1
  462. package/dist/chunk-G56KBWFY.js.map +0 -1
  463. package/dist/chunk-I3ISCYT7.js +0 -159
  464. package/dist/chunk-I3ISCYT7.js.map +0 -1
  465. package/dist/chunk-KG7TZKZG.js.map +0 -1
  466. package/dist/chunk-KJIMGIWO.js.map +0 -1
  467. package/dist/chunk-KTFRCC5C.js.map +0 -1
  468. package/dist/chunk-KUX3OB6D.js.map +0 -1
  469. package/dist/chunk-MUM7IANK.js.map +0 -1
  470. package/dist/chunk-NA2NIJZI.js.map +0 -1
  471. package/dist/chunk-NSITFOCJ.js +0 -99
  472. package/dist/chunk-NSITFOCJ.js.map +0 -1
  473. package/dist/chunk-PT43Y56J.js.map +0 -1
  474. package/dist/chunk-QIBVIOXO.js.map +0 -1
  475. package/dist/chunk-RRNRNANG.js.map +0 -1
  476. package/dist/chunk-RTBJ5IOO.js +0 -87
  477. package/dist/chunk-RTBJ5IOO.js.map +0 -1
  478. package/dist/chunk-SKGMN35F.js.map +0 -1
  479. package/dist/chunk-SL3JAAKN.js.map +0 -1
  480. package/dist/chunk-SPXXX5E4.js.map +0 -1
  481. package/dist/chunk-SPYWXKJN.js.map +0 -1
  482. package/dist/chunk-U4FOQDY4.js.map +0 -1
  483. package/dist/chunk-UXVWEX5L.js.map +0 -1
  484. package/dist/chunk-UXWB3FPF.js.map +0 -1
  485. package/dist/chunk-YMUFFJCO.js.map +0 -1
  486. package/dist/chunk-ZN4FD4PE.js +0 -364
  487. package/dist/chunk-ZN4FD4PE.js.map +0 -1
  488. package/dist/chunk-ZORTV6NH.js.map +0 -1
  489. package/dist/collection-facade-4GRREZ6C.js +0 -45
  490. package/dist/derive-6O5SWQKN.js +0 -21
  491. package/dist/executor-5NIMLSKZ.js +0 -8
  492. package/dist/executor-AQVXV5GZ.js +0 -8
  493. package/dist/executor-PUAO6AKJ.js +0 -29
  494. package/dist/export-accessible-72EQNBMR.js +0 -22
  495. package/dist/extract-partition-PUYNU3UF.js +0 -37
  496. package/dist/find-2ABFCZX4.js +0 -10
  497. package/dist/issue-SIDORTSZ.js +0 -18
  498. package/dist/json-schema-V3M5MUCM.js.map +0 -1
  499. package/dist/kernel/query/join.d.ts +0 -232
  500. package/dist/liberate-LCDPNAG2.js +0 -24
  501. package/dist/link-set-FKNWAYKS.js +0 -30
  502. package/dist/noydb-DUXZPKSN.js +0 -90
  503. package/dist/register-I2DZXGAR.js +0 -31
  504. package/dist/registry-23WF3TGH.js +0 -8
  505. package/dist/registry-4AYVUNXK.js +0 -8
  506. package/dist/registry-VSSQPIGF.js +0 -18
  507. package/dist/registry-YLEWMGAC.js +0 -32
  508. package/dist/request-withdrawal-KFQHEZ25.js +0 -30
  509. package/dist/revoke-DQDZAZZM.js +0 -23
  510. package/dist/signer-WAMDZHEN.js +0 -24
  511. package/dist/storage-FLR73HHF.js +0 -22
  512. package/dist/walk-3UQBRMDV.js +0 -21
  513. package/dist/withdraw-accessible-EL5GXZBS.js +0 -27
  514. /package/dist/{api-TXFOVOXX.js.map → api-GVYEKSJE.js.map} +0 -0
  515. /package/dist/{chunk-BUE2D7PX.js.map → chunk-32YV3TJT.js.map} +0 -0
  516. /package/dist/{chunk-3RCJJBNR.js.map → chunk-3ELRMVJK.js.map} +0 -0
  517. /package/dist/{chunk-6GMZ7HEE.js.map → chunk-3F7GLNAE.js.map} +0 -0
  518. /package/dist/{chunk-2Y4IMKA6.js.map → chunk-3H5KLDZN.js.map} +0 -0
  519. /package/dist/{chunk-VTFVLCUH.js.map → chunk-3JWHAR6E.js.map} +0 -0
  520. /package/dist/{chunk-JBDFMYKQ.js.map → chunk-4AF3TUMP.js.map} +0 -0
  521. /package/dist/{chunk-J6FXAEUG.js.map → chunk-6B3VNR4P.js.map} +0 -0
  522. /package/dist/{chunk-TUFM4UZP.js.map → chunk-6K7DPM7D.js.map} +0 -0
  523. /package/dist/{chunk-K6LHRFBL.js.map → chunk-6LMQ5R26.js.map} +0 -0
  524. /package/dist/{chunk-XLMEZIAJ.js.map → chunk-6OWXYZK2.js.map} +0 -0
  525. /package/dist/{chunk-BOWNCWZT.js.map → chunk-6QSQQLSE.js.map} +0 -0
  526. /package/dist/{chunk-NQKIUNW5.js.map → chunk-A6IJU4TK.js.map} +0 -0
  527. /package/dist/{chunk-QIZPZMUI.js.map → chunk-AOWGXU6D.js.map} +0 -0
  528. /package/dist/{chunk-SFAWCTEM.js.map → chunk-B57AFBY2.js.map} +0 -0
  529. /package/dist/{chunk-GPEQUXHL.js.map → chunk-B6SJIBQK.js.map} +0 -0
  530. /package/dist/{chunk-Q2PU57HC.js.map → chunk-BK2HHQGN.js.map} +0 -0
  531. /package/dist/{collection-facade-4GRREZ6C.js.map → chunk-BKT776R5.js.map} +0 -0
  532. /package/dist/{chunk-FXBIP2WD.js.map → chunk-BUDAGWL5.js.map} +0 -0
  533. /package/dist/{chunk-BOET4NA4.js.map → chunk-CKNGS5MH.js.map} +0 -0
  534. /package/dist/{chunk-YSRUYAVU.js.map → chunk-DE4DH2RZ.js.map} +0 -0
  535. /package/dist/{chunk-6I2RQCET.js.map → chunk-DF73H4UN.js.map} +0 -0
  536. /package/dist/{chunk-K7NTTA6P.js.map → chunk-EOVMT6TB.js.map} +0 -0
  537. /package/dist/{chunk-XTXOCYOJ.js.map → chunk-FCKWQE2H.js.map} +0 -0
  538. /package/dist/{chunk-4OZNXTO4.js.map → chunk-FN5EBVTQ.js.map} +0 -0
  539. /package/dist/{chunk-NKHRDYOR.js.map → chunk-FQ5VRHIB.js.map} +0 -0
  540. /package/dist/{chunk-FAHMLERK.js.map → chunk-FW22ZCXT.js.map} +0 -0
  541. /package/dist/{chunk-RMS3NEA3.js.map → chunk-HT2AHGQI.js.map} +0 -0
  542. /package/dist/{chunk-CHJBLCOG.js.map → chunk-HVSCEIYL.js.map} +0 -0
  543. /package/dist/{chunk-GY4WYNNG.js.map → chunk-ID6Z6E66.js.map} +0 -0
  544. /package/dist/{chunk-EYBQEIUY.js.map → chunk-IEX7NK2K.js.map} +0 -0
  545. /package/dist/{chunk-KUJDV5QH.js.map → chunk-ISZQJBML.js.map} +0 -0
  546. /package/dist/{chunk-LWBCUYZW.js.map → chunk-IT22PWKV.js.map} +0 -0
  547. /package/dist/{chunk-7V4TP3AF.js.map → chunk-J6UOHJY5.js.map} +0 -0
  548. /package/dist/{chunk-JMGDHKQF.js.map → chunk-JCN44NCY.js.map} +0 -0
  549. /package/dist/{chunk-CARABLSQ.js.map → chunk-K6W7BVZ6.js.map} +0 -0
  550. /package/dist/{chunk-453F654R.js.map → chunk-L7DOS3TE.js.map} +0 -0
  551. /package/dist/{chunk-WEQEYLCS.js.map → chunk-LGRLME4M.js.map} +0 -0
  552. /package/dist/{chunk-RMF67KCG.js.map → chunk-LQ4ZHOKP.js.map} +0 -0
  553. /package/dist/{chunk-ZVO4QVPD.js.map → chunk-M522UYZ2.js.map} +0 -0
  554. /package/dist/{chunk-2N4GY74U.js.map → chunk-MTL7MXGR.js.map} +0 -0
  555. /package/dist/{chunk-TFR7DSOV.js.map → chunk-MVZ2TPVP.js.map} +0 -0
  556. /package/dist/{chunk-CPWQB3N5.js.map → chunk-N5DNADLQ.js.map} +0 -0
  557. /package/dist/{chunk-ELNXJMGB.js.map → chunk-NNARWO72.js.map} +0 -0
  558. /package/dist/{chunk-6YXCPL4T.js.map → chunk-PDCG6PR5.js.map} +0 -0
  559. /package/dist/{chunk-REDOOY2Q.js.map → chunk-PSIV7CJV.js.map} +0 -0
  560. /package/dist/{chunk-ANATMFIO.js.map → chunk-QWFHIOD2.js.map} +0 -0
  561. /package/dist/{chunk-X2DLENDQ.js.map → chunk-QWGU66MP.js.map} +0 -0
  562. /package/dist/{chunk-BSFNRLK2.js.map → chunk-S57HTZ6X.js.map} +0 -0
  563. /package/dist/{chunk-SZJ3DLZA.js.map → chunk-SEE332EV.js.map} +0 -0
  564. /package/dist/{chunk-YYP7WSEB.js.map → chunk-SI3V7D4G.js.map} +0 -0
  565. /package/dist/{chunk-UGTBXF5U.js.map → chunk-SOIQ4MM4.js.map} +0 -0
  566. /package/dist/{chunk-VXGSWL6L.js.map → chunk-SYVZW77S.js.map} +0 -0
  567. /package/dist/{chunk-MVMXZYXT.js.map → chunk-TKUOEU2F.js.map} +0 -0
  568. /package/dist/{chunk-SMH6SRX7.js.map → chunk-TROR3ALR.js.map} +0 -0
  569. /package/dist/{chunk-DGOZ4UZD.js.map → chunk-VNNRUGMM.js.map} +0 -0
  570. /package/dist/{chunk-HDOU6I2Y.js.map → chunk-VNPEWFPD.js.map} +0 -0
  571. /package/dist/{chunk-L7CIOOBW.js.map → chunk-WNJ4AVGE.js.map} +0 -0
  572. /package/dist/{chunk-FMZY5Q6L.js.map → chunk-WX5ADGTZ.js.map} +0 -0
  573. /package/dist/{chunk-Q7HZX3IF.js.map → chunk-X4773RBR.js.map} +0 -0
  574. /package/dist/{chunk-ANSIZYEG.js.map → chunk-YNIUIERI.js.map} +0 -0
  575. /package/dist/{chunk-BZ3534YM.js.map → chunk-ZUVBC32X.js.map} +0 -0
  576. /package/dist/{chunk-L742JPKZ.js.map → chunk-ZXABPVM6.js.map} +0 -0
  577. /package/dist/{classified-marker-LI2SF2E4.js.map → classified-marker-W3USLL5M.js.map} +0 -0
  578. /package/dist/{computed-VPOKQK4N.js.map → collection-facade-QU6IJBN3.js.map} +0 -0
  579. /package/dist/{derive-6O5SWQKN.js.map → computed-TPFBX7U4.js.map} +0 -0
  580. /package/dist/{dead-filter-TSWZQRR5.js.map → dead-filter-U2UYKSZL.js.map} +0 -0
  581. /package/dist/{delegation-OVIFFPG4.js.map → delegation-S3AEPW2T.js.map} +0 -0
  582. /package/dist/{enclave-KJOTOH7X.js.map → derive-OX7F6TGG.js.map} +0 -0
  583. /package/dist/{dispatch-WC6X2M6C.js.map → dispatch-3CQDJV5Q.js.map} +0 -0
  584. /package/dist/{dispatch-S73TK3IY.js.map → dispatch-RH4LHKBH.js.map} +0 -0
  585. /package/dist/{executor-5NIMLSKZ.js.map → enclave-27SMF6GF.js.map} +0 -0
  586. /package/dist/{executor-AQVXV5GZ.js.map → executor-B6SRO2QS.js.map} +0 -0
  587. /package/dist/{executor-PUAO6AKJ.js.map → executor-BI5CHWRY.js.map} +0 -0
  588. /package/dist/{export-accessible-72EQNBMR.js.map → executor-RBKM5W5K.js.map} +0 -0
  589. /package/dist/{extract-partition-PUYNU3UF.js.map → export-accessible-VMA3YM5V.js.map} +0 -0
  590. /package/dist/{find-2ABFCZX4.js.map → extract-partition-NF7PXGPP.js.map} +0 -0
  591. /package/dist/{fanout-sidecar-WUFXNYP4.js.map → fanout-sidecar-OT6RYLOL.js.map} +0 -0
  592. /package/dist/{issue-SIDORTSZ.js.map → find-LZMP26KF.js.map} +0 -0
  593. /package/dist/{ledger-F33ZVMTK.js.map → issue-IHARXWW5.js.map} +0 -0
  594. /package/dist/{liberate-LCDPNAG2.js.map → ledger-KZPCMVZY.js.map} +0 -0
  595. /package/dist/{link-set-FKNWAYKS.js.map → liberate-GRLCZMW4.js.map} +0 -0
  596. /package/dist/{managed-secret-PQYKSR6T.js.map → link-set-JCMJ7ULP.js.map} +0 -0
  597. /package/dist/{noydb-DUXZPKSN.js.map → managed-secret-S3MQ6SH6.js.map} +0 -0
  598. /package/dist/{migrate-cek-5ENH64AA.js.map → migrate-cek-V7GKJZ7O.js.map} +0 -0
  599. /package/dist/{register-I2DZXGAR.js.map → noydb-SWQJ3MZS.js.map} +0 -0
  600. /package/dist/{pod-handle-Q736KYON.js.map → pod-handle-WGDFB4C2.js.map} +0 -0
  601. /package/dist/{post-register-LNE2FE2A.js.map → post-register-SLSXIPBV.js.map} +0 -0
  602. /package/dist/{registry-23WF3TGH.js.map → query/all/index.js.map} +0 -0
  603. /package/dist/{registry-4AYVUNXK.js.map → register-F3OYE7MJ.js.map} +0 -0
  604. /package/dist/{registry-VSSQPIGF.js.map → registry-CILQFXFK.js.map} +0 -0
  605. /package/dist/{registry-YLEWMGAC.js.map → registry-XNNYQVKV.js.map} +0 -0
  606. /package/dist/{request-withdrawal-KFQHEZ25.js.map → registry-YCDZV3VW.js.map} +0 -0
  607. /package/dist/{revoke-DQDZAZZM.js.map → registry-ZGYS33TE.js.map} +0 -0
  608. /package/dist/{signer-WAMDZHEN.js.map → request-withdrawal-Z5NC6TXT.js.map} +0 -0
  609. /package/dist/{reveal-67RDQRIN.js.map → reveal-4BCKPEC2.js.map} +0 -0
  610. /package/dist/{stale-DDL7WQEZ.js.map → revoke-ZL62WC2D.js.map} +0 -0
  611. /package/dist/{seed-G42JYN56.js.map → seed-4JS2RJ4A.js.map} +0 -0
  612. /package/dist/{storage-FLR73HHF.js.map → signer-MBZZMXTC.js.map} +0 -0
  613. /package/dist/{walk-3UQBRMDV.js.map → stale-TJ3DYZMQ.js.map} +0 -0
  614. /package/dist/{withdraw-accessible-EL5GXZBS.js.map → storage-SVMKRGCW.js.map} +0 -0
  615. /package/dist/{store-coordination-provider-MEQ2MJQG.js.map → store-coordination-provider-2O2VUHKW.js.map} +0 -0
  616. /package/dist/{verify-KOV2G5D6.js.map → verify-RVT67IMH.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/kernel/query/scan-builder.ts"],"sourcesContent":["/**\n * Streaming scan builder with filter + aggregate support.\n *\n * `Collection.scan()` now returns a `ScanBuilder<T>` that\n * implements `AsyncIterable<T>` (for existing `for await … of`\n * consumers) AND exposes chainable `.where()` / `.filter()` clauses\n * plus a `.aggregate(spec)` async terminal that reduces the scan\n * stream through the same reducer protocol as `Query.aggregate()`\n *.\n *\n * **Memory model:** O(reducers), not O(records). The aggregate\n * terminal initializes one state per reducer, iterates through the\n * scan one record at a time via `for await`, applies every reducer's\n * `step` per record, and never collects the stream into an array.\n * This is what makes `scan().aggregate()` suitable for collections\n * that don't fit in memory — the bound is a code-level invariant\n * visible in the function body, not a runtime assertion.\n *\n * **Paginated iteration:** the builder holds a `pageProvider`\n * closure that maps `(cursor, limit) → Promise<page>`, plumbed by\n * `Collection.scan()` to `collection.listPage(...)`. The page\n * iterator walks cursors forward until exhaustion, same as the\n * previous async-generator `scan()` did.\n *\n * **Backward compatibility:** existing `for await (const rec of\n * collection.scan()) { … }` code continues to work because\n * `ScanBuilder` implements `[Symbol.asyncIterator]`. The previous\n * signature returned an `AsyncIterableIterator<T>` (which has both\n * `[Symbol.asyncIterator]` and `.next()`). We verified at grep time\n * that no call sites use `.next()` on the scan result directly, so\n * the narrowed interface is safe.\n *\n * **Immutability:** each `.where()` / `.filter()` call returns a\n * fresh builder sharing the same page provider and page size. This\n * lets a base scan be reused for multiple parallel aggregations:\n *\n * ```ts\n * const scan = invoices.scan()\n * const [open, paid] = await Promise.all([\n * scan.where('status', '==', 'open').aggregate({ n: count() }),\n * scan.where('status', '==', 'paid').aggregate({ n: count() }),\n * ])\n * ```\n *\n * Note that each aggregation pays a full scan — there's no shared\n * iteration across the two. When the specs are known together, pass\n * them as an ARRAY (#1340): `.aggregate([specA, specB])` steps every\n * spec's state from the same yielded record, so N specs cost one\n * pass, not N.\n *\n * **Out of scope for (tracked separately):**\n * - `scan().aggregate().live()` — unbounded scan + change-stream\n * reconciliation is a design problem, not just a code one, and\n * #1340 deliberately left it out\n * - Parallel scan across pages — race-safe page cursor contracts\n * are not in the adapter API yet\n * - `scan().join(...)` — tracked under (streaming join)\n */\n\nimport type { QueryField } from '../types.js'\nimport type { Clause, FieldClause, Operator } from './predicate.js'\nimport { evaluateClause, hasFnClause, normalizeMatches, normalizeSubqueryOperand } from './predicate.js'\nimport type { ReduceSpec, ReduceResult } from '../../with-lookup/reduce/reduction.js'\n// ─── #1458 — Relate is TYPE-ONLY here, same as in `builder.ts` ───────────\n// The streaming iterator has to be able to run a plan that carries legs; it\n// cannot BUILD one. `splitAroundJoins` is the Find-side shim (join-conditional,\n// with the empty answer inline) that `builder.ts` publishes for both builders,\n// so the two cannot drift on what \"pre-join\" means.\nimport type { JoinContext, JoinLeg } from './relate/join.js'\nimport type { ScanJoinResolver } from './relate/scan-methods.js'\nimport { splitAroundJoins } from './builder.js'\nimport { FieldNotQueryableError, QueryExtensionMissingError } from '../errors.js'\nimport type { ViaPipeline } from '../via/pipeline.js'\n\n/**\n * Result of the multi-spec `.aggregate([specA, specB, …])` form (#1340) — a\n * tuple positionally matching the specs, each element the shape that spec's\n * own single-spec `.aggregate()` would have returned.\n */\nexport type MultiReduceResult<Specs extends readonly ReduceSpec[]> = {\n -readonly [K in keyof Specs]: ReduceResult<Specs[K]>\n}\n\n/**\n * Page provider — the Collection-shaped hook the builder calls to\n * walk cursors forward. Kept as a structural interface so tests can\n * wire up a synthetic provider without pulling in the full\n * Collection class. Collection's `listPage` matches this shape\n * exactly.\n */\nexport interface ScanPageProvider<T> {\n listPage(opts: {\n cursor?: string\n limit?: number\n }): Promise<{ items: T[]; nextCursor: string | null }>\n}\n\nconst DEFAULT_SCAN_PAGE_SIZE = 100\n\n/**\n * Chainable streaming scan. Implements `AsyncIterable<T>` for\n * drop-in use with `for await … of`; adds `.where()` / `.filter()`\n * chainable clauses and a `.aggregate(spec)` async terminal.\n *\n * The builder is immutable per operation — each chained call\n * returns a fresh `ScanBuilder` sharing the same page provider and\n * page size. The original builder is never mutated, so it's safe\n * to reuse across multiple parallel consumers.\n */\nexport class ScanBuilder<T, S extends keyof T = never, M extends keyof T & string = never> implements AsyncIterable<T> {\n private readonly pageProvider: ScanPageProvider<T>\n private readonly pageSize: number\n private readonly clauses: readonly Clause[]\n /**\n * Zero-or-more join legs to apply per record as the stream flows.\n * Each leg attaches the resolved right-side record (or null) under\n * its alias. — streaming joins.\n *\n * Joins are evaluated AFTER clauses, so a `where()` filtered-out\n * record never triggers a right-side lookup. This is the same\n * ordering as `Query.toArray()` (clauses first, joins after) and\n * keeps the streaming path from doing wasted work.\n */\n private readonly joins: readonly JoinLeg[]\n /**\n * Join resolution context. Required for `.join()` to translate a\n * field name into a target collection + ref mode and to resolve\n * the right-side `JoinableSource`. Optional because tests\n * construct ScanBuilder directly with synthetic page providers\n * that don't know about ref() — calling `.join()` without a\n * context throws with an actionable error.\n */\n private readonly joinContext: JoinContext | undefined\n /**\n * The backing collection's compiled Via pipeline (money now; more Via\n * features later). When it declares a result decode, yielded records\n * are decoded (e.g. money: stored scaled-int → canonical decimal) so\n * `scan()` agrees with `get()`/`list()`/`query().toArray()`. Decoded\n * with `'raw'` (canonical decimal, no locale-formatted virtuals) since\n * the scan stream carries no locale context, mirroring `Query.toArray()`.\n */\n private readonly via: ViaPipeline | undefined\n\n // ─── #1458 — installed by the extension subpaths ────────────────────────\n //\n // `ScanBuilder` is split the same way `Query` is: Find here, Reduce and\n // Relate in `@noy-db/hub/query/{reduce,relate}`. These two are declared\n // rather than defined because the ITERATOR below calls them, and it stays in\n // Find — both calls are behind `joins.length === 0`, which only Relate's\n // `join()` can make false.\n declare protected buildJoinResolvers: () => ScanJoinResolver[]\n declare protected applyOneJoinStreaming: (record: unknown, resolver: ScanJoinResolver) => unknown\n\n constructor(\n pageProvider: ScanPageProvider<T>,\n pageSize: number = DEFAULT_SCAN_PAGE_SIZE,\n clauses: readonly Clause[] = [],\n joins: readonly JoinLeg[] = [],\n joinContext?: JoinContext,\n via?: ViaPipeline,\n ) {\n this.pageProvider = pageProvider\n this.pageSize = pageSize\n this.clauses = clauses\n this.joins = joins\n this.joinContext = joinContext\n this.via = via\n }\n\n /**\n * Decode this scan's Via-covered fields on a record (e.g. money: stored\n * scaled-int → canonical decimal). No-op when the Via pipeline declares\n * no result decode. See {@link via}.\n */\n private decodeVia(record: T): T {\n if (!this.via || !this.via.hasResultDecode) return record\n return this.via.decodeResults(record) as T\n }\n\n /**\n * Add a field comparison. Runs per record as the scan stream\n * flows through, so non-matching records are dropped before they\n * reach `.aggregate()` or the iteration consumer. Multiple\n * `.where()` calls are AND-combined — same semantics as\n * `Query.where()`.\n *\n * Clauses cannot use the secondary-index fast path here because\n * the scan sources records from the adapter's paginator, not from\n * the in-memory cache where indexes live. Index-accelerated scans\n * are a future optimization — the current implementation\n * evaluates clauses per record in O(1) per clause.\n *\n * Consults the Via pipeline's posture before building a clause (#629\n * Task 8): a field whose posture is `queryable: 'none'` throws\n * `FieldNotQueryableError` here, at the call site — same gate as\n * `Query.where()`.\n */\n where(field: QueryField<T, S>, op: Operator, value: unknown): ScanBuilder<T, S, M> {\n // A Via-covered field (e.g. money) compares in major units, BigInt-exact\n // in scaled space — same build-time operand rewrite as Query.where().\n const via = this.via\n if (via?.postureFor(field as string)?.queryable === 'none') throw new FieldNotQueryableError(field as string)\n // #1357: a 'matches' operand is refused-or-normalized HERE, at the call\n // site — an anchored literal prefix lowers to `startsWith` (taking the\n // sorted index), anything else serializes to `{ source, flags }` so the\n // pattern folds into an MV's queryHash. Every other operator is identity.\n // #1351: a SUBQUERY operand of `in`/`!in` resolves to its id array here,\n // at build time — same normalization order as `Query.where()`, so all\n // three builders turn the same call into the same clause.\n const { op: sop, value: sval, subquery } = normalizeSubqueryOperand(op, value)\n const { op: mop, value: mval } = normalizeMatches(sop, sval)\n const viaClause = via?.buildClause(field as string, mop, mval)\n const clause: FieldClause = viaClause\n ? {\n type: 'field',\n field: field as string,\n op: mop,\n value: mval,\n ...(subquery ? { subquery } : {}),\n via: {\n brand: viaClause.brand,\n payload: viaClause.payload,\n evaluate: (actual: unknown, evalOp: string) => via!.evaluateClause(viaClause, actual, evalOp),\n },\n }\n : { type: 'field', field: field as string, op: mop, value: mval, ...(subquery ? { subquery } : {}) }\n return new ScanBuilder<T, S, M>(\n this.pageProvider,\n this.pageSize,\n [...this.clauses, clause],\n this.joins,\n this.joinContext,\n this.via,\n )\n }\n\n /**\n * Escape hatch: add an arbitrary predicate function. Same\n * non-serializable caveat as `Query.filter()` — filter clauses\n * don't round-trip through `toPlan()`. Prefer `.where()` when\n * possible.\n */\n filter(fn: (record: T) => boolean): ScanBuilder<T, S, M> {\n const clause: Clause = {\n type: 'filter',\n fn: fn as (record: unknown) => boolean,\n }\n return new ScanBuilder<T, S, M>(\n this.pageProvider,\n this.pageSize,\n [...this.clauses, clause],\n this.joins,\n this.joinContext,\n this.via,\n )\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<T> {\n // One-time setup: resolve every join leg's right-side source\n // and pick its strategy (lookupById per row vs hash from\n // snapshot once). Both are O(left) per record after setup; the\n // difference is the upfront cost of hashing the right side\n // when there's no lookupById.\n //\n // Hash maps live for the lifetime of the iteration, so memory\n // for the right side is O(rightRowCount) per leg. Memory for\n // the left side stays O(pageSize) regardless — that's the\n // streaming property we're after.\n const joinResolvers = this.joins.length === 0 ? null : this.buildJoinResolvers()\n // #1030 — a clause addressing a join alias cannot be evaluated against the\n // raw record, where the alias does not exist yet. Split once per\n // iteration, not per record. Streaming pays nothing for this: the\n // post-join predicate runs on the row already in hand, so the O(pageSize)\n // memory property is untouched.\n const { preJoin, postJoin } = splitAroundJoins(this.clauses, this.joins)\n\n let page = await this.pageProvider.listPage({ limit: this.pageSize })\n while (true) {\n for (const record of page.items) {\n // Filter on the raw stored record (same order as Query.toArray:\n // clauses first), then decode Via-covered fields (e.g. money, to\n // the canonical decimal) before yielding so scan() never leaks the\n // internal stored representation.\n if (!this.recordMatches(record, preJoin)) continue\n const decoded = this.decodeVia(record)\n if (joinResolvers === null) {\n yield decoded\n } else {\n // Apply every join leg in declaration order. Each\n // leg attaches a field — the result of one leg becomes\n // the input to the next. Multi-FK chaining is\n // supported by construction.\n let attached: unknown = decoded\n for (const resolver of joinResolvers) {\n attached = this.applyOneJoinStreaming(attached, resolver)\n }\n if (postJoin.length > 0 && !this.recordMatches(attached as T, postJoin)) continue\n yield attached as T\n }\n }\n if (page.nextCursor === null) return\n page = await this.pageProvider.listPage({\n cursor: page.nextCursor,\n limit: this.pageSize,\n })\n }\n }\n\n /**\n * Evaluate the clause list against a single record. Linear in\n * the clause count; short-circuits on first false. Clauses on a\n * scan are always re-evaluated per record — no index-accelerated\n * path, because the stream sources records from the adapter\n * paginator, not from the in-memory cache where indexes live.\n */\n private recordMatches(record: T, clauses: readonly Clause[] = this.clauses): boolean {\n if (clauses.length === 0) return true\n // User-callback clauses (filter) see the DECODED view (e.g. money's\n // canonical decimal); field clauses keep the raw record — their\n // operands are pre-built into stored space. Decoded at most once per\n // record, only when a callback clause exists.\n const fnView =\n this.via?.hasResultDecode && hasFnClause(clauses)\n ? this.decodeVia(record)\n : undefined\n for (const clause of clauses) {\n if (!evaluateClause(record, clause, fnView)) return false\n }\n return true\n }\n}\n\n// ─── #1458 — ScanBuilder's extension stubs ────────────────────────────────\n// Same mechanism, and the same reason for not declaring them on the class, as\n// `builder.ts`'s block: the method's TYPE must arrive with its subpath.\nconst SCAN_EXTENSION_METHODS: readonly (readonly [string, string])[] = [\n ['aggregate', '@noy-db/hub/query/reduce'],\n ['groupBy', '@noy-db/hub/query/reduce'],\n ['join', '@noy-db/hub/query/relate'],\n]\n\nfor (const [method, subpath] of SCAN_EXTENSION_METHODS) {\n Object.defineProperty(ScanBuilder.prototype, method, {\n value: function scanExtensionMissing(): never {\n throw new QueryExtensionMissingError(`scan().${method}`, subpath)\n },\n writable: true,\n enumerable: false,\n configurable: true,\n })\n}\n\n\n/**\n * ── Grouped streaming reduction over a `scan()` — `#1340` ──────────────────\n *\n * `scan().groupBy(key, { maxGroups }).aggregate(spec)` folds an unbounded,\n * page-by-page scan into one row per group. The distinguishing property\n * against the eager `Query.groupBy()` path is WHAT IS HELD:\n *\n * - eager (`groupAndReduce` in `with-lookup/reduce/groupby.ts`) partitions\n * the matched records into `Map<key, records[]>` and reduces each bucket\n * afterwards — O(matched records) memory;\n * - this one holds **one reducer state per group and no records at all** —\n * O(groups × state), with the left side still streaming at O(pageSize).\n *\n * So the two cannot share an implementation, and this deliberately does\n * NOT use `groupAndReduce`: reusing it would mean collecting the stream,\n * which is the exact thing `scan()` exists to avoid. What IS shared is every\n * piece that decides SEMANTICS — the group-key canonicalisation (so `null`\n * and `undefined` bucket apart here exactly as they do there), the reducer\n * protocol, `ViaPipeline.wrapReducers` (money stays BigInt-exact),\n * `bindDistinctReducers` (`countDistinct` dedups on the canonical index key),\n * and `projectDateTruncKeys` (a derived calendar key is stamped onto a\n * shallow copy of the row before bucketing, same as `Query.groupBy()`).\n *\n * ## The memory budget IS the feature\n *\n * `maxGroups` defaults to `GROUPBY_MAX_CARDINALITY` (100_000) — the same\n * ceiling the eager path enforces — and is refused the moment the group that\n * would exceed it is first seen, mid-stream, before its state is allocated.\n * ⛔ It never truncates: a truncated rollup is a WRONG ANSWER that looks like\n * a right one, and the whole point of declaring a budget is to learn that the\n * grouping does not fit. The refusal names the option and the observed count.\n *\n * ⚠️ **Per-group state is NOT constant.** `count`/`sum`/`avg`/`min`/`max` are\n * O(1) per group, but `median`/`percentile` (exact) hold every sampled value\n * — O(n) per group — `mode` holds one entry per distinct value, and\n * `countDistinct` one per distinct value. A grouped scan with an exact\n * `median` is therefore O(matched records) overall no matter what `maxGroups`\n * says, since the values live in the group states. Pair it with\n * `{ approx: true }` (the t-digest, bounded per group) when the scan is\n * genuinely unbounded — that is what makes `maxGroups` a real ceiling rather\n * than an accounting fiction.\n *\n * ## Post-group `having` / `orderBy` / `limit` (#1336) are NOT on this path\n *\n * Those live on `GroupedReduction`, which is built around a SYNCHRONOUS\n * `executeRecords()` closure and the eager pipeline; a scan has neither.\n * Rather than grow a second, subtly different implementation of the same\n * three operations, this terminal returns the row array — bounded by\n * `maxGroups` and already in memory — and the caller filters, sorts and\n * slices it. See the report on #1340; if a consumer wants the chainable\n * shape, the honest fix is to lift the post-group stage out of\n * `GroupedReduction` and share it, not to copy it here.\n *\n * ⚠️ Lives in THIS file rather than its own `scan-groupby.ts` for one\n * mechanical reason: `check-architecture`'s `port-layering` ratchet\n * grandfathers `scan-builder.ts`'s two `with-lookup/reduce/*` imports per\n * specifier, and a NEW kernel file may not statically import a `with-*`\n * service at all. Splitting it out means either a dynamic import on the\n * reducer protocol or a new grandfather entry; neither is worth it for a\n * class that only exists to terminate `ScanBuilder.groupBy()`.\n */\n"],"mappings":"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","names":[]}
@@ -0,0 +1,456 @@
1
+ import {
2
+ distinctKeyOf
3
+ } from "./chunk-SUZKW6UR.js";
4
+ import {
5
+ readPath
6
+ } from "./chunk-HLEK5VAN.js";
7
+
8
+ // src/with-lookup/reduce/reducers.ts
9
+ function count(opts) {
10
+ const _seed = opts?.seed;
11
+ void _seed;
12
+ return {
13
+ op: "count",
14
+ init: () => 0,
15
+ step: (state) => state + 1,
16
+ remove: (state) => state - 1,
17
+ finalize: (state) => state,
18
+ merge: (a, b) => a + b
19
+ };
20
+ }
21
+ function countDistinct(field, opts) {
22
+ const _seed = opts?.seed;
23
+ void _seed;
24
+ const via = opts?.canonicalize;
25
+ const keyOf = (record) => distinctKeyOf(field, readPath(record, field), via);
26
+ return {
27
+ op: "countDistinct",
28
+ field,
29
+ init: () => ({ counts: /* @__PURE__ */ new Map() }),
30
+ step: (state, record) => {
31
+ const key = keyOf(record);
32
+ if (key === void 0) return state;
33
+ const counts = new Map(state.counts);
34
+ counts.set(key, (counts.get(key) ?? 0) + 1);
35
+ return { counts };
36
+ },
37
+ remove: (state, record) => {
38
+ const key = keyOf(record);
39
+ if (key === void 0) return state;
40
+ const current = state.counts.get(key);
41
+ if (current === void 0) return state;
42
+ const counts = new Map(state.counts);
43
+ if (current <= 1) counts.delete(key);
44
+ else counts.set(key, current - 1);
45
+ return { counts };
46
+ },
47
+ finalize: (state) => state.counts.size,
48
+ merge: (a, b) => {
49
+ const counts = new Map(a.counts);
50
+ for (const [k, n] of b.counts) counts.set(k, (counts.get(k) ?? 0) + n);
51
+ return { counts };
52
+ }
53
+ };
54
+ }
55
+ function bindDistinctReducers(spec, via) {
56
+ if (!via) return spec;
57
+ const entries = Object.entries(spec);
58
+ let changed = false;
59
+ const out = {};
60
+ for (const [key, reducer] of entries) {
61
+ if (reducer?.op === "countDistinct" && typeof reducer.field === "string") {
62
+ out[key] = countDistinct(reducer.field, { canonicalize: via });
63
+ changed = true;
64
+ } else {
65
+ out[key] = reducer;
66
+ }
67
+ }
68
+ return changed ? out : spec;
69
+ }
70
+ function sum(field, opts) {
71
+ const _seed = opts?.seed;
72
+ void _seed;
73
+ return {
74
+ op: "sum",
75
+ field,
76
+ // Money-only metadata, read by `wrapMoneyReducers`. No effect on a
77
+ // generic numeric sum.
78
+ ...opts?.convertTo !== void 0 ? { convertTo: opts.convertTo } : {},
79
+ ...opts?.fx !== void 0 ? { fx: opts.fx } : {},
80
+ init: () => 0,
81
+ step: (state, record) => state + readNumber(record, field),
82
+ remove: (state, record) => state - readNumber(record, field),
83
+ finalize: (state) => state,
84
+ merge: (a, b) => a + b
85
+ };
86
+ }
87
+ function avg(field, opts) {
88
+ const _seed = opts?.seed;
89
+ void _seed;
90
+ return {
91
+ op: "avg",
92
+ field,
93
+ init: () => ({ sum: 0, count: 0 }),
94
+ step: (state, record) => ({
95
+ sum: state.sum + readNumber(record, field),
96
+ count: state.count + 1
97
+ }),
98
+ remove: (state, record) => ({
99
+ sum: state.sum - readNumber(record, field),
100
+ count: state.count - 1
101
+ }),
102
+ finalize: (state) => state.count === 0 ? null : state.sum / state.count,
103
+ merge: (a, b) => ({ sum: a.sum + b.sum, count: a.count + b.count })
104
+ };
105
+ }
106
+ function pushValue(state, value) {
107
+ return { values: [...state.values, value] };
108
+ }
109
+ function removeValue(state, value) {
110
+ const idx = state.values.indexOf(value);
111
+ if (idx < 0) return state;
112
+ const next = state.values.slice();
113
+ next.splice(idx, 1);
114
+ return { values: next };
115
+ }
116
+ function min(field, opts) {
117
+ const _seed = opts?.seed;
118
+ void _seed;
119
+ return {
120
+ op: "min",
121
+ field,
122
+ init: () => ({ values: [] }),
123
+ step: (state, record) => pushValue(state, readNumber(record, field)),
124
+ remove: (state, record) => removeValue(state, readNumber(record, field)),
125
+ finalize: (state) => {
126
+ if (state.values.length === 0) return null;
127
+ let out = state.values[0];
128
+ for (let i = 1; i < state.values.length; i++) {
129
+ const v = state.values[i];
130
+ if (v < out) out = v;
131
+ }
132
+ return out;
133
+ },
134
+ merge: (a, b) => ({ values: [...a.values, ...b.values] })
135
+ };
136
+ }
137
+ function max(field, opts) {
138
+ const _seed = opts?.seed;
139
+ void _seed;
140
+ return {
141
+ op: "max",
142
+ field,
143
+ init: () => ({ values: [] }),
144
+ step: (state, record) => pushValue(state, readNumber(record, field)),
145
+ remove: (state, record) => removeValue(state, readNumber(record, field)),
146
+ finalize: (state) => {
147
+ if (state.values.length === 0) return null;
148
+ let out = state.values[0];
149
+ for (let i = 1; i < state.values.length; i++) {
150
+ const v = state.values[i];
151
+ if (v > out) out = v;
152
+ }
153
+ return out;
154
+ },
155
+ merge: (a, b) => ({ values: [...a.values, ...b.values] })
156
+ };
157
+ }
158
+ function welfordReducer(op, field, population) {
159
+ return {
160
+ op,
161
+ field,
162
+ init: () => ({ n: 0, mean: 0, m2: 0 }),
163
+ step: (state, record) => {
164
+ const x = readNumber(record, field);
165
+ const n = state.n + 1;
166
+ const delta = x - state.mean;
167
+ const mean = state.mean + delta / n;
168
+ return { n, mean, m2: state.m2 + delta * (x - mean) };
169
+ },
170
+ remove: (state, record) => {
171
+ const x = readNumber(record, field);
172
+ const n = state.n - 1;
173
+ if (n <= 0) return { n: 0, mean: 0, m2: 0 };
174
+ const mean = (state.mean * state.n - x) / n;
175
+ return { n, mean, m2: state.m2 - (x - state.mean) * (x - mean) };
176
+ },
177
+ // Chan et al.'s parallel combination — the reason a reduction can be
178
+ // sharded and rolled up without re-reading the leaves.
179
+ merge: (a, b) => {
180
+ if (a.n === 0) return b;
181
+ if (b.n === 0) return a;
182
+ const n = a.n + b.n;
183
+ const delta = b.mean - a.mean;
184
+ return {
185
+ n,
186
+ mean: a.mean + delta * b.n / n,
187
+ m2: a.m2 + b.m2 + delta * delta * a.n * b.n / n
188
+ };
189
+ },
190
+ finalize: (state) => {
191
+ const divisor = population ? state.n : state.n - 1;
192
+ if (divisor <= 0) return null;
193
+ const v = state.m2 / divisor;
194
+ return op === "stddev" ? Math.sqrt(v) : v;
195
+ }
196
+ };
197
+ }
198
+ function variance(field, opts) {
199
+ const _seed = opts?.seed;
200
+ void _seed;
201
+ return welfordReducer("variance", field, opts?.population === true);
202
+ }
203
+ function stddev(field, opts) {
204
+ const _seed = opts?.seed;
205
+ void _seed;
206
+ return welfordReducer("stddev", field, opts?.population === true);
207
+ }
208
+ function assertProbability(op, p) {
209
+ if (!Number.isFinite(p) || p < 0 || p > 1) {
210
+ throw new Error(`${op}(): p must be a number between 0 and 1, got ${p}.`);
211
+ }
212
+ }
213
+ function asExact(state) {
214
+ if (state.kind !== "exact") throw new Error("percentile: expected the exact quantile state");
215
+ return state;
216
+ }
217
+ function asDigest(state) {
218
+ if (state.kind !== "tdigest") throw new Error("percentile: expected the t-digest state");
219
+ return state;
220
+ }
221
+ function quantileOf(values, p) {
222
+ const n = values.length;
223
+ if (n === 0) return null;
224
+ if (n === 1) return values[0];
225
+ const sorted = [...values].sort((a, b) => a - b);
226
+ const x = p * (n - 1);
227
+ const lo = Math.floor(x);
228
+ const frac = x - lo;
229
+ if (frac === 0) return sorted[lo];
230
+ return sorted[lo] + (sorted[lo + 1] - sorted[lo]) * frac;
231
+ }
232
+ var TDIGEST_COMPRESSION = 100;
233
+ var TDIGEST_BUFFER = 256;
234
+ function tdigestFlush(state, force = false) {
235
+ if (state.buffer.length === 0 && !force) return;
236
+ const all = state.centroids.concat(state.buffer.map((mean) => ({ mean, count: 1 })));
237
+ state.buffer = [];
238
+ if (all.length === 0) return;
239
+ all.sort((a, b) => a.mean - b.mean);
240
+ const total = state.n;
241
+ const out = [];
242
+ let curMean = all[0].mean;
243
+ let curCount = all[0].count;
244
+ let before = 0;
245
+ for (let i = 1; i < all.length; i++) {
246
+ const c = all[i];
247
+ const q = (before + curCount + c.count / 2) / total;
248
+ const limit = 4 * total * q * (1 - q) / TDIGEST_COMPRESSION;
249
+ if (curCount + c.count <= Math.max(limit, 1)) {
250
+ const count2 = curCount + c.count;
251
+ curMean = curMean + (c.mean - curMean) * c.count / count2;
252
+ curCount = count2;
253
+ } else {
254
+ out.push({ mean: curMean, count: curCount });
255
+ before += curCount;
256
+ curMean = c.mean;
257
+ curCount = c.count;
258
+ }
259
+ }
260
+ out.push({ mean: curMean, count: curCount });
261
+ state.centroids = out;
262
+ }
263
+ function tdigestQuantile(state, p) {
264
+ tdigestFlush(state);
265
+ const cs = state.centroids;
266
+ if (cs.length === 0) return null;
267
+ if (cs.length === 1) return cs[0].mean;
268
+ const centres = [];
269
+ let acc = 0;
270
+ for (const c of cs) {
271
+ centres.push(acc + (c.count - 1) / 2);
272
+ acc += c.count;
273
+ }
274
+ const target = p * (state.n - 1);
275
+ const last = cs.length - 1;
276
+ if (target <= centres[0]) return cs[0].mean;
277
+ if (target >= centres[last]) return cs[last].mean;
278
+ for (let i = 0; i < last; i++) {
279
+ const a = centres[i];
280
+ const b = centres[i + 1];
281
+ if (target <= b) {
282
+ const t = b === a ? 0 : (target - a) / (b - a);
283
+ return cs[i].mean + (cs[i + 1].mean - cs[i].mean) * t;
284
+ }
285
+ }
286
+ return cs[last].mean;
287
+ }
288
+ function exactQuantileReducer(op, field, p) {
289
+ return {
290
+ op,
291
+ field,
292
+ p,
293
+ init: () => ({ kind: "exact", values: [] }),
294
+ step: (state, record) => {
295
+ asExact(state).values.push(readNumber(record, field));
296
+ return state;
297
+ },
298
+ remove: (state, record) => {
299
+ const values = asExact(state).values;
300
+ const idx = values.indexOf(readNumber(record, field));
301
+ if (idx >= 0) values.splice(idx, 1);
302
+ return state;
303
+ },
304
+ merge: (a, b) => ({ kind: "exact", values: [...asExact(a).values, ...asExact(b).values] }),
305
+ finalize: (state) => quantileOf(asExact(state).values, p)
306
+ };
307
+ }
308
+ function approxQuantileReducer(field, p) {
309
+ return {
310
+ op: "percentile",
311
+ field,
312
+ p,
313
+ approx: true,
314
+ init: () => ({ kind: "tdigest", centroids: [], buffer: [], n: 0 }),
315
+ step: (state, record) => {
316
+ const d = asDigest(state);
317
+ d.buffer.push(readNumber(record, field));
318
+ d.n += 1;
319
+ if (d.buffer.length >= TDIGEST_BUFFER) tdigestFlush(d);
320
+ return state;
321
+ },
322
+ // No `remove`: a centroid has forgotten which values it absorbed, so an
323
+ // un-fold is not expressible. Deliberate, and asserted by a test.
324
+ merge: (a, b) => {
325
+ const A = asDigest(a);
326
+ const B = asDigest(b);
327
+ const s = {
328
+ kind: "tdigest",
329
+ centroids: [...A.centroids, ...B.centroids],
330
+ buffer: [...A.buffer, ...B.buffer],
331
+ n: A.n + B.n
332
+ };
333
+ tdigestFlush(s, true);
334
+ return s;
335
+ },
336
+ finalize: (state) => tdigestQuantile(asDigest(state), p)
337
+ };
338
+ }
339
+ function median(field, opts) {
340
+ const _seed = opts?.seed;
341
+ void _seed;
342
+ return exactQuantileReducer("median", field, 0.5);
343
+ }
344
+ function percentile(field, p, opts) {
345
+ assertProbability("percentile", p);
346
+ const _seed = opts?.seed;
347
+ void _seed;
348
+ return opts?.approx === true ? approxQuantileReducer(field, p) : exactQuantileReducer("percentile", field, p);
349
+ }
350
+ function mode(field, opts) {
351
+ const _seed = opts?.seed;
352
+ void _seed;
353
+ return {
354
+ op: "mode",
355
+ field,
356
+ init: () => ({ counts: /* @__PURE__ */ new Map() }),
357
+ step: (state, record) => {
358
+ const v = readNumber(record, field);
359
+ state.counts.set(v, (state.counts.get(v) ?? 0) + 1);
360
+ return state;
361
+ },
362
+ remove: (state, record) => {
363
+ const v = readNumber(record, field);
364
+ const current = state.counts.get(v);
365
+ if (current === void 0) return state;
366
+ if (current <= 1) state.counts.delete(v);
367
+ else state.counts.set(v, current - 1);
368
+ return state;
369
+ },
370
+ merge: (a, b) => {
371
+ const counts = new Map(a.counts);
372
+ for (const [v, c] of b.counts) counts.set(v, (counts.get(v) ?? 0) + c);
373
+ return { counts };
374
+ },
375
+ finalize: (state) => {
376
+ let best = null;
377
+ let bestCount = 0;
378
+ for (const [v, c] of state.counts) {
379
+ if (c > bestCount || c === bestCount && best !== null && v < best) {
380
+ best = v;
381
+ bestCount = c;
382
+ }
383
+ }
384
+ return best;
385
+ }
386
+ };
387
+ }
388
+ function moneySum(field, opts) {
389
+ return sum(field, opts);
390
+ }
391
+ function moneyMin(field, opts) {
392
+ return min(field, opts);
393
+ }
394
+ function moneyMax(field, opts) {
395
+ return max(field, opts);
396
+ }
397
+ function moneyMedian(field, opts) {
398
+ return median(field, opts);
399
+ }
400
+ function moneyPercentile(field, p, opts) {
401
+ return percentile(field, p, opts);
402
+ }
403
+ var reducerBuilder = {
404
+ count,
405
+ countDistinct,
406
+ // The generic F parameter on sum/min/max in the interface is type-only; the
407
+ // standalone factories are plain `(field: string)` functions. With M=never the
408
+ // conditional return collapses to the numeric branch, matching the factories'
409
+ // return type, but TypeScript cannot verify that collapse for a generic method
410
+ // signature — so each factory is cast directly to the method's type.
411
+ sum,
412
+ avg,
413
+ min,
414
+ max,
415
+ median,
416
+ percentile,
417
+ variance,
418
+ stddev,
419
+ mode,
420
+ moneySum,
421
+ moneyMin,
422
+ moneyMax,
423
+ moneyMedian,
424
+ moneyPercentile
425
+ };
426
+ function readNumber(record, field) {
427
+ const value = readPath(record, field);
428
+ if (typeof value === "object" && value !== null && "amount" in value && "currency" in value) {
429
+ throw new Error(
430
+ `aggregate: field "${field}" holds a money value but was not money-aware \u2014 declare it in the collection's moneyFields so sum/min/max stay exact`
431
+ );
432
+ }
433
+ return typeof value === "number" && Number.isFinite(value) ? value : 0;
434
+ }
435
+
436
+ export {
437
+ count,
438
+ countDistinct,
439
+ bindDistinctReducers,
440
+ sum,
441
+ avg,
442
+ min,
443
+ max,
444
+ variance,
445
+ stddev,
446
+ median,
447
+ percentile,
448
+ mode,
449
+ moneySum,
450
+ moneyMin,
451
+ moneyMax,
452
+ moneyMedian,
453
+ moneyPercentile,
454
+ reducerBuilder
455
+ };
456
+ //# sourceMappingURL=chunk-F2TDU7MQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/with-lookup/reduce/reducers.ts"],"sourcesContent":["/**\n * Reduction reducers for the query DSL.\n *\n * the reducer protocol plus five built-in factories\n * (`count`, `sum`, `avg`, `min`, `max`) consumed by `Query.aggregate()`\n * and, in the future, `Scan.aggregate()`. Every factory accepts\n * an optional `{ seed }` parameter that is plumbed through the\n * protocol but unused by the executor — that's the load-bearing\n * half of constraint #2. When partition-aware reduction\n * lands, the seed carries the previous partition's running total into\n * the next partition without requiring a protocol change.\n *\n * Reducers are intentionally generic over their internal state type\n * `S` so compound reducers (avg keeps `{sum, count}`, min/max keep a\n * value bag) can model internal bookkeeping without leaking the\n * implementation through the accumulator's public shape. `finalize`\n * collapses `S` back into the user-visible `R`.\n *\n * Reducers are pure data — `init` / `step` / `finalize` / optional\n * `remove` are stateless functions that receive and return `S`. This\n * is the shape that admits O(1) incremental maintenance in a future\n * optimization (delta-aware `LiveReduction` applies `step` or\n * `remove` per delta), without blocking the simpler \"full re-run on\n * source change\" that ships.\n */\n\nimport { readPath } from '../../kernel/query/predicate.js'\nimport { distinctKeyOf, type BucketKeyCanonicalizer } from '../../kernel/query/distinct-key.js'\nimport type { MoneyString } from '../../via/money/branded.js'\nimport type { QueryField } from '../../kernel/types.js'\n\n/**\n * A single reducer: factory-produced, ready to plug into an\n * `.aggregate()` spec.\n *\n * Type parameters:\n * - `R` — user-visible result type (what the reduction returns\n * for this slot, e.g. `number` for `sum()`)\n * - `S` — internal state type, defaults to `R` for simple reducers\n * that don't need compound bookkeeping\n *\n * A reducer is stateless: every method is pure over `S`. `init()` is\n * called once per reduction run to build the initial state; `step()`\n * folds a record into the state; `remove()` (optional) un-folds a\n * record, enabling incremental live maintenance; `finalize()` reads\n * the final answer out of the state at the end of the run.\n */\nexport interface Reducer<R, S = R> {\n /** Build the initial state for a fresh reduction run. */\n init(): S\n /** Fold a record into the state. Returns the new state. */\n step(state: S, record: unknown): S\n /**\n * Un-fold a record from the state. Returns the new state.\n *\n * Optional — reducers without `remove` cannot be maintained\n * incrementally and must be re-run from scratch when the underlying\n * record set changes. `sum`, `count`, `avg` implement `remove` in\n * O(1); `min` and `max` implement it in O(N) worst case (when the\n * extremum itself is removed and the next extremum must be\n * recomputed from the remaining contributing values).\n */\n remove?(state: S, record: unknown): S\n /** Collapse the internal state into the user-visible result. */\n finalize(state: S): R\n /**\n * Combine two independent partial states into one (then `finalize` once).\n * Optional. MUST be associative + commutative with `init()` as identity.\n * Never merge finalized results — only states. Enables parallel /\n * hierarchical reduction (e.g. cross-shard or advisor→firm rollup).\n */\n merge?(a: S, b: S): S\n /**\n * Identifying operation tag stamped by each built-in factory.\n * Used by `summariseAggregateOp` in the introspection walker to\n * render human-readable aggregate descriptors in `dumpSchema()`.\n * Optional so third-party custom reducers are unaffected.\n */\n readonly op?:\n | 'count'\n | 'countDistinct'\n | 'sum'\n | 'avg'\n | 'min'\n | 'max'\n | 'median'\n | 'percentile'\n | 'variance'\n | 'stddev'\n | 'mode'\n /**\n * Field name for field-based reducers (`sum`, `avg`, `min`, `max`).\n * Absent on `count` which aggregates over record count, not a field.\n */\n readonly field?: string\n /**\n * Money-only: target currency for `sum` over a multi-currency money\n * field. Consumed by `wrapMoneyReducers` to convert per-currency\n * subtotals to one figure. Ignored for non-money fields.\n */\n readonly convertTo?: string\n /**\n * Money-only: FX rate map (`'USD->EUR' → rate`) used with `convertTo`.\n */\n readonly fx?: Record<string, number | string>\n /**\n * Quantile reducers only (#1353): the probability in `[0, 1]`. Carried as\n * metadata so `wrapMoneyReducers` can rebuild the reducer on the exact\n * BigInt path — a rewrite that must reproduce the SAME p, not guess one.\n * `median` stamps `0.5`.\n */\n readonly p?: number\n /**\n * `percentile` only (#1353): `true` when the reducer is the bounded-memory\n * t-digest rather than the exact O(n) one. Read by `wrapMoneyReducers`,\n * which refuses it over a money field — a t-digest is a float structure.\n */\n readonly approx?: boolean\n}\n\n/**\n * Common options accepted by every reducer factory.\n *\n * `seed` — optional initial value for the internal state. **Unused by\n * the executor**, plumbed through the protocol for constraint\n * #2 (partition-aware reduction seam). In, partitioned\n * reductions will pass the previous partition's carry as `seed` so\n * a long time series can be rolled forward one partition at a time\n * without re-reducing closed partitions.\n *\n * always uses `init()` with the factory's zero value, regardless\n * of whether `seed` was passed. Do not remove the parameter — that's\n * the whole point of having it exist now.\n */\nexport interface ReducerOptions<TSeed = unknown> {\n /** constraint #2 — seed is plumbed through but unused in. */\n readonly seed?: TSeed\n /**\n * Money-only (honored by `sum` over a multi-currency money field):\n * convert per-currency subtotals to this currency for a single figure.\n */\n readonly convertTo?: string\n /** Money-only: FX rate map (`'USD->EUR' → rate`) used with `convertTo`. */\n readonly fx?: Record<string, number | string>\n}\n\n// ---------------------------------------------------------------------------\n// Factories\n// ---------------------------------------------------------------------------\n\n/**\n * Count the number of records that match the query. Ignores field\n * values entirely — the count is over the number of records, not over\n * the number of non-null field values in any column.\n */\nexport function count(opts?: ReducerOptions<number>): Reducer<number> {\n // Seed captured on the closure but unused at execution time in\n //. The reference in _seed keeps lint happy.\n const _seed = opts?.seed\n void _seed\n return {\n op: 'count',\n init: () => 0,\n step: (state) => state + 1,\n remove: (state) => state - 1,\n finalize: (state) => state,\n merge: (a, b) => a + b,\n }\n}\n\n/**\n * Multiset state behind {@link countDistinct}: canonical distinct key →\n * how many records currently contribute it. The COUNT, not a bare Set, is\n * what makes `remove()` correct — dropping one of three records holding\n * `'c1'` must not drop `'c1'` from the distinct set.\n */\nexport interface CountDistinctState {\n readonly counts: ReadonlyMap<string, number>\n}\n\n/**\n * Number of DISTINCT non-nullish values of `field` across matching records\n * (#1347) — `COUNT(DISTINCT field)`.\n *\n * Distinctness is decided on the canonical index key, not on the stored\n * string and not on any formatted rendering, so a money field's `'0100'` and\n * `'100'` count once; see `kernel/query/distinct-key.ts` for why, and for why\n * nullish values are excluded rather than counted as a value of their own.\n *\n * The canonicalizer is bound LATE, by {@link bindDistinctReducers}, at the\n * same two points `wrapReducers` runs — a bare `countDistinct('amount')` in a\n * spec has no way to know which collection it will be reduced against, so a\n * constructor argument would be a footgun. Unbound, it falls back to the raw\n * stringified key, which is exactly what a non-Via field wants.\n *\n * Incremental complexity: O(1) `step` and `remove`, O(1) `finalize`.\n */\nexport function countDistinct(\n field: string,\n opts?: ReducerOptions<number> & { readonly canonicalize?: BucketKeyCanonicalizer },\n): Reducer<number, CountDistinctState> {\n const _seed = opts?.seed\n void _seed\n const via = opts?.canonicalize\n const keyOf = (record: unknown): string | undefined =>\n distinctKeyOf(field, readPath(record, field), via)\n return {\n op: 'countDistinct',\n field,\n init: () => ({ counts: new Map() }),\n step: (state, record) => {\n const key = keyOf(record)\n if (key === undefined) return state\n const counts = new Map(state.counts)\n counts.set(key, (counts.get(key) ?? 0) + 1)\n return { counts }\n },\n remove: (state, record) => {\n const key = keyOf(record)\n if (key === undefined) return state\n const current = state.counts.get(key)\n if (current === undefined) return state\n const counts = new Map(state.counts)\n if (current <= 1) counts.delete(key)\n else counts.set(key, current - 1)\n return { counts }\n },\n finalize: (state) => state.counts.size,\n merge: (a, b) => {\n const counts = new Map(a.counts)\n for (const [k, n] of b.counts) counts.set(k, (counts.get(k) ?? 0) + n)\n return { counts }\n },\n }\n}\n\n/**\n * Rebind every `countDistinct` reducer in a spec to a Via canonicalizer.\n *\n * Called wherever `ViaPipeline.wrapReducers` is called — the two are the same\n * seam, kept separate only because `wrapReducers` folds over BINDINGS (money\n * rewriting its own `sum`) while this one is brand-agnostic: any binding that\n * canonicalizes an index key canonicalizes a distinct key, by definition.\n *\n * Returns the spec unchanged when there is nothing to bind, so the common\n * path allocates nothing.\n */\nexport function bindDistinctReducers<Spec>(spec: Spec, via: BucketKeyCanonicalizer | undefined): Spec {\n if (!via) return spec\n const entries = Object.entries(spec as Record<string, Reducer<unknown, unknown>>)\n let changed = false\n const out: Record<string, unknown> = {}\n for (const [key, reducer] of entries) {\n if (reducer?.op === 'countDistinct' && typeof reducer.field === 'string') {\n out[key] = countDistinct(reducer.field, { canonicalize: via })\n changed = true\n } else {\n out[key] = reducer\n }\n }\n return changed ? (out as Spec) : spec\n}\n\n/**\n * Sum a numeric field across all matching records. Non-number values\n * at the field path are coerced to 0 — consumers who want a different\n * behavior (throw, skip, treat as NaN) should filter upstream via\n * `.where()` or write a custom reducer.\n *\n * KNOWN LIMITATION (type imprecision): the declared result type is `number`,\n * but when `field` is a **money** field the runtime returns a decimal *string*\n * (e.g. `'0.30'`, or `{ EUR: '0.30' }` in multi-currency mode) — money sums are\n * BigInt-exact in scaled space and never collapse to a float. The `number` type\n * is therefore a lie for money fields; narrow the result yourself at the call\n * site. A precise fix requires threading money-field declarations into the type\n * system (tracked separately).\n */\nexport function sum(\n field: string,\n opts?: ReducerOptions<number>,\n): Reducer<number> {\n const _seed = opts?.seed\n void _seed\n return {\n op: 'sum',\n field,\n // Money-only metadata, read by `wrapMoneyReducers`. No effect on a\n // generic numeric sum.\n ...(opts?.convertTo !== undefined ? { convertTo: opts.convertTo } : {}),\n ...(opts?.fx !== undefined ? { fx: opts.fx } : {}),\n init: () => 0,\n step: (state, record) => state + readNumber(record, field),\n remove: (state, record) => state - readNumber(record, field),\n finalize: (state) => state,\n merge: (a, b) => a + b,\n }\n}\n\n/**\n * Arithmetic mean of a numeric field across all matching records.\n *\n * Returns `null` for an empty result set (zero records is not a\n * well-defined denominator — returning NaN would poison downstream\n * arithmetic, and throwing would force every consumer to wrap in\n * try/catch just to handle \"no matches\"). Consumers who want an\n * explicit zero should coalesce with `?? 0`.\n *\n * Internal state is `{sum, count}` so the running average can be\n * maintained incrementally — on each delta, both fields update in\n * O(1) and `finalize` divides. Directly storing `avg` as state would\n * not admit incremental removal without also tracking count.\n */\nexport function avg(\n field: string,\n opts?: ReducerOptions<{ sum: number; count: number }>,\n): Reducer<number | null, { sum: number; count: number }> {\n const _seed = opts?.seed\n void _seed\n return {\n op: 'avg',\n field,\n init: () => ({ sum: 0, count: 0 }),\n step: (state, record) => ({\n sum: state.sum + readNumber(record, field),\n count: state.count + 1,\n }),\n remove: (state, record) => ({\n sum: state.sum - readNumber(record, field),\n count: state.count - 1,\n }),\n finalize: (state) => (state.count === 0 ? null : state.sum / state.count),\n merge: (a, b) => ({ sum: a.sum + b.sum, count: a.count + b.count }),\n }\n}\n\nexport interface MinMaxState {\n /**\n * Multiset of contributing field values. Stored as a plain array\n * because we need to support `remove` and a plain array gives us\n * O(1) push + O(N) worst-case removal — which matches the\n * documented min/max removal complexity. A sorted structure would\n * let us drop the O(N) rescan but adds complexity that doesn't\n * need; consumers hitting the O(N) ceiling should file an issue.\n */\n readonly values: number[]\n}\n\nfunction pushValue(state: MinMaxState, value: number): MinMaxState {\n return { values: [...state.values, value] }\n}\n\nfunction removeValue(state: MinMaxState, value: number): MinMaxState {\n // Remove the first matching value — duplicates are fine, we only\n // need to drop one instance per `remove()` call so the multiset\n // count stays consistent with the record count.\n const idx = state.values.indexOf(value)\n if (idx < 0) return state\n const next = state.values.slice()\n next.splice(idx, 1)\n return { values: next }\n}\n\n/**\n * Smallest numeric value of a field across all matching records.\n * Returns `null` for an empty result set. See `avg()` for the\n * reasoning on `null` vs NaN vs throwing.\n *\n * Incremental complexity: O(1) for `step`, O(N) worst case for\n * `remove` when the current minimum is removed (the state holds the\n * full multiset of contributing values and `finalize` scans for the\n * new minimum). Consumers with very large result sets and frequent\n * removals of the current extremum should either accept the cost or\n * wait for a future optimization.\n */\nexport function min(\n field: string,\n opts?: ReducerOptions<number>,\n): Reducer<number | null, MinMaxState> {\n const _seed = opts?.seed\n void _seed\n return {\n op: 'min',\n field,\n init: () => ({ values: [] }),\n step: (state, record) => pushValue(state, readNumber(record, field)),\n remove: (state, record) => removeValue(state, readNumber(record, field)),\n finalize: (state) => {\n if (state.values.length === 0) return null\n let out = state.values[0]!\n for (let i = 1; i < state.values.length; i++) {\n const v = state.values[i]!\n if (v < out) out = v\n }\n return out\n },\n merge: (a, b) => ({ values: [...a.values, ...b.values] }),\n }\n}\n\n/**\n * Largest numeric value of a field across all matching records.\n * Mirror of `min()` — see that doc for semantics, null-on-empty\n * behavior, and the O(N) removal caveat.\n */\nexport function max(\n field: string,\n opts?: ReducerOptions<number>,\n): Reducer<number | null, MinMaxState> {\n const _seed = opts?.seed\n void _seed\n return {\n op: 'max',\n field,\n init: () => ({ values: [] }),\n step: (state, record) => pushValue(state, readNumber(record, field)),\n remove: (state, record) => removeValue(state, readNumber(record, field)),\n finalize: (state) => {\n if (state.values.length === 0) return null\n let out = state.values[0]!\n for (let i = 1; i < state.values.length; i++) {\n const v = state.values[i]!\n if (v > out) out = v\n }\n return out\n },\n merge: (a, b) => ({ values: [...a.values, ...b.values] }),\n }\n}\n\n// ---------------------------------------------------------------------------\n// Statistical reducers (#1353)\n// ---------------------------------------------------------------------------\n\n/**\n * ⚠️ MEMORY, stated once for the whole section.\n *\n * `variance` / `stddev` are **streaming** — three numbers of state regardless\n * of how many records pass through, so they are free in a `.groupBy()` and\n * free as a running window aggregate (#1349).\n *\n * `median`, `percentile` (exact) and `mode` are **O(n) per group**: the first\n * two keep every contributing value, `mode` keeps one entry per distinct value.\n * Multiplied by the `GROUPBY_MAX_CARDINALITY` ceiling (100,000 groups) that is\n * the one place in the reduce vocabulary where a legal query can exhaust\n * memory, so it is not \"free like `sum`\". Two ways out, in order of preference:\n * narrow with `.where()` before grouping, or pass\n * `percentile(field, p, { approx: true })` for the bounded-memory t-digest —\n * O(compression) state per group instead of O(n), at a small, measured error.\n *\n * Unlike `count` / `sum` / `min` / `max`, whose states are copied on every\n * `step`, the reducers in this section MUTATE their state in place and return\n * it (the shape `via/money/money-reducer.ts` already uses). Copy-on-write here\n * would make a median over a group quadratic in the group size, which is a\n * worse bug than the inconsistency. States are built fresh by `init()` on every\n * reduction run and never shared, so the mutation is not observable — except\n * through `merge`, which therefore always returns a NEW state.\n */\n\n/**\n * Welford state behind {@link variance} and {@link stddev}.\n *\n * `m2` is the running sum of squared deviations **from the running mean**, not\n * a sum of squares — that is the entire point. The textbook one-pass identity\n * `(Σx² − (Σx)²/n)` subtracts two enormous nearly-equal numbers, and on an\n * accounting column (invoice totals clustered around a large figure) the\n * cancellation eats every significant digit: four totals just over 1e9 with a\n * true sample variance of 30 come back as **−170.67**, so `stddev` is `NaN`.\n * Welford never forms the large intermediate.\n */\nexport interface WelfordState {\n /** Number of contributing records. */\n readonly n: number\n /** Running arithmetic mean. */\n readonly mean: number\n /** Running sum of squared deviations from `mean`. */\n readonly m2: number\n}\n\n/** Options for {@link variance} / {@link stddev}. */\nexport interface DispersionOptions extends ReducerOptions<WelfordState> {\n /**\n * `true` → **population** dispersion (÷ n). Default `false` → **sample**\n * dispersion (÷ n−1), which is Postgres's `var_samp` / `stddev_samp`, the\n * unqualified spelling in every SQL dialect this library is measured\n * against.\n *\n * The divisor is not cosmetic and the wrong one is a silently wrong answer,\n * so the two disagree loudly at n = 1: sample is `null` (n−1 = 0 is not a\n * denominator), population is `0`.\n */\n readonly population?: boolean\n}\n\nfunction welfordReducer(\n op: 'variance' | 'stddev',\n field: string,\n population: boolean,\n): Reducer<number | null, WelfordState> {\n return {\n op,\n field,\n init: () => ({ n: 0, mean: 0, m2: 0 }),\n step: (state, record) => {\n const x = readNumber(record, field)\n const n = state.n + 1\n const delta = x - state.mean\n const mean = state.mean + delta / n\n // (x - mean) uses the UPDATED mean; delta the previous one. Using the\n // same mean twice is the naive formula wearing a Welford costume.\n return { n, mean, m2: state.m2 + delta * (x - mean) }\n },\n remove: (state, record) => {\n const x = readNumber(record, field)\n const n = state.n - 1\n if (n <= 0) return { n: 0, mean: 0, m2: 0 }\n const mean = (state.mean * state.n - x) / n\n return { n, mean, m2: state.m2 - (x - state.mean) * (x - mean) }\n },\n // Chan et al.'s parallel combination — the reason a reduction can be\n // sharded and rolled up without re-reading the leaves.\n merge: (a, b) => {\n if (a.n === 0) return b\n if (b.n === 0) return a\n const n = a.n + b.n\n const delta = b.mean - a.mean\n return {\n n,\n mean: a.mean + (delta * b.n) / n,\n m2: a.m2 + b.m2 + (delta * delta * a.n * b.n) / n,\n }\n },\n finalize: (state) => {\n const divisor = population ? state.n : state.n - 1\n if (divisor <= 0) return null\n const v = state.m2 / divisor\n return op === 'stddev' ? Math.sqrt(v) : v\n },\n }\n}\n\n/**\n * Variance of a numeric field — **sample (n−1) by default**, `{ population:\n * true }` for the n divisor. See {@link DispersionOptions}.\n *\n * Streaming (Welford): O(1) state, O(1) `step`, O(1) `remove`, associative\n * `merge`. Safe as a running window aggregate.\n *\n * `null` for an empty result set, and `null` for a single record in sample\n * mode (population mode returns `0`) — see `avg()` for why null rather than\n * `NaN` or a throw.\n *\n * ⛔ Not available over a declared money field: dispersion is inherently a\n * float computation, so `wrapMoneyReducers` refuses rather than let\n * `readNumber` read a scaled-integer string as `0`.\n */\nexport function variance(field: string, opts?: DispersionOptions): Reducer<number | null, WelfordState> {\n const _seed = opts?.seed\n void _seed\n return welfordReducer('variance', field, opts?.population === true)\n}\n\n/**\n * Standard deviation of a numeric field — the square root of {@link variance},\n * with the same divisor rule, the same empty/single-element answers, the same\n * streaming Welford state, and the same money refusal.\n */\nexport function stddev(field: string, opts?: DispersionOptions): Reducer<number | null, WelfordState> {\n const _seed = opts?.seed\n void _seed\n return welfordReducer('stddev', field, opts?.population === true)\n}\n\n/**\n * Exact quantile state: every contributing value, unsorted (sorting happens\n * once, in `finalize`, on a copy — so a running window aggregate does not\n * disturb the multiset it is still being appended to).\n */\nexport interface ExactQuantileState {\n readonly kind: 'exact'\n readonly values: number[]\n}\n\n/** One t-digest centroid: a weighted summary of `count` nearby values. */\nexport interface Centroid {\n readonly mean: number\n readonly count: number\n}\n\n/**\n * t-digest state: compressed centroids plus a small unmerged buffer.\n *\n * Implemented here rather than taken from npm — `hub/src/**` adds no\n * dependency, and this one is ~60 lines.\n */\nexport interface TDigestState {\n readonly kind: 'tdigest'\n centroids: Centroid[]\n buffer: number[]\n n: number\n}\n\n/** State of {@link median} / {@link percentile}; the arm depends on `approx`. */\nexport type QuantileState = ExactQuantileState | TDigestState\n\n/** Options for {@link percentile}. */\nexport interface PercentileOptions extends ReducerOptions<number> {\n /**\n * `true` → bounded-memory t-digest instead of keeping every value. O(1)-ish\n * state per group, at a small error (under 1% of the value range at every\n * quantile on a 10k uniform scan, exact at p = 0 and p = 1).\n *\n * The trade is real: an approximate reducer cannot `remove()`, so it does\n * not participate in incremental live maintenance, and it is refused over a\n * money field.\n */\n readonly approx?: boolean\n}\n\nfunction assertProbability(op: string, p: number): void {\n if (!Number.isFinite(p) || p < 0 || p > 1) {\n throw new Error(`${op}(): p must be a number between 0 and 1, got ${p}.`)\n }\n}\n\nfunction asExact(state: QuantileState): ExactQuantileState {\n if (state.kind !== 'exact') throw new Error('percentile: expected the exact quantile state')\n return state\n}\n\nfunction asDigest(state: QuantileState): TDigestState {\n if (state.kind !== 'tdigest') throw new Error('percentile: expected the t-digest state')\n return state\n}\n\n/**\n * `percentile_cont` over an in-memory multiset — the INTERPOLATING definition.\n *\n * `x = p * (n − 1)`; when `x` lands between two ranks the answer is the linear\n * blend of the two neighbours. So the median of `[1,2,3,4]` is `2.5`, a value\n * that is not in the input. `percentile_disc` would answer `2`. Postgres names\n * both; this library ships only `_cont`, because it is the one `median` has to\n * agree with — a `median` that returned `2` while `percentile(f, 0.5)`\n * returned `2.5` would be the worse surprise.\n */\nfunction quantileOf(values: readonly number[], p: number): number | null {\n const n = values.length\n if (n === 0) return null\n if (n === 1) return values[0]!\n const sorted = [...values].sort((a, b) => a - b)\n const x = p * (n - 1)\n const lo = Math.floor(x)\n const frac = x - lo\n if (frac === 0) return sorted[lo]!\n return sorted[lo]! + (sorted[lo + 1]! - sorted[lo]!) * frac\n}\n\n/** Centroid budget. Larger ⇒ more accurate and more memory; 100 is the usual default. */\nconst TDIGEST_COMPRESSION = 100\n/** Unmerged values tolerated before a compression pass. */\nconst TDIGEST_BUFFER = 256\n\n/**\n * Fold the buffer into the centroid list and compress.\n *\n * The size rule is the standard one: a centroid sitting at estimated quantile\n * `q` may hold at most `4·n·q·(1−q)/compression` values, which is ~0 at the\n * tails and widest in the middle. That is what keeps p = 0 and p = 1 EXACT\n * (the extreme centroids stay singletons) while the middle compresses hard.\n */\nfunction tdigestFlush(state: TDigestState, force = false): void {\n if (state.buffer.length === 0 && !force) return\n const all: Centroid[] = state.centroids.concat(state.buffer.map((mean) => ({ mean, count: 1 })))\n state.buffer = []\n if (all.length === 0) return\n all.sort((a, b) => a.mean - b.mean)\n const total = state.n\n const out: Centroid[] = []\n let curMean = all[0]!.mean\n let curCount = all[0]!.count\n let before = 0\n for (let i = 1; i < all.length; i++) {\n const c = all[i]!\n const q = (before + curCount + c.count / 2) / total\n const limit = (4 * total * q * (1 - q)) / TDIGEST_COMPRESSION\n if (curCount + c.count <= Math.max(limit, 1)) {\n const count = curCount + c.count\n curMean = curMean + ((c.mean - curMean) * c.count) / count\n curCount = count\n } else {\n out.push({ mean: curMean, count: curCount })\n before += curCount\n curMean = c.mean\n curCount = c.count\n }\n }\n out.push({ mean: curMean, count: curCount })\n state.centroids = out\n}\n\n/**\n * Estimate the `p` quantile off the centroids, interpolating between centroid\n * CENTRES so the answer degrades to `quantileOf` exactly when no compression\n * has happened (every centroid a singleton ⇒ its centre is its rank).\n */\nfunction tdigestQuantile(state: TDigestState, p: number): number | null {\n tdigestFlush(state)\n const cs = state.centroids\n if (cs.length === 0) return null\n if (cs.length === 1) return cs[0]!.mean\n const centres: number[] = []\n let acc = 0\n for (const c of cs) {\n centres.push(acc + (c.count - 1) / 2)\n acc += c.count\n }\n const target = p * (state.n - 1)\n const last = cs.length - 1\n if (target <= centres[0]!) return cs[0]!.mean\n if (target >= centres[last]!) return cs[last]!.mean\n for (let i = 0; i < last; i++) {\n const a = centres[i]!\n const b = centres[i + 1]!\n if (target <= b) {\n const t = b === a ? 0 : (target - a) / (b - a)\n return cs[i]!.mean + (cs[i + 1]!.mean - cs[i]!.mean) * t\n }\n }\n return cs[last]!.mean\n}\n\nfunction exactQuantileReducer(\n op: 'median' | 'percentile',\n field: string,\n p: number,\n): Reducer<number | null, QuantileState> {\n return {\n op,\n field,\n p,\n init: (): QuantileState => ({ kind: 'exact', values: [] }),\n step: (state, record) => {\n asExact(state).values.push(readNumber(record, field))\n return state\n },\n remove: (state, record) => {\n const values = asExact(state).values\n const idx = values.indexOf(readNumber(record, field))\n if (idx >= 0) values.splice(idx, 1)\n return state\n },\n merge: (a, b) => ({ kind: 'exact', values: [...asExact(a).values, ...asExact(b).values] }),\n finalize: (state) => quantileOf(asExact(state).values, p),\n }\n}\n\nfunction approxQuantileReducer(field: string, p: number): Reducer<number | null, QuantileState> {\n return {\n op: 'percentile',\n field,\n p,\n approx: true,\n init: (): QuantileState => ({ kind: 'tdigest', centroids: [], buffer: [], n: 0 }),\n step: (state, record) => {\n const d = asDigest(state)\n d.buffer.push(readNumber(record, field))\n d.n += 1\n if (d.buffer.length >= TDIGEST_BUFFER) tdigestFlush(d)\n return state\n },\n // No `remove`: a centroid has forgotten which values it absorbed, so an\n // un-fold is not expressible. Deliberate, and asserted by a test.\n merge: (a, b) => {\n const A = asDigest(a)\n const B = asDigest(b)\n const s: TDigestState = {\n kind: 'tdigest',\n centroids: [...A.centroids, ...B.centroids],\n buffer: [...A.buffer, ...B.buffer],\n n: A.n + B.n,\n }\n tdigestFlush(s, true)\n return s\n },\n finalize: (state) => tdigestQuantile(asDigest(state), p),\n }\n}\n\n/**\n * Median of a numeric field — exactly `percentile(field, 0.5)`, and therefore\n * **`percentile_cont`**: an even-sized input INTERPOLATES (`[1,2,3,4]` → `2.5`)\n * rather than picking a member. See {@link quantileOf} for why only the\n * interpolating definition ships.\n *\n * `null` on an empty result set. O(n) memory per group — read the memory note\n * at the top of this section before using it under `.groupBy()`.\n *\n * Over a declared money field the reducer is rewritten onto the exact BigInt\n * path; {@link moneyMedian} is the same call with the honest return type.\n */\nexport function median(field: string, opts?: ReducerOptions<number>): Reducer<number | null, QuantileState> {\n const _seed = opts?.seed\n void _seed\n return exactQuantileReducer('median', field, 0.5)\n}\n\n/**\n * The `p` quantile of a numeric field, `p ∈ [0, 1]`, by the **`percentile_cont`\n * (interpolating)** definition — `percentile(f, 0.9)` over `1..10` is `9.1`,\n * not `9`. `p = 0` is the minimum and `p = 1` the maximum, exactly.\n *\n * Throws for a `p` outside `[0, 1]` or a non-finite one, at construction time.\n *\n * Exact by default and O(n) per group; pass `{ approx: true }` for the\n * bounded-memory t-digest (see {@link PercentileOptions}).\n */\nexport function percentile(\n field: string,\n p: number,\n opts?: PercentileOptions,\n): Reducer<number | null, QuantileState> {\n assertProbability('percentile', p)\n const _seed = opts?.seed\n void _seed\n return opts?.approx === true ? approxQuantileReducer(field, p) : exactQuantileReducer('percentile', field, p)\n}\n\n/** Frequency table behind {@link mode}: value → how many records hold it. */\nexport interface ModeState {\n readonly counts: Map<number, number>\n}\n\n/**\n * Most frequent value of a numeric field.\n *\n * **Tie rule: the LOWEST value wins.** Two values with equal frequency is the\n * common case on real data, not an edge case, and the alternatives are worse:\n * \"first seen\" makes the answer depend on store iteration order (so the same\n * query answers differently after a compaction, and `merge` stops being\n * commutative), and \"all of them\" changes the result TYPE based on the data.\n * Lowest-wins is total, order-independent, and mergeable.\n *\n * `null` on an empty result set. O(distinct values) memory per group.\n *\n * ⛔ Numeric only, and not available over a declared money field.\n */\nexport function mode(field: string, opts?: ReducerOptions<number>): Reducer<number | null, ModeState> {\n const _seed = opts?.seed\n void _seed\n return {\n op: 'mode',\n field,\n init: () => ({ counts: new Map<number, number>() }),\n step: (state, record) => {\n const v = readNumber(record, field)\n state.counts.set(v, (state.counts.get(v) ?? 0) + 1)\n return state\n },\n remove: (state, record) => {\n const v = readNumber(record, field)\n const current = state.counts.get(v)\n if (current === undefined) return state\n if (current <= 1) state.counts.delete(v)\n else state.counts.set(v, current - 1)\n return state\n },\n merge: (a, b) => {\n const counts = new Map(a.counts)\n for (const [v, c] of b.counts) counts.set(v, (counts.get(v) ?? 0) + c)\n return { counts }\n },\n finalize: (state) => {\n let best: number | null = null\n let bestCount = 0\n for (const [v, c] of state.counts) {\n if (c > bestCount || (c === bestCount && best !== null && v < best)) {\n best = v\n bestCount = c\n }\n }\n return best\n },\n }\n}\n\n// ---------------------------------------------------------------------------\n// Money-typed reducer constructors\n// ---------------------------------------------------------------------------\n\n/**\n * `sum()` for a **declared money field**, typed to match the runtime.\n *\n * `sum()` returns `Reducer<number>`, but `wrapMoneyReducers` (applied at\n * `query.aggregate()` time, once `moneyFields` is known) rewrites any\n * `sum`/`min`/`max` over a money field to a money reducer that finalizes to a\n * `MoneyString` decimal — so the `number` type is a lie for money fields and\n * consumers need a cast at every read site. `moneySum` is the same reducer with\n * the correct `Reducer<MoneyString>` return type, so no read-site cast is\n * needed. It is the caller's assertion that `field` is a money field; use plain\n * `sum()` for non-money fields. (For a multi-currency money field WITHOUT\n * `convertTo`, the runtime returns a per-currency `Record<string, MoneyString>`\n * rather than a single `MoneyString` — pass `convertTo` to collapse to one\n * currency, or read the map at the boundary.)\n */\nexport function moneySum(field: string, opts?: ReducerOptions<number>): Reducer<MoneyString> {\n // The constructed reducer is the plain numeric `sum`; `wrapMoneyReducers`\n // swaps in the MoneyString-producing money reducer at aggregate() time.\n return sum(field, opts) as unknown as Reducer<MoneyString>\n}\n\n/**\n * `min()` for a declared money field, typed `Reducer<MoneyString | null>`\n * (null on an empty result set in fixed-currency mode, mirroring `min()`). See\n * {@link moneySum} for the late-binding rewrite. Note: `convertTo`/`fx` on\n * `opts` have no effect on min/max (cross-currency min/max is unsupported — use\n * {@link moneySum} for currency conversion). In multi-currency mode the runtime\n * returns a per-currency map and an empty result is `{}` rather than `null`.\n */\nexport function moneyMin(field: string, opts?: ReducerOptions<number>): Reducer<MoneyString | null> {\n return min(field, opts) as unknown as Reducer<MoneyString | null>\n}\n\n/**\n * `max()` for a declared money field, typed `Reducer<MoneyString | null>`\n * (null on an empty result set in fixed-currency mode, mirroring `max()`). See\n * {@link moneyMin} for the `convertTo`/`fx` and multi-currency caveats.\n */\nexport function moneyMax(field: string, opts?: ReducerOptions<number>): Reducer<MoneyString | null> {\n return max(field, opts) as unknown as Reducer<MoneyString | null>\n}\n\n/**\n * `median()` for a **declared money field**, typed `Reducer<MoneyString | null>`.\n *\n * Same late-binding rewrite as {@link moneySum}: `wrapMoneyReducers` swaps in a\n * reducer that keeps the stored scaled integers as `bigint`s and interpolates\n * the two middle values IN SCALED SPACE with half-even rounding — the money\n * module's rounding everywhere else. Nothing round-trips through a float, so\n * the answer is exact past `Number.MAX_SAFE_INTEGER`, where two distinct cent\n * amounts stop being distinct numbers at all.\n *\n * An even-sized input can therefore land on a half unit (`0.10` and `0.15` →\n * `12.5` cents): that is the one place money median rounds, and it rounds\n * half-to-even (`0.12`), never away from zero.\n *\n * In multi-currency mode the runtime returns a per-currency map, as `moneyMin`\n * does; an empty result is `null` in fixed mode and `{}` in multi.\n */\nexport function moneyMedian(field: string, opts?: ReducerOptions<number>): Reducer<MoneyString | null> {\n return median(field, opts) as unknown as Reducer<MoneyString | null>\n}\n\n/**\n * `percentile()` for a declared money field — see {@link moneyMedian} for the\n * exactness and rounding contract, which is the same code path (`median` is\n * `p = 0.5`). The interpolation weight is taken from `p`'s DECIMAL spelling as\n * an exact rational, so `p = 0.9` is `9/10`, not the float nearest to it.\n *\n * There is deliberately no `approx` here: the t-digest is a float structure and\n * `wrapMoneyReducers` refuses it over a money field.\n */\nexport function moneyPercentile(\n field: string,\n p: number,\n opts?: ReducerOptions<number>,\n): Reducer<MoneyString | null> {\n return percentile(field, p, opts) as unknown as Reducer<MoneyString | null>\n}\n\n// ---------------------------------------------------------------------------\n// Builder (typed spec-builder for aggregate())\n// ---------------------------------------------------------------------------\n\n/**\n * Typed builder passed to the `aggregate(b => spec)` overload.\n *\n * Each field-taking method narrows `field` to `QueryField<T, S>`, which\n * excludes any field listed in the collection's `sensitive` option at\n * compile time. `count()` carries no field argument and is always allowed.\n *\n * The type parameters match the `Query<T, S>` they come from:\n * - `T` — the record type of the collection\n * - `S` — the union of sensitive field keys (defaults to `never`)\n *\n * ONE shared runtime instance (`reducerBuilder`) serves all `T`/`S`\n * combinations — the field narrowing is type-only; the methods delegate\n * directly to the standalone factories.\n */\nexport interface ReducerBuilder<T, S extends keyof T = never, M extends keyof T & string = never> {\n count(opts?: ReducerOptions<number>): Reducer<number>\n countDistinct(field: QueryField<T, S>, opts?: ReducerOptions<number>): Reducer<number, CountDistinctState>\n sum<F extends QueryField<T, S>>(field: F, opts?: ReducerOptions<number>): [F] extends [M] ? Reducer<MoneyString> : Reducer<number>\n avg(field: QueryField<T, S>, opts?: ReducerOptions<{ sum: number; count: number }>): ReturnType<typeof avg>\n min<F extends QueryField<T, S>>(field: F, opts?: ReducerOptions<number>): [F] extends [M] ? Reducer<MoneyString | null> : ReturnType<typeof min>\n max<F extends QueryField<T, S>>(field: F, opts?: ReducerOptions<number>): [F] extends [M] ? Reducer<MoneyString | null> : ReturnType<typeof max>\n median<F extends QueryField<T, S>>(field: F, opts?: ReducerOptions<number>): [F] extends [M] ? Reducer<MoneyString | null> : ReturnType<typeof median>\n percentile<F extends QueryField<T, S>>(field: F, p: number, opts?: PercentileOptions): [F] extends [M] ? Reducer<MoneyString | null> : ReturnType<typeof percentile>\n variance(field: QueryField<T, S>, opts?: DispersionOptions): ReturnType<typeof variance>\n stddev(field: QueryField<T, S>, opts?: DispersionOptions): ReturnType<typeof stddev>\n mode(field: QueryField<T, S>, opts?: ReducerOptions<number>): ReturnType<typeof mode>\n moneySum(field: QueryField<T, S>, opts?: ReducerOptions<number>): Reducer<MoneyString>\n moneyMin(field: QueryField<T, S>, opts?: ReducerOptions<number>): Reducer<MoneyString | null>\n moneyMax(field: QueryField<T, S>, opts?: ReducerOptions<number>): Reducer<MoneyString | null>\n moneyMedian(field: QueryField<T, S>, opts?: ReducerOptions<number>): Reducer<MoneyString | null>\n moneyPercentile(field: QueryField<T, S>, p: number, opts?: ReducerOptions<number>): Reducer<MoneyString | null>\n}\n\n/**\n * Shared runtime instance for the `aggregate(b => spec)` builder form.\n *\n * The field-narrowing to `QueryField<T, S>` is type-only — each method\n * delegates directly to its standalone factory. A `(field: string) => R`\n * factory is assignable to a `(field: QueryField<T,S>) => R` method by\n * parameter-contravariance, so this single instance works for all `T`/`S`.\n */\nexport const reducerBuilder: ReducerBuilder<Record<string, unknown>> = {\n count,\n countDistinct,\n // The generic F parameter on sum/min/max in the interface is type-only; the\n // standalone factories are plain `(field: string)` functions. With M=never the\n // conditional return collapses to the numeric branch, matching the factories'\n // return type, but TypeScript cannot verify that collapse for a generic method\n // signature — so each factory is cast directly to the method's type.\n sum: sum as ReducerBuilder<Record<string, unknown>>['sum'],\n avg,\n min: min as ReducerBuilder<Record<string, unknown>>['min'],\n max: max as ReducerBuilder<Record<string, unknown>>['max'],\n median: median as ReducerBuilder<Record<string, unknown>>['median'],\n percentile: percentile as ReducerBuilder<Record<string, unknown>>['percentile'],\n variance,\n stddev,\n mode,\n moneySum, moneyMin, moneyMax, moneyMedian, moneyPercentile,\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Read a numeric field from a record. Non-number values (null,\n * undefined, strings, objects) coerce to 0 so sum/avg/min/max don't\n * produce NaN on one bad row. Consumers who want strict typing should\n * validate upstream with Standard Schema, which NOYDB already runs on\n * every `put()`.\n */\nfunction readNumber(record: unknown, field: string): number {\n const value = readPath(record, field)\n // Defensive: a `{ amount, currency }` value means a multi-currency\n // money field reached a generic numeric reducer instead of being\n // rewritten by `wrapMoneyReducers` — that would silently produce a\n // wrong total. Surface it loudly rather than coercing to 0.\n if (\n typeof value === 'object' &&\n value !== null &&\n 'amount' in value &&\n 'currency' in value\n ) {\n throw new Error(\n `aggregate: field \"${field}\" holds a money value but was not money-aware — ` +\n `declare it in the collection's moneyFields so sum/min/max stay exact`,\n )\n }\n return typeof value === 'number' && Number.isFinite(value) ? value : 0\n}\n"],"mappings":"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","names":["count"]}
@@ -0,0 +1,13 @@
1
+ // src/kernel/query/internal/core.ts
2
+ function installMethods(target, mixin) {
3
+ for (const name of Object.getOwnPropertyNames(mixin.prototype)) {
4
+ if (name === "constructor") continue;
5
+ const desc = Object.getOwnPropertyDescriptor(mixin.prototype, name);
6
+ if (desc) Object.defineProperty(target, name, desc);
7
+ }
8
+ }
9
+
10
+ export {
11
+ installMethods
12
+ };
13
+ //# sourceMappingURL=chunk-F6NCB7KT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/kernel/query/internal/core.ts"],"sourcesContent":["/**\n * #1458 — how an extension group's methods reach `Query.prototype`.\n *\n * Each group defines its half of the builder as a MIXIN CLASS whose method\n * bodies moved out of `builder.ts` unchanged — `this.plan`, `this.source`,\n * `this.joinContext` and the rest still resolve, because TypeScript's\n * `private` is a compile-time construct and a method installed on the\n * prototype reads them like any other property. The mixin declares those\n * fields with `declare`, which emits nothing.\n *\n * ⭐ **Why a mixin CLASS rather than a file of `Query.prototype.x = function`\n * assignments.** The bodies are the point: several are 100+ lines carrying\n * prose that explains a decision, and a mechanical rewrite into assignment\n * form would have touched every one of them. As class methods they moved\n * byte-for-byte, so the diff shows a relocation rather than a rewrite — and an\n * overload set (`join`, `joinOn`, `aggregate`, `groupBy` all have them)\n * survives, which an assignment form cannot express.\n */\n\n/**\n * Copy a mixin's prototype methods onto a target prototype, replacing the Find\n * stubs.\n *\n * `getOwnPropertyNames` rather than `Object.assign`: class methods are\n * non-enumerable prototype properties, so `assign` copies nothing at all —\n * silently, leaving every stub in place. Descriptors are copied whole so a\n * getter stays a getter.\n */\nexport function installMethods(target: object, mixin: { prototype: object }): void {\n for (const name of Object.getOwnPropertyNames(mixin.prototype)) {\n if (name === 'constructor') continue\n const desc = Object.getOwnPropertyDescriptor(mixin.prototype, name)\n if (desc) Object.defineProperty(target, name, desc)\n }\n}\n"],"mappings":";AA4BO,SAAS,eAAe,QAAgB,OAAoC;AACjF,aAAW,QAAQ,OAAO,oBAAoB,MAAM,SAAS,GAAG;AAC9D,QAAI,SAAS,cAAe;AAC5B,UAAM,OAAO,OAAO,yBAAyB,MAAM,WAAW,IAAI;AAClE,QAAI,KAAM,QAAO,eAAe,QAAQ,MAAM,IAAI;AAAA,EACpD;AACF;","names":[]}