@noy-db/hub 0.2.0-pre.10 → 0.2.0-pre.12

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 (266) hide show
  1. package/README.md +126 -0
  2. package/dist/aggregate/index.cjs +289 -12
  3. package/dist/aggregate/index.cjs.map +1 -1
  4. package/dist/aggregate/index.d.cts +2 -2
  5. package/dist/aggregate/index.d.ts +2 -2
  6. package/dist/aggregate/index.js +7 -7
  7. package/dist/aggregate/index.js.map +1 -1
  8. package/dist/attestation/index.cjs.map +1 -1
  9. package/dist/attestation/index.d.cts +3 -3
  10. package/dist/attestation/index.d.ts +3 -3
  11. package/dist/attestation/index.js +6 -6
  12. package/dist/blobs/index.cjs +28 -0
  13. package/dist/blobs/index.cjs.map +1 -1
  14. package/dist/blobs/index.d.cts +4 -4
  15. package/dist/blobs/index.d.ts +4 -4
  16. package/dist/blobs/index.js +5 -5
  17. package/dist/bundle/index.cjs +1468 -19
  18. package/dist/bundle/index.cjs.map +1 -1
  19. package/dist/bundle/index.d.cts +5 -5
  20. package/dist/bundle/index.d.ts +5 -5
  21. package/dist/bundle/index.js +9 -9
  22. package/dist/{chunk-7CEGU63S.js → chunk-4BHFNKTP.js} +2 -2
  23. package/dist/{chunk-5OEJ6GOT.js → chunk-5ARRXIVR.js} +2 -2
  24. package/dist/{chunk-DRXIZOFV.js → chunk-6AD5TBF2.js} +31 -3
  25. package/dist/chunk-6AD5TBF2.js.map +1 -0
  26. package/dist/{chunk-YM7LFCG7.js → chunk-6BYBVRZU.js} +3 -3
  27. package/dist/{chunk-5IXJGFF2.js → chunk-7JJE3OMJ.js} +5 -5
  28. package/dist/{chunk-HHOO7HGH.js → chunk-7LVRIW4G.js} +4 -4
  29. package/dist/{chunk-O6EJ6WTI.js → chunk-AGRC7NQQ.js} +62 -2
  30. package/dist/chunk-AGRC7NQQ.js.map +1 -0
  31. package/dist/{chunk-IMYKDWB4.js → chunk-B7GGYNKQ.js} +2 -2
  32. package/dist/{chunk-BDV7INMP.js → chunk-BXOUVUES.js} +4 -4
  33. package/dist/{chunk-FO3UEG4S.js → chunk-C2CIIQRG.js} +2 -2
  34. package/dist/{chunk-ZROPXHJY.js → chunk-CHBXWJZQ.js} +2 -2
  35. package/dist/{chunk-RYIL3PI2.js → chunk-CILT6V3V.js} +2 -2
  36. package/dist/{chunk-PXTQPZO4.js → chunk-DLTU4M2I.js} +6 -6
  37. package/dist/{chunk-GAUEWM7D.js → chunk-EKNUBIIQ.js} +4 -4
  38. package/dist/{chunk-HQSQC2XL.js → chunk-GFPR7VJS.js} +17 -4
  39. package/dist/chunk-GFPR7VJS.js.map +1 -0
  40. package/dist/{chunk-6EOXTJS2.js → chunk-HBAJDI2N.js} +5 -5
  41. package/dist/{chunk-PVUUIWHY.js → chunk-HLGDYFWR.js} +10 -3
  42. package/dist/chunk-HLGDYFWR.js.map +1 -0
  43. package/dist/{chunk-RRNA5GKT.js → chunk-IEPT7HVP.js} +2 -2
  44. package/dist/{chunk-R233SLY3.js → chunk-IUBHXEPJ.js} +2 -2
  45. package/dist/{chunk-CH22FZHT.js → chunk-L6BYRCYB.js} +2 -2
  46. package/dist/{chunk-5OX6XVNS.js → chunk-LOA2VCMS.js} +5 -5
  47. package/dist/{chunk-BB27JMWB.js → chunk-LSEW3ZZ2.js} +3 -3
  48. package/dist/{chunk-Y26YV5R3.js → chunk-LWSD4QPT.js} +3 -3
  49. package/dist/{chunk-WIRRPTFH.js → chunk-LYNNZEQD.js} +1 -1
  50. package/dist/chunk-LYNNZEQD.js.map +1 -0
  51. package/dist/{chunk-26NK23DZ.js → chunk-M45IRXDM.js} +3 -3
  52. package/dist/{chunk-CXJG63MA.js → chunk-NP6EZT44.js} +20 -6
  53. package/dist/chunk-NP6EZT44.js.map +1 -0
  54. package/dist/{chunk-GNHAC43Q.js → chunk-O53RIZCC.js} +5 -5
  55. package/dist/chunk-OPDTLHFA.js +783 -0
  56. package/dist/chunk-OPDTLHFA.js.map +1 -0
  57. package/dist/{chunk-LSTBFLL2.js → chunk-P3Z5Y2TS.js} +2 -2
  58. package/dist/{chunk-QSOYKKMD.js → chunk-P4EDT5ZP.js} +2 -2
  59. package/dist/{chunk-PC6ZEDRL.js → chunk-RHQYVHFH.js} +2 -2
  60. package/dist/{chunk-3LPV6BXR.js → chunk-RRDWXNBQ.js} +3 -3
  61. package/dist/{chunk-4CLICFEY.js → chunk-SJJQKNMP.js} +4 -4
  62. package/dist/{chunk-TY32C732.js → chunk-SZ4N3IL5.js} +5 -5
  63. package/dist/{chunk-4USCAEDT.js → chunk-TMHJEYW7.js} +502 -60
  64. package/dist/chunk-TMHJEYW7.js.map +1 -0
  65. package/dist/{chunk-2N62W5YP.js → chunk-UA6G45ME.js} +3 -3
  66. package/dist/{chunk-6YLPHBKR.js → chunk-UOC7JMZO.js} +13 -4
  67. package/dist/chunk-UOC7JMZO.js.map +1 -0
  68. package/dist/{chunk-DAP2XL7Q.js → chunk-VOXMU6LB.js} +2 -2
  69. package/dist/chunk-WNRGOVLG.js +64 -0
  70. package/dist/chunk-WNRGOVLG.js.map +1 -0
  71. package/dist/{chunk-DJRWA3Q5.js → chunk-WUG3E423.js} +4 -4
  72. package/dist/{chunk-PM3QYWUU.js → chunk-XHM2SARW.js} +3 -3
  73. package/dist/{chunk-RC6SU5NO.js → chunk-XSIFXX54.js} +2 -2
  74. package/dist/{chunk-CXFOITNS.js → chunk-ZC7MNVYN.js} +2 -2
  75. package/dist/{chunk-6T2UDBKG.js → chunk-ZCFS7U4J.js} +2 -2
  76. package/dist/consent/index.cjs.map +1 -1
  77. package/dist/consent/index.d.cts +4 -4
  78. package/dist/consent/index.d.ts +4 -4
  79. package/dist/consent/index.js +3 -3
  80. package/dist/{crypto-2CRLG4F4.js → crypto-AJB72OKN.js} +3 -3
  81. package/dist/{delegation-ZTRT2PRV.js → delegation-6FCWDRUS.js} +5 -5
  82. package/dist/derivations/index.cjs.map +1 -1
  83. package/dist/derivations/index.d.cts +5 -5
  84. package/dist/derivations/index.d.ts +5 -5
  85. package/dist/derivations/index.js +4 -4
  86. package/dist/{dev-unlock-BOEYl1xl.d.ts → dev-unlock-D3mpVFRc.d.ts} +1 -1
  87. package/dist/{dev-unlock-AglVnkPY.d.cts → dev-unlock-ckqa_Nso.d.cts} +1 -1
  88. package/dist/executor-7KSCEIFA.js +8 -0
  89. package/dist/executor-D2QMNGRJ.js +8 -0
  90. package/dist/executor-O5AZK7UW.js +11 -0
  91. package/dist/{fanout-sidecar-OKPMMPLG.js → fanout-sidecar-ZSKEQ6NI.js} +2 -2
  92. package/dist/guards/index.cjs +53 -1
  93. package/dist/guards/index.cjs.map +1 -1
  94. package/dist/guards/index.d.cts +12 -6
  95. package/dist/guards/index.d.ts +12 -6
  96. package/dist/guards/index.js +5 -3
  97. package/dist/{hash-B9m3_fhj.d.ts → hash-CTZVkXLx.d.ts} +1 -1
  98. package/dist/{hash-RVqz2zi8.d.cts → hash-rDSSd_oW.d.cts} +1 -1
  99. package/dist/history/index.cjs.map +1 -1
  100. package/dist/history/index.d.cts +5 -5
  101. package/dist/history/index.d.ts +5 -5
  102. package/dist/history/index.js +5 -5
  103. package/dist/i18n/index.cjs.map +1 -1
  104. package/dist/i18n/index.d.cts +4 -4
  105. package/dist/i18n/index.d.ts +4 -4
  106. package/dist/i18n/index.js +6 -6
  107. package/dist/immutable-guard-C51vAHuh.d.cts +67 -0
  108. package/dist/immutable-guard-DyD0qg2k.d.ts +67 -0
  109. package/dist/index-CkFHr4OP.d.ts +1190 -0
  110. package/dist/index-Cmop06zJ.d.cts +1190 -0
  111. package/dist/index.cjs +1636 -61
  112. package/dist/index.cjs.map +1 -1
  113. package/dist/index.d.cts +46 -13
  114. package/dist/index.d.ts +46 -13
  115. package/dist/index.js +76 -44
  116. package/dist/index.js.map +1 -1
  117. package/dist/indexing/index.cjs.map +1 -1
  118. package/dist/indexing/index.js +2 -2
  119. package/dist/issue-YIYG4OW5.js +12 -0
  120. package/dist/{ledger-O7FXOG3D.js → ledger-5JMVF7PY.js} +5 -5
  121. package/dist/materialized-views/index.cjs.map +1 -1
  122. package/dist/materialized-views/index.d.cts +5 -6
  123. package/dist/materialized-views/index.d.ts +5 -6
  124. package/dist/materialized-views/index.js +6 -6
  125. package/dist/noydb-D5SLAJ6V.js +34 -0
  126. package/dist/overlay-views/index.cjs.map +1 -1
  127. package/dist/overlay-views/index.d.cts +5 -5
  128. package/dist/overlay-views/index.d.ts +5 -5
  129. package/dist/overlay-views/index.js +4 -4
  130. package/dist/periods/index.cjs.map +1 -1
  131. package/dist/periods/index.d.cts +4 -4
  132. package/dist/periods/index.d.ts +4 -4
  133. package/dist/periods/index.js +5 -5
  134. package/dist/{public-envelope-HMYHZIRH.js → public-envelope-PFLZI5MO.js} +4 -4
  135. package/dist/query/index.cjs +293 -10
  136. package/dist/query/index.cjs.map +1 -1
  137. package/dist/query/index.d.cts +2 -2
  138. package/dist/query/index.d.ts +2 -2
  139. package/dist/query/index.js +4 -4
  140. package/dist/registry-BVQ5ITMF.js +8 -0
  141. package/dist/registry-JLP3QOLD.js +8 -0
  142. package/dist/{registry-ST2VNFZC.js → registry-NCY445U5.js} +3 -3
  143. package/dist/{revoke-S6JMSLUN.js → revoke-7RLGQWZ7.js} +6 -6
  144. package/dist/session/index.cjs.map +1 -1
  145. package/dist/session/index.d.cts +5 -5
  146. package/dist/session/index.d.ts +5 -5
  147. package/dist/session/index.js +3 -3
  148. package/dist/shadow/index.cjs.map +1 -1
  149. package/dist/shadow/index.d.cts +4 -4
  150. package/dist/shadow/index.d.ts +4 -4
  151. package/dist/shadow/index.js +2 -2
  152. package/dist/{signer-7NPTB3SQ.js → signer-6JF44I4A.js} +5 -5
  153. package/dist/snapshots/index.cjs.map +1 -1
  154. package/dist/snapshots/index.d.cts +4 -4
  155. package/dist/snapshots/index.d.ts +4 -4
  156. package/dist/snapshots/index.js +4 -4
  157. package/dist/{stale-VKXSXJF4.js → stale-UBLP3RJ3.js} +2 -2
  158. package/dist/store/index.cjs.map +1 -1
  159. package/dist/store/index.d.cts +4 -4
  160. package/dist/store/index.d.ts +4 -4
  161. package/dist/store/index.js +2 -2
  162. package/dist/strategy-rtpKDfTC.d.cts +2029 -0
  163. package/dist/strategy-rtpKDfTC.d.ts +2029 -0
  164. package/dist/sync/index.cjs.map +1 -1
  165. package/dist/sync/index.d.cts +3 -3
  166. package/dist/sync/index.d.ts +3 -3
  167. package/dist/sync/index.js +4 -4
  168. package/dist/team/index.cjs.map +1 -1
  169. package/dist/team/index.d.cts +4 -4
  170. package/dist/team/index.d.ts +4 -4
  171. package/dist/team/index.js +8 -8
  172. package/dist/tx/index.cjs +8 -1
  173. package/dist/tx/index.cjs.map +1 -1
  174. package/dist/tx/index.d.cts +4 -4
  175. package/dist/tx/index.d.ts +4 -4
  176. package/dist/tx/index.js +3 -3
  177. package/dist/{types-n2_IfwlQ.d.cts → types-BGwjsDef.d.cts} +520 -6
  178. package/dist/{types-CaNQm4i8.d.ts → types-DRdfwgTG.d.ts} +520 -6
  179. package/dist/{ulid-CLMjmyhG.d.cts → ulid-D4d0Xto3.d.cts} +1 -1
  180. package/dist/{ulid-B9SMWj5i.d.ts → ulid-DOTPZ5_h.d.ts} +1 -1
  181. package/dist/util/index.cjs.map +1 -1
  182. package/dist/util/index.js +1 -1
  183. package/dist/vault-group-Z4KB75ZH.js +450 -0
  184. package/dist/vault-group-Z4KB75ZH.js.map +1 -0
  185. package/dist/{with-derivation-CVIOPTUf.d.ts → with-derivation-B082Y_WQ.d.ts} +1 -1
  186. package/dist/{with-derivation-aKrtS7Jj.d.cts → with-derivation-CB1EdcFF.d.cts} +1 -1
  187. package/dist/{with-materialized-view-C1eA1_T_.d.cts → with-materialized-view-CzRg1Dpr.d.cts} +1 -1
  188. package/dist/{with-materialized-view-DaYaE8-Q.d.ts → with-materialized-view-Dw4SwjKl.d.ts} +1 -1
  189. package/dist/{with-overlayed-view-DleJfKcV.d.cts → with-overlayed-view-C9YFKXzn.d.cts} +1 -1
  190. package/dist/{with-overlayed-view-DQsh2p8H.d.ts → with-overlayed-view-CaCXeW26.d.ts} +1 -1
  191. package/package.json +3 -3
  192. package/dist/chunk-2LPPNWF6.js +0 -340
  193. package/dist/chunk-2LPPNWF6.js.map +0 -1
  194. package/dist/chunk-4USCAEDT.js.map +0 -1
  195. package/dist/chunk-6YLPHBKR.js.map +0 -1
  196. package/dist/chunk-C3WE6UJY.js +0 -19
  197. package/dist/chunk-C3WE6UJY.js.map +0 -1
  198. package/dist/chunk-CXJG63MA.js.map +0 -1
  199. package/dist/chunk-DRXIZOFV.js.map +0 -1
  200. package/dist/chunk-HQSQC2XL.js.map +0 -1
  201. package/dist/chunk-O6EJ6WTI.js.map +0 -1
  202. package/dist/chunk-PVUUIWHY.js.map +0 -1
  203. package/dist/chunk-WIRRPTFH.js.map +0 -1
  204. package/dist/executor-S76VN45G.js +0 -8
  205. package/dist/executor-UCXLIGLW.js +0 -11
  206. package/dist/executor-ZCNZJMGR.js +0 -8
  207. package/dist/index-B8bjExET.d.cts +0 -2434
  208. package/dist/index-DfUbNad8.d.ts +0 -2434
  209. package/dist/issue-3W6IVLKH.js +0 -12
  210. package/dist/noydb-YAZNH5TI.js +0 -34
  211. package/dist/registry-UFIK7CSR.js +0 -8
  212. package/dist/registry-ZGYYSM5I.js +0 -8
  213. package/dist/strategy-CT2LCKAX.d.cts +0 -613
  214. package/dist/strategy-CT2LCKAX.d.ts +0 -613
  215. package/dist/with-guard-DZQbPzoP.d.cts +0 -18
  216. package/dist/with-guard-DseETUrF.d.ts +0 -18
  217. /package/dist/{chunk-7CEGU63S.js.map → chunk-4BHFNKTP.js.map} +0 -0
  218. /package/dist/{chunk-5OEJ6GOT.js.map → chunk-5ARRXIVR.js.map} +0 -0
  219. /package/dist/{chunk-YM7LFCG7.js.map → chunk-6BYBVRZU.js.map} +0 -0
  220. /package/dist/{chunk-5IXJGFF2.js.map → chunk-7JJE3OMJ.js.map} +0 -0
  221. /package/dist/{chunk-HHOO7HGH.js.map → chunk-7LVRIW4G.js.map} +0 -0
  222. /package/dist/{chunk-IMYKDWB4.js.map → chunk-B7GGYNKQ.js.map} +0 -0
  223. /package/dist/{chunk-BDV7INMP.js.map → chunk-BXOUVUES.js.map} +0 -0
  224. /package/dist/{chunk-FO3UEG4S.js.map → chunk-C2CIIQRG.js.map} +0 -0
  225. /package/dist/{chunk-ZROPXHJY.js.map → chunk-CHBXWJZQ.js.map} +0 -0
  226. /package/dist/{chunk-RYIL3PI2.js.map → chunk-CILT6V3V.js.map} +0 -0
  227. /package/dist/{chunk-PXTQPZO4.js.map → chunk-DLTU4M2I.js.map} +0 -0
  228. /package/dist/{chunk-GAUEWM7D.js.map → chunk-EKNUBIIQ.js.map} +0 -0
  229. /package/dist/{chunk-6EOXTJS2.js.map → chunk-HBAJDI2N.js.map} +0 -0
  230. /package/dist/{chunk-RRNA5GKT.js.map → chunk-IEPT7HVP.js.map} +0 -0
  231. /package/dist/{chunk-R233SLY3.js.map → chunk-IUBHXEPJ.js.map} +0 -0
  232. /package/dist/{chunk-CH22FZHT.js.map → chunk-L6BYRCYB.js.map} +0 -0
  233. /package/dist/{chunk-5OX6XVNS.js.map → chunk-LOA2VCMS.js.map} +0 -0
  234. /package/dist/{chunk-BB27JMWB.js.map → chunk-LSEW3ZZ2.js.map} +0 -0
  235. /package/dist/{chunk-Y26YV5R3.js.map → chunk-LWSD4QPT.js.map} +0 -0
  236. /package/dist/{chunk-26NK23DZ.js.map → chunk-M45IRXDM.js.map} +0 -0
  237. /package/dist/{chunk-GNHAC43Q.js.map → chunk-O53RIZCC.js.map} +0 -0
  238. /package/dist/{chunk-LSTBFLL2.js.map → chunk-P3Z5Y2TS.js.map} +0 -0
  239. /package/dist/{chunk-QSOYKKMD.js.map → chunk-P4EDT5ZP.js.map} +0 -0
  240. /package/dist/{chunk-PC6ZEDRL.js.map → chunk-RHQYVHFH.js.map} +0 -0
  241. /package/dist/{chunk-3LPV6BXR.js.map → chunk-RRDWXNBQ.js.map} +0 -0
  242. /package/dist/{chunk-4CLICFEY.js.map → chunk-SJJQKNMP.js.map} +0 -0
  243. /package/dist/{chunk-TY32C732.js.map → chunk-SZ4N3IL5.js.map} +0 -0
  244. /package/dist/{chunk-2N62W5YP.js.map → chunk-UA6G45ME.js.map} +0 -0
  245. /package/dist/{chunk-DAP2XL7Q.js.map → chunk-VOXMU6LB.js.map} +0 -0
  246. /package/dist/{chunk-DJRWA3Q5.js.map → chunk-WUG3E423.js.map} +0 -0
  247. /package/dist/{chunk-PM3QYWUU.js.map → chunk-XHM2SARW.js.map} +0 -0
  248. /package/dist/{chunk-RC6SU5NO.js.map → chunk-XSIFXX54.js.map} +0 -0
  249. /package/dist/{chunk-CXFOITNS.js.map → chunk-ZC7MNVYN.js.map} +0 -0
  250. /package/dist/{chunk-6T2UDBKG.js.map → chunk-ZCFS7U4J.js.map} +0 -0
  251. /package/dist/{crypto-2CRLG4F4.js.map → crypto-AJB72OKN.js.map} +0 -0
  252. /package/dist/{delegation-ZTRT2PRV.js.map → delegation-6FCWDRUS.js.map} +0 -0
  253. /package/dist/{executor-S76VN45G.js.map → executor-7KSCEIFA.js.map} +0 -0
  254. /package/dist/{executor-UCXLIGLW.js.map → executor-D2QMNGRJ.js.map} +0 -0
  255. /package/dist/{executor-ZCNZJMGR.js.map → executor-O5AZK7UW.js.map} +0 -0
  256. /package/dist/{fanout-sidecar-OKPMMPLG.js.map → fanout-sidecar-ZSKEQ6NI.js.map} +0 -0
  257. /package/dist/{issue-3W6IVLKH.js.map → issue-YIYG4OW5.js.map} +0 -0
  258. /package/dist/{ledger-O7FXOG3D.js.map → ledger-5JMVF7PY.js.map} +0 -0
  259. /package/dist/{noydb-YAZNH5TI.js.map → noydb-D5SLAJ6V.js.map} +0 -0
  260. /package/dist/{public-envelope-HMYHZIRH.js.map → public-envelope-PFLZI5MO.js.map} +0 -0
  261. /package/dist/{registry-ST2VNFZC.js.map → registry-BVQ5ITMF.js.map} +0 -0
  262. /package/dist/{registry-UFIK7CSR.js.map → registry-JLP3QOLD.js.map} +0 -0
  263. /package/dist/{registry-ZGYYSM5I.js.map → registry-NCY445U5.js.map} +0 -0
  264. /package/dist/{revoke-S6JMSLUN.js.map → revoke-7RLGQWZ7.js.map} +0 -0
  265. /package/dist/{signer-7NPTB3SQ.js.map → signer-6JF44I4A.js.map} +0 -0
  266. /package/dist/{stale-VKXSXJF4.js.map → stale-UBLP3RJ3.js.map} +0 -0
@@ -0,0 +1,783 @@
1
+ import {
2
+ readPath
3
+ } from "./chunk-TV3YZ35S.js";
4
+ import {
5
+ GroupCardinalityError,
6
+ NoydbError
7
+ } from "./chunk-AGRC7NQQ.js";
8
+
9
+ // src/money/iso4217.ts
10
+ var MINOR_UNITS = {
11
+ // 2-decimal majors
12
+ EUR: 2,
13
+ USD: 2,
14
+ GBP: 2,
15
+ CHF: 2,
16
+ CAD: 2,
17
+ AUD: 2,
18
+ NZD: 2,
19
+ SGD: 2,
20
+ HKD: 2,
21
+ CNY: 2,
22
+ INR: 2,
23
+ BRL: 2,
24
+ MXN: 2,
25
+ ZAR: 2,
26
+ RUB: 2,
27
+ TRY: 2,
28
+ PLN: 2,
29
+ SEK: 2,
30
+ NOK: 2,
31
+ DKK: 2,
32
+ CZK: 2,
33
+ HUF: 2,
34
+ RON: 2,
35
+ ILS: 2,
36
+ THB: 2,
37
+ PHP: 2,
38
+ MYR: 2,
39
+ IDR: 2,
40
+ AED: 2,
41
+ SAR: 2,
42
+ QAR: 2,
43
+ EGP: 2,
44
+ // 0-decimal
45
+ JPY: 0,
46
+ KRW: 0,
47
+ ISK: 0,
48
+ CLP: 0,
49
+ VND: 0,
50
+ XOF: 0,
51
+ XAF: 0,
52
+ PYG: 0,
53
+ // 3-decimal
54
+ BHD: 3,
55
+ KWD: 3,
56
+ OMR: 3,
57
+ TND: 3,
58
+ JOD: 3,
59
+ IQD: 3,
60
+ LYD: 3
61
+ };
62
+ function scaleForCurrency(code) {
63
+ const v = MINOR_UNITS[code];
64
+ return v === void 0 ? null : v;
65
+ }
66
+
67
+ // src/money/descriptor.ts
68
+ var MoneyPrecisionError = class extends NoydbError {
69
+ constructor(field, value, scale) {
70
+ super(
71
+ "MONEY_PRECISION",
72
+ `money: value ${JSON.stringify(value)} for field "${field}" exceeds scale ${scale} and no rounding mode is configured`
73
+ );
74
+ this.field = field;
75
+ this.value = value;
76
+ this.scale = scale;
77
+ this.name = "MoneyPrecisionError";
78
+ }
79
+ field;
80
+ value;
81
+ scale;
82
+ };
83
+ var MoneyCurrencyError = class extends NoydbError {
84
+ constructor(currency, reason, field) {
85
+ super(
86
+ "MONEY_CURRENCY",
87
+ reason === "not-allowed" ? `money: currency "${currency}" is not allowed${field ? ` for field "${field}"` : ""}` : `money: no scale known for currency "${currency}"${field ? ` (field "${field}")` : ""} \u2014 pass an explicit scale / scaleOverrides`
88
+ );
89
+ this.currency = currency;
90
+ this.reason = reason;
91
+ this.field = field;
92
+ this.name = "MoneyCurrencyError";
93
+ }
94
+ currency;
95
+ reason;
96
+ field;
97
+ };
98
+ var MoneyUnsupportedError = class extends NoydbError {
99
+ constructor(field, message) {
100
+ super(
101
+ "MONEY_UNSUPPORTED",
102
+ message ?? `money: operation is not supported on field "${field}" \u2014 use sum() and count() and divide at the boundary`
103
+ );
104
+ this.field = field;
105
+ this.name = "MoneyUnsupportedError";
106
+ }
107
+ field;
108
+ };
109
+ function isMultiOptions(o) {
110
+ return "currencies" in o;
111
+ }
112
+ function money(options) {
113
+ const hasFixed = "currency" in options;
114
+ const hasMulti = "currencies" in options;
115
+ if (hasFixed && hasMulti) {
116
+ throw new TypeError("money: `currency` and `currencies` are mutually exclusive");
117
+ }
118
+ if (!hasFixed && !hasMulti) {
119
+ throw new TypeError("money: one of `currency` or `currencies` is required");
120
+ }
121
+ const rounding = options.rounding;
122
+ if (isMultiOptions(options)) {
123
+ const overrides = options.scaleOverrides ?? {};
124
+ const allowList = options.currencies;
125
+ const allows = (c) => allowList === "any" ? true : allowList.includes(c);
126
+ const scaleFor = (c) => {
127
+ if (!allows(c)) throw new MoneyCurrencyError(c, "not-allowed");
128
+ const s = overrides[c] ?? scaleForCurrency(c);
129
+ if (s === null || s === void 0) throw new MoneyCurrencyError(c, "unknown-scale");
130
+ return s;
131
+ };
132
+ if (allowList !== "any") for (const c of allowList) scaleFor(c);
133
+ const soleCurrency = () => allowList !== "any" && allowList.length === 1 ? allowList[0] : void 0;
134
+ return {
135
+ _noydbMoney: true,
136
+ mode: "multi",
137
+ options,
138
+ rounding,
139
+ fixedCurrency: void 0,
140
+ scaleFor,
141
+ allows,
142
+ soleCurrency
143
+ };
144
+ }
145
+ const currency = options.currency;
146
+ const resolvedScale = options.scale ?? scaleForCurrency(currency);
147
+ if (resolvedScale === null || resolvedScale === void 0) {
148
+ throw new MoneyCurrencyError(currency, "unknown-scale");
149
+ }
150
+ return {
151
+ _noydbMoney: true,
152
+ mode: "fixed",
153
+ options,
154
+ rounding,
155
+ fixedCurrency: currency,
156
+ scaleFor(c) {
157
+ if (c !== currency) throw new MoneyCurrencyError(c, "not-allowed");
158
+ return resolvedScale;
159
+ },
160
+ allows: (c) => c === currency,
161
+ soleCurrency: () => currency
162
+ };
163
+ }
164
+ function isMoneyDescriptor(x) {
165
+ return typeof x === "object" && x !== null && x._noydbMoney === true;
166
+ }
167
+
168
+ // src/aggregate/aggregation.ts
169
+ function reduceRecords(records, spec) {
170
+ const state = {};
171
+ for (const key of Object.keys(spec)) {
172
+ state[key] = spec[key].init();
173
+ }
174
+ for (const record of records) {
175
+ for (const key of Object.keys(spec)) {
176
+ state[key] = spec[key].step(state[key], record);
177
+ }
178
+ }
179
+ const result = {};
180
+ for (const key of Object.keys(spec)) {
181
+ result[key] = spec[key].finalize(state[key]);
182
+ }
183
+ return result;
184
+ }
185
+ var LiveAggregationImpl = class {
186
+ constructor(recompute, upstreams) {
187
+ this.recompute = recompute;
188
+ try {
189
+ this.value = recompute();
190
+ this.error = void 0;
191
+ } catch (err) {
192
+ this.value = void 0;
193
+ this.error = err;
194
+ }
195
+ for (const upstream of upstreams) {
196
+ const unsub = upstream.subscribe(() => this.refresh());
197
+ this.unsubscribes.push(unsub);
198
+ }
199
+ }
200
+ recompute;
201
+ value;
202
+ error;
203
+ listeners = /* @__PURE__ */ new Set();
204
+ unsubscribes = [];
205
+ stopped = false;
206
+ refresh() {
207
+ if (this.stopped) return;
208
+ try {
209
+ this.value = this.recompute();
210
+ this.error = void 0;
211
+ } catch (err) {
212
+ this.error = err;
213
+ }
214
+ for (const listener of this.listeners) {
215
+ try {
216
+ listener();
217
+ } catch (err) {
218
+ console.warn("[noy-db] LiveAggregation listener threw:", err);
219
+ }
220
+ }
221
+ }
222
+ subscribe(cb) {
223
+ if (this.stopped) {
224
+ return () => {
225
+ };
226
+ }
227
+ this.listeners.add(cb);
228
+ return () => {
229
+ this.listeners.delete(cb);
230
+ };
231
+ }
232
+ stop() {
233
+ if (this.stopped) return;
234
+ this.stopped = true;
235
+ for (const unsub of this.unsubscribes) {
236
+ try {
237
+ unsub();
238
+ } catch (err) {
239
+ console.warn("[noy-db] LiveAggregation upstream unsubscribe threw:", err);
240
+ }
241
+ }
242
+ this.unsubscribes.length = 0;
243
+ this.listeners.clear();
244
+ }
245
+ };
246
+ var Aggregation = class {
247
+ constructor(executeRecords, spec, upstreams) {
248
+ this.executeRecords = executeRecords;
249
+ this.spec = spec;
250
+ this.upstreams = upstreams;
251
+ }
252
+ executeRecords;
253
+ spec;
254
+ upstreams;
255
+ /**
256
+ * Execute the query and reduce the results synchronously.
257
+ * Returns the reduced shape matching the spec — e.g. a spec of
258
+ * `{ total: sum('amount'), n: count() }` returns
259
+ * `{ total: number, n: number }`.
260
+ */
261
+ run() {
262
+ return reduceRecords(this.executeRecords(), this.spec);
263
+ }
264
+ /**
265
+ * Build a reactive `LiveAggregation<R>` that re-runs the reduction
266
+ * whenever any upstream source notifies of a change. The initial
267
+ * value is computed eagerly in the constructor, so consumers can
268
+ * read `live.value` immediately after calling `.live()`.
269
+ *
270
+ * Always call `live.stop()` when finished — it tears down the
271
+ * upstream subscriptions. Vue's `onUnmounted` is the canonical
272
+ * place.
273
+ *
274
+ * **Implementation note:** every upstream change triggers a full
275
+ * re-reduction. Incremental maintenance (O(1) per delta for
276
+ * sum/count/avg via the reducer protocol's `remove()` method) is a
277
+ * planned follow-up optimization — the protocol already supports
278
+ * it, but the executor doesn't drive it yet. Consumers get
279
+ * correct, reactive values today; future PRs can switch to
280
+ * delta-based maintenance without changing this API.
281
+ */
282
+ live() {
283
+ const recompute = () => reduceRecords(this.executeRecords(), this.spec);
284
+ return new LiveAggregationImpl(recompute, this.upstreams);
285
+ }
286
+ };
287
+ function buildLiveAggregation(recompute, upstreams) {
288
+ return new LiveAggregationImpl(recompute, upstreams);
289
+ }
290
+
291
+ // src/aggregate/canonical-key.ts
292
+ function canonicalGroupKey(fields, row) {
293
+ const sorted = [...fields].sort();
294
+ const parts = [];
295
+ for (const name of sorted) {
296
+ const v = row[name];
297
+ const serialised = v === void 0 ? "undefined" : JSON.stringify(v);
298
+ parts.push(`${name}=${serialised}`);
299
+ }
300
+ return parts.join("|");
301
+ }
302
+
303
+ // src/money/fixed-point.ts
304
+ function expandExponent(s) {
305
+ const m = /^([+-]?)(\d+)(?:\.(\d+))?[eE]([+-]?\d+)$/.exec(s);
306
+ if (!m) return s;
307
+ const sign = m[1] === "-" ? "-" : "";
308
+ const intp = m[2];
309
+ const frac = m[3] ?? "";
310
+ const exp = Number(m[4]);
311
+ const digits = intp + frac;
312
+ const pointPos = intp.length + exp;
313
+ let body;
314
+ if (pointPos <= 0) {
315
+ body = "0." + "0".repeat(-pointPos) + digits;
316
+ } else if (pointPos >= digits.length) {
317
+ body = digits + "0".repeat(pointPos - digits.length);
318
+ } else {
319
+ body = digits.slice(0, pointPos) + "." + digits.slice(pointPos);
320
+ }
321
+ return sign + body;
322
+ }
323
+ function toCanonicalDecimalString(input) {
324
+ let s;
325
+ if (typeof input === "number") {
326
+ if (!Number.isFinite(input)) return null;
327
+ s = String(input);
328
+ } else {
329
+ s = input.trim();
330
+ }
331
+ s = expandExponent(s);
332
+ if (s.startsWith("+")) s = s.slice(1);
333
+ if (!/^-?(\d+(\.\d*)?|\.\d+)$/.test(s)) return null;
334
+ return s;
335
+ }
336
+ function shouldRoundUp(negative, lastKeptDigit, firstDiscarded, hasMoreNonZeroAfterFirst, mode) {
337
+ switch (mode) {
338
+ case "up":
339
+ return true;
340
+ case "down":
341
+ return false;
342
+ case "ceil":
343
+ return !negative;
344
+ case "floor":
345
+ return negative;
346
+ case "half-up":
347
+ return firstDiscarded >= 5;
348
+ case "half-down":
349
+ return firstDiscarded > 5 || firstDiscarded === 5 && hasMoreNonZeroAfterFirst;
350
+ case "half-even":
351
+ if (firstDiscarded > 5) return true;
352
+ if (firstDiscarded < 5) return false;
353
+ return hasMoreNonZeroAfterFirst || lastKeptDigit % 2 === 1;
354
+ }
355
+ }
356
+ function parseToScaledInt(input, scale, rounding) {
357
+ const canonical = toCanonicalDecimalString(input);
358
+ if (canonical === null) return { ok: false, reason: "nonfinite" };
359
+ const negative = canonical.startsWith("-");
360
+ const unsigned = negative ? canonical.slice(1) : canonical;
361
+ const dot = unsigned.indexOf(".");
362
+ const intPart = dot === -1 ? unsigned : unsigned.slice(0, dot);
363
+ const fracPart = dot === -1 ? "" : unsigned.slice(dot + 1);
364
+ const intDigits = intPart === "" ? "0" : intPart;
365
+ if (fracPart.length <= scale) {
366
+ const keep2 = fracPart.padEnd(scale, "0");
367
+ const magnitude2 = BigInt(intDigits + keep2);
368
+ return { ok: true, value: negative && magnitude2 !== 0n ? -magnitude2 : magnitude2 };
369
+ }
370
+ const keep = fracPart.slice(0, scale);
371
+ const tail = fracPart.slice(scale);
372
+ const magnitudeDigits = intDigits + keep;
373
+ let magnitude = BigInt(magnitudeDigits);
374
+ if (/^0+$/.test(tail)) {
375
+ return { ok: true, value: negative && magnitude !== 0n ? -magnitude : magnitude };
376
+ }
377
+ if (rounding === void 0) return { ok: false, reason: "precision" };
378
+ const lastKeptDigit = Number(magnitudeDigits[magnitudeDigits.length - 1]);
379
+ const firstDiscarded = Number(tail[0]);
380
+ const hasMoreNonZeroAfterFirst = /[1-9]/.test(tail.slice(1));
381
+ if (shouldRoundUp(negative, lastKeptDigit, firstDiscarded, hasMoreNonZeroAfterFirst, rounding)) {
382
+ magnitude += 1n;
383
+ }
384
+ return { ok: true, value: negative && magnitude !== 0n ? -magnitude : magnitude };
385
+ }
386
+ function formatScaledInt(value, scale) {
387
+ const negative = value < 0n;
388
+ const abs = (negative ? -value : value).toString();
389
+ if (scale === 0) return (negative ? "-" : "") + abs;
390
+ const padded = abs.padStart(scale + 1, "0");
391
+ const cut = padded.length - scale;
392
+ const intPart = padded.slice(0, cut);
393
+ const fracPart = padded.slice(cut);
394
+ return (negative ? "-" : "") + intPart + "." + fracPart;
395
+ }
396
+
397
+ // src/money/money-reducer.ts
398
+ function toScaledInt(v) {
399
+ if (typeof v === "string" || typeof v === "number" || typeof v === "bigint") {
400
+ try {
401
+ return BigInt(v);
402
+ } catch {
403
+ return null;
404
+ }
405
+ }
406
+ return null;
407
+ }
408
+ function readMoney(record, field, desc) {
409
+ const raw = readPath(record, field);
410
+ if (raw === null || raw === void 0) return null;
411
+ if (desc.mode === "fixed") {
412
+ const value2 = toScaledInt(raw);
413
+ return value2 === null ? null : { currency: desc.fixedCurrency, value: value2 };
414
+ }
415
+ if (typeof raw !== "object") return null;
416
+ const o = raw;
417
+ if (typeof o.currency !== "string") return null;
418
+ const value = toScaledInt(o.amount);
419
+ return value === null ? null : { currency: o.currency, value };
420
+ }
421
+ function targetScaleFor(desc, currency) {
422
+ if (desc.allows(currency)) return desc.scaleFor(currency);
423
+ const s = scaleForCurrency(currency);
424
+ if (s === null) {
425
+ throw new Error(`money: cannot determine scale for conversion target "${currency}"`);
426
+ }
427
+ return s;
428
+ }
429
+ function parseRate(rate) {
430
+ const s = String(rate).trim();
431
+ const neg = s.startsWith("-");
432
+ const body = neg ? s.slice(1) : s;
433
+ const dot = body.indexOf(".");
434
+ const intPart = dot === -1 ? body : body.slice(0, dot);
435
+ const fracPart = dot === -1 ? "" : body.slice(dot + 1);
436
+ const int = BigInt((intPart === "" ? "0" : intPart) + fracPart);
437
+ return { int: neg ? -int : int, scale: fracPart.length };
438
+ }
439
+ function divRoundHalfEven(n, d) {
440
+ const q = n / d;
441
+ const r = n % d;
442
+ const twiceR = (r < 0n ? -r : r) * 2n;
443
+ if (twiceR < d) return q;
444
+ if (twiceR > d) return q + (n < 0n ? -1n : 1n);
445
+ return q % 2n === 0n ? q : q + (n < 0n ? -1n : 1n);
446
+ }
447
+ function convertScaled(value, srcScale, rate, targetScale) {
448
+ const { int: rateInt, scale: rateScale } = parseRate(rate);
449
+ const product = value * rateInt;
450
+ const curScale = srcScale + rateScale;
451
+ if (curScale === targetScale) return product;
452
+ if (curScale < targetScale) return product * 10n ** BigInt(targetScale - curScale);
453
+ return divRoundHalfEven(product, 10n ** BigInt(curScale - targetScale));
454
+ }
455
+ function finalizeSum(state, desc, convertTo, fx) {
456
+ if (convertTo !== void 0) {
457
+ if (fx === void 0) {
458
+ throw new Error(`money: sum convertTo "${convertTo}" requires an fx rate map`);
459
+ }
460
+ const targetScale = targetScaleFor(desc, convertTo);
461
+ let total = 0n;
462
+ for (const [cur, v] of state) {
463
+ if (cur === convertTo) {
464
+ total += convertScaled(v, desc.scaleFor(cur), 1, targetScale);
465
+ continue;
466
+ }
467
+ const rate = fx[`${cur}->${convertTo}`];
468
+ if (rate === void 0) {
469
+ throw new Error(`money: no fx rate for "${cur}->${convertTo}"`);
470
+ }
471
+ total += convertScaled(v, desc.scaleFor(cur), rate, targetScale);
472
+ }
473
+ return formatScaledInt(total, targetScale);
474
+ }
475
+ if (desc.mode === "fixed") {
476
+ const cur = desc.fixedCurrency;
477
+ return formatScaledInt(state.get(cur) ?? 0n, desc.scaleFor(cur));
478
+ }
479
+ const out = {};
480
+ for (const [cur, v] of state) out[cur] = formatScaledInt(v, desc.scaleFor(cur));
481
+ return out;
482
+ }
483
+ function moneySumReducer(field, desc, convertTo, fx) {
484
+ return {
485
+ op: "sum",
486
+ field,
487
+ init: () => /* @__PURE__ */ new Map(),
488
+ step: (state, record) => {
489
+ const m = readMoney(record, field, desc);
490
+ if (m) state.set(m.currency, (state.get(m.currency) ?? 0n) + m.value);
491
+ return state;
492
+ },
493
+ remove: (state, record) => {
494
+ const m = readMoney(record, field, desc);
495
+ if (m) state.set(m.currency, (state.get(m.currency) ?? 0n) - m.value);
496
+ return state;
497
+ },
498
+ finalize: (state) => finalizeSum(state, desc, convertTo, fx)
499
+ };
500
+ }
501
+ function extremum(values, op) {
502
+ let out = values[0];
503
+ for (let i = 1; i < values.length; i++) {
504
+ const v = values[i];
505
+ if (op === "min" ? v < out : v > out) out = v;
506
+ }
507
+ return out;
508
+ }
509
+ function moneyMinMaxReducer(op, field, desc) {
510
+ return {
511
+ op,
512
+ field,
513
+ init: () => /* @__PURE__ */ new Map(),
514
+ step: (state, record) => {
515
+ const m = readMoney(record, field, desc);
516
+ if (m) {
517
+ const arr = state.get(m.currency);
518
+ if (arr) arr.push(m.value);
519
+ else state.set(m.currency, [m.value]);
520
+ }
521
+ return state;
522
+ },
523
+ remove: (state, record) => {
524
+ const m = readMoney(record, field, desc);
525
+ if (m) {
526
+ const arr = state.get(m.currency);
527
+ if (arr) {
528
+ const idx = arr.indexOf(m.value);
529
+ if (idx >= 0) arr.splice(idx, 1);
530
+ }
531
+ }
532
+ return state;
533
+ },
534
+ finalize: (state) => {
535
+ if (desc.mode === "fixed") {
536
+ const cur = desc.fixedCurrency;
537
+ const arr = state.get(cur);
538
+ if (!arr || arr.length === 0) return null;
539
+ return formatScaledInt(extremum(arr, op), desc.scaleFor(cur));
540
+ }
541
+ const out = {};
542
+ for (const [cur, arr] of state) {
543
+ if (arr.length > 0) out[cur] = formatScaledInt(extremum(arr, op), desc.scaleFor(cur));
544
+ }
545
+ return out;
546
+ }
547
+ };
548
+ }
549
+ function wrapMoneyReducers(spec, moneyFields) {
550
+ let changed = false;
551
+ const out = {};
552
+ for (const [key, reducer] of Object.entries(spec)) {
553
+ const field = reducer.field;
554
+ const desc = field ? moneyFields[field] : void 0;
555
+ if (desc && reducer.op === "avg") {
556
+ throw new MoneyUnsupportedError(
557
+ field,
558
+ `avg() is not supported on money field "${field}" in v1 \u2014 use sum() and count() and divide at the boundary.`
559
+ );
560
+ }
561
+ if (desc && (reducer.op === "sum" || reducer.op === "min" || reducer.op === "max")) {
562
+ changed = true;
563
+ out[key] = reducer.op === "sum" ? moneySumReducer(field, desc, reducer.convertTo, reducer.fx) : moneyMinMaxReducer(reducer.op, field, desc);
564
+ } else {
565
+ out[key] = reducer;
566
+ }
567
+ }
568
+ return changed ? out : spec;
569
+ }
570
+
571
+ // src/aggregate/groupby.ts
572
+ var GROUPBY_WARN_CARDINALITY = 1e4;
573
+ var GROUPBY_MAX_CARDINALITY = 1e5;
574
+ var warnedCardinalityFields = /* @__PURE__ */ new Set();
575
+ function warnCardinalityApproaching(fields, observed) {
576
+ const key = JSON.stringify([...fields].sort());
577
+ if (warnedCardinalityFields.has(key)) return;
578
+ warnedCardinalityFields.add(key);
579
+ const label = `[${fields.join(", ")}]`;
580
+ console.warn(
581
+ `[noy-db] .groupBy(${label}) produced ${observed} distinct groups, ${Math.round(observed / GROUPBY_MAX_CARDINALITY * 100)}% of the ${GROUPBY_MAX_CARDINALITY}-group ceiling. Narrow the query with .where() before grouping, or switch to a lower-cardinality field.`
582
+ );
583
+ }
584
+ function resetGroupByWarnings() {
585
+ warnedCardinalityFields.clear();
586
+ }
587
+ var GroupedQueryBase = class {
588
+ constructor(executeRecords, fieldOrFields, upstreams, dictLabelResolver, moneyFields) {
589
+ this.executeRecords = executeRecords;
590
+ this.upstreams = upstreams;
591
+ this.dictLabelResolver = dictLabelResolver;
592
+ this.moneyFields = moneyFields;
593
+ this.fields = typeof fieldOrFields === "string" ? [fieldOrFields] : [...fieldOrFields];
594
+ }
595
+ executeRecords;
596
+ upstreams;
597
+ dictLabelResolver;
598
+ moneyFields;
599
+ /**
600
+ * Field set this grouped query buckets on. Stored in declaration
601
+ * order — the same order is preserved on every result row by
602
+ * `groupAndReduce`. For the single-field constructor, this is
603
+ * `[field]`.
604
+ */
605
+ fields;
606
+ /** Apply money-aware reducer rewriting when money fields are declared. */
607
+ wrapSpec(spec) {
608
+ return this.moneyFields ? wrapMoneyReducers(spec, this.moneyFields) : spec;
609
+ }
610
+ };
611
+ var GroupedQuery = class extends GroupedQueryBase {
612
+ /**
613
+ * Build a grouped aggregation. Returns a `GroupedAggregation`
614
+ * with `.run()`, `.runAsync()`, and `.live()` terminals — same shape
615
+ * as the non-grouped `.aggregate()` wrapper, just with an array
616
+ * result (one row per bucket) instead of a single reduced object.
617
+ */
618
+ aggregate(spec) {
619
+ return new GroupedAggregation(
620
+ this.executeRecords,
621
+ this.fields,
622
+ this.wrapSpec(spec),
623
+ this.upstreams,
624
+ this.dictLabelResolver
625
+ );
626
+ }
627
+ };
628
+ var GroupedQueryN = class extends GroupedQueryBase {
629
+ aggregate(spec) {
630
+ return new GroupedAggregation(
631
+ this.executeRecords,
632
+ this.fields,
633
+ this.wrapSpec(spec),
634
+ this.upstreams,
635
+ this.dictLabelResolver
636
+ );
637
+ }
638
+ };
639
+ function groupAndReduce(records, fieldOrFields, spec) {
640
+ const fields = typeof fieldOrFields === "string" ? [fieldOrFields] : fieldOrFields;
641
+ if (fields.length === 0) {
642
+ throw new Error(".groupBy() requires at least one field");
643
+ }
644
+ const buckets = /* @__PURE__ */ new Map();
645
+ const fieldLabel = fields.length === 1 ? fields[0] : `[${fields.join(", ")}]`;
646
+ for (const record of records) {
647
+ const keyValues = {};
648
+ for (const f of fields) {
649
+ keyValues[f] = readPath(record, f);
650
+ }
651
+ const dedupKey = canonicalGroupKey(fields, keyValues);
652
+ let bucket = buckets.get(dedupKey);
653
+ if (bucket === void 0) {
654
+ if (buckets.size >= GROUPBY_MAX_CARDINALITY) {
655
+ throw new GroupCardinalityError(
656
+ fieldLabel,
657
+ buckets.size + 1,
658
+ GROUPBY_MAX_CARDINALITY
659
+ );
660
+ }
661
+ bucket = { keyValues, records: [] };
662
+ buckets.set(dedupKey, bucket);
663
+ }
664
+ bucket.records.push(record);
665
+ }
666
+ if (buckets.size >= GROUPBY_WARN_CARDINALITY) {
667
+ warnCardinalityApproaching(fields, buckets.size);
668
+ }
669
+ const reducerKeys = Object.keys(spec);
670
+ const out = [];
671
+ for (const bucket of buckets.values()) {
672
+ const state = {};
673
+ for (const rk of reducerKeys) {
674
+ state[rk] = spec[rk].init();
675
+ }
676
+ for (const record of bucket.records) {
677
+ for (const rk of reducerKeys) {
678
+ state[rk] = spec[rk].step(state[rk], record);
679
+ }
680
+ }
681
+ const row = {};
682
+ for (const f of fields) {
683
+ row[f] = bucket.keyValues[f];
684
+ }
685
+ for (const rk of reducerKeys) {
686
+ row[rk] = spec[rk].finalize(state[rk]);
687
+ }
688
+ out.push(row);
689
+ }
690
+ return out;
691
+ }
692
+ var GroupedAggregation = class {
693
+ constructor(executeRecords, fields, spec, upstreams, dictLabelResolver) {
694
+ this.executeRecords = executeRecords;
695
+ this.spec = spec;
696
+ this.upstreams = upstreams;
697
+ this.dictLabelResolver = dictLabelResolver;
698
+ this.fields = typeof fields === "string" ? [fields] : [...fields];
699
+ }
700
+ executeRecords;
701
+ spec;
702
+ upstreams;
703
+ dictLabelResolver;
704
+ fields;
705
+ /** Execute the query, group, reduce, and return an array of rows. */
706
+ run() {
707
+ return groupAndReduce(this.executeRecords(), this.fields, this.spec);
708
+ }
709
+ /**
710
+ * Execute the query, group, reduce, and resolve `<field>Label` for
711
+ * each result row when the grouping field is a `dictKey` and a
712
+ * `locale` is provided. Returns `R[]` synchronously when
713
+ * no locale is specified (identical to `.run()`).
714
+ *
715
+ * The `<field>Label` field is appended to each row. Rows whose group
716
+ * key has no dictionary entry get `<field>Label: undefined`.
717
+ *
718
+ * Dict-label resolution is single-field only — multi-key groupings
719
+ * do not produce a `<field>Label`. The resolver is only attached
720
+ * by the builder when `fields.length === 1`.
721
+ */
722
+ async runAsync(opts) {
723
+ const rows = groupAndReduce(this.executeRecords(), this.fields, this.spec);
724
+ if (!opts?.locale || !this.dictLabelResolver || this.fields.length !== 1) return rows;
725
+ const resolve = this.dictLabelResolver;
726
+ const locale = opts.locale;
727
+ const fallback = opts.fallback;
728
+ const field = this.fields[0];
729
+ const labelKey = `${field}Label`;
730
+ return Promise.all(
731
+ rows.map(async (row) => {
732
+ const key = row[field];
733
+ if (typeof key !== "string") return row;
734
+ const label = await resolve(key, locale, fallback);
735
+ return { ...row, [labelKey]: label };
736
+ })
737
+ );
738
+ }
739
+ /**
740
+ * Build a reactive `LiveAggregation<R[]>` that re-runs the full
741
+ * group-and-reduce pipeline whenever any upstream source notifies
742
+ * of a change. Same error-isolation and idempotent-stop contract
743
+ * as `Aggregation.live()` — the implementation delegates to the
744
+ * same `LiveAggregationImpl` class by threading a fresh
745
+ * recompute closure through the existing constructor.
746
+ *
747
+ * uses naive full re-run on every change. Incremental
748
+ * per-bucket maintenance (apply `step` on inserted records,
749
+ * `remove` on deleted records, route by bucket key) is a future
750
+ * optimization — the reducer protocol admits it, but wiring
751
+ * delta-aware source subscriptions is a separate PR.
752
+ *
753
+ * Always call `live.stop()` when finished.
754
+ */
755
+ live() {
756
+ const recompute = () => groupAndReduce(this.executeRecords(), this.fields, this.spec);
757
+ return buildLiveAggregation(recompute, this.upstreams);
758
+ }
759
+ };
760
+
761
+ export {
762
+ parseToScaledInt,
763
+ formatScaledInt,
764
+ scaleForCurrency,
765
+ MoneyPrecisionError,
766
+ MoneyCurrencyError,
767
+ MoneyUnsupportedError,
768
+ money,
769
+ isMoneyDescriptor,
770
+ wrapMoneyReducers,
771
+ reduceRecords,
772
+ Aggregation,
773
+ buildLiveAggregation,
774
+ canonicalGroupKey,
775
+ GROUPBY_WARN_CARDINALITY,
776
+ GROUPBY_MAX_CARDINALITY,
777
+ resetGroupByWarnings,
778
+ GroupedQuery,
779
+ GroupedQueryN,
780
+ groupAndReduce,
781
+ GroupedAggregation
782
+ };
783
+ //# sourceMappingURL=chunk-OPDTLHFA.js.map