@noy-db/hub 0.2.0-pre.13 → 0.2.0-pre.15

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 (260) hide show
  1. package/dist/aggregate/index.cjs +56 -56
  2. package/dist/aggregate/index.cjs.map +1 -1
  3. package/dist/aggregate/index.d.cts +2 -2
  4. package/dist/aggregate/index.d.ts +2 -2
  5. package/dist/aggregate/index.js +4 -4
  6. package/dist/attestation/index.cjs.map +1 -1
  7. package/dist/attestation/index.d.cts +5 -5
  8. package/dist/attestation/index.d.ts +5 -5
  9. package/dist/attestation/index.js +5 -5
  10. package/dist/blobs/index.cjs.map +1 -1
  11. package/dist/blobs/index.d.cts +6 -6
  12. package/dist/blobs/index.d.ts +6 -6
  13. package/dist/blobs/index.js +4 -4
  14. package/dist/bundle/index.cjs +559 -76
  15. package/dist/bundle/index.cjs.map +1 -1
  16. package/dist/bundle/index.d.cts +7 -7
  17. package/dist/bundle/index.d.ts +7 -7
  18. package/dist/bundle/index.js +8 -8
  19. package/dist/{chunk-YWBHS25M.js → chunk-3EWXMOK3.js} +8 -267
  20. package/dist/chunk-3EWXMOK3.js.map +1 -0
  21. package/dist/{chunk-SJ24GHID.js → chunk-4TBBMHVC.js} +2 -2
  22. package/dist/{chunk-NKGY3C53.js → chunk-535SSHBS.js} +8 -1
  23. package/dist/{chunk-NKGY3C53.js.map → chunk-535SSHBS.js.map} +1 -1
  24. package/dist/{chunk-HQXOEWLZ.js → chunk-56DJ7JVK.js} +3 -3
  25. package/dist/{chunk-KKB42D3Q.js → chunk-5LQG6ZO2.js} +2 -2
  26. package/dist/{chunk-TDECYU4Y.js → chunk-6AJBSQU4.js} +2 -2
  27. package/dist/{chunk-O2JW656W.js → chunk-6RR3MNMG.js} +3 -3
  28. package/dist/{chunk-P5MW7BG2.js → chunk-7EFFHEN5.js} +57 -50
  29. package/dist/chunk-7EFFHEN5.js.map +1 -0
  30. package/dist/{chunk-7TEI2K2A.js → chunk-7HT2MEZ5.js} +4 -4
  31. package/dist/{chunk-WQKZIQIL.js → chunk-7PS7EOCF.js} +3 -3
  32. package/dist/{chunk-C3WRKABE.js → chunk-A5ZOOZFB.js} +3 -3
  33. package/dist/{chunk-5NISHSBO.js → chunk-AAVWKNZW.js} +2 -2
  34. package/dist/{chunk-SOU42FGB.js → chunk-BIYRQQV6.js} +4 -4
  35. package/dist/{chunk-ILWQGTNH.js → chunk-BQ65SS5A.js} +2 -2
  36. package/dist/{chunk-CWFQTAD4.js → chunk-C5T5AFWN.js} +4 -4
  37. package/dist/chunk-CJORTUJ2.js +524 -0
  38. package/dist/chunk-CJORTUJ2.js.map +1 -0
  39. package/dist/{chunk-SYSKC237.js → chunk-COFPAMX6.js} +5 -5
  40. package/dist/{chunk-D5Y3HIC6.js → chunk-CZI2A4MQ.js} +3 -3
  41. package/dist/{chunk-KJF7EPUE.js → chunk-DKO2QFSA.js} +2 -2
  42. package/dist/{chunk-QFYVGJLI.js → chunk-DQU36Q7I.js} +2 -2
  43. package/dist/{chunk-NIUXQDWD.js → chunk-EGD5DXFT.js} +2 -2
  44. package/dist/{chunk-NJMKHRQI.js → chunk-EYVQHAGH.js} +267 -67
  45. package/dist/chunk-EYVQHAGH.js.map +1 -0
  46. package/dist/{chunk-KHQ3N5AB.js → chunk-F4OJZIWQ.js} +4 -4
  47. package/dist/{chunk-3OUCWHV6.js → chunk-FWPKCXTN.js} +2 -2
  48. package/dist/{chunk-QIVFGU2M.js → chunk-HOR4R722.js} +3 -3
  49. package/dist/{chunk-NP6EZT44.js → chunk-IQLVUT37.js} +2 -2
  50. package/dist/{chunk-4VCQH32J.js → chunk-JD3OZAI4.js} +2 -2
  51. package/dist/{chunk-J67BP5EP.js → chunk-KI6HAJWL.js} +3 -3
  52. package/dist/{chunk-AYNF7PVX.js → chunk-KIP6JLTF.js} +2 -2
  53. package/dist/{chunk-PW26DAXS.js → chunk-L2FE64BU.js} +3 -3
  54. package/dist/{chunk-QAWCVWCX.js → chunk-LX3CB26H.js} +4 -4
  55. package/dist/{chunk-VAK6NQAK.js → chunk-NSCVNK5K.js} +4 -4
  56. package/dist/{chunk-4YDZ7JPZ.js → chunk-NU6Q3FOR.js} +4 -4
  57. package/dist/chunk-NU6Q3FOR.js.map +1 -0
  58. package/dist/{chunk-3XZRRBFW.js → chunk-OHVFWCJP.js} +2 -2
  59. package/dist/{chunk-TEQGXA7L.js → chunk-PE4AQGFH.js} +4 -4
  60. package/dist/{chunk-UNQEWORI.js → chunk-TS26M2SB.js} +2 -2
  61. package/dist/{chunk-FNVFT4HZ.js → chunk-VU7SWWT5.js} +2 -2
  62. package/dist/{chunk-GZJ5JBED.js → chunk-WBAYSNUQ.js} +3 -3
  63. package/dist/{chunk-HHZ77DHM.js → chunk-WGHU7BLI.js} +2 -2
  64. package/dist/{chunk-GL3Z7LH7.js → chunk-X73VS74Y.js} +2 -2
  65. package/dist/{chunk-WIBHRONM.js → chunk-XWH4MXIU.js} +2 -2
  66. package/dist/{chunk-M6KXHRIA.js → chunk-YHPM5D7Y.js} +3 -3
  67. package/dist/{chunk-E3DIBDKA.js → chunk-YULZKK4F.js} +2 -2
  68. package/dist/{chunk-JWFNOD2T.js → chunk-Z4DO7YSI.js} +2 -2
  69. package/dist/{chunk-JPOQMXGT.js → chunk-ZNQYHJXX.js} +2 -2
  70. package/dist/consent/index.cjs.map +1 -1
  71. package/dist/consent/index.d.cts +6 -6
  72. package/dist/consent/index.d.ts +6 -6
  73. package/dist/consent/index.js +3 -3
  74. package/dist/{crypto-YXH6SAOW.js → crypto-QXQOHMHF.js} +3 -3
  75. package/dist/{delegation-K5ERUH6A.js → delegation-NIQ43IPU.js} +5 -5
  76. package/dist/derivations/index.cjs.map +1 -1
  77. package/dist/derivations/index.d.cts +7 -7
  78. package/dist/derivations/index.d.ts +7 -7
  79. package/dist/derivations/index.js +4 -4
  80. package/dist/{dev-unlock-BW0GNBEV.d.ts → dev-unlock-iAS8z9jc.d.ts} +1 -1
  81. package/dist/{dev-unlock-a7SOtaV0.d.cts → dev-unlock-nVkuRLLe.d.cts} +1 -1
  82. package/dist/executor-6ZDSDZ6V.js +8 -0
  83. package/dist/executor-HSSRXDOB.js +11 -0
  84. package/dist/executor-IDZDAFNH.js +8 -0
  85. package/dist/guards/index.cjs.map +1 -1
  86. package/dist/guards/index.d.cts +7 -7
  87. package/dist/guards/index.d.ts +7 -7
  88. package/dist/guards/index.js +3 -3
  89. package/dist/{hash-B0cLQcq_.d.cts → hash-Cv6byZs7.d.cts} +1 -1
  90. package/dist/{hash-uMNIAAW8.d.ts → hash-DHOnRarj.d.ts} +1 -1
  91. package/dist/history/index.cjs.map +1 -1
  92. package/dist/history/index.d.cts +7 -7
  93. package/dist/history/index.d.ts +7 -7
  94. package/dist/history/index.js +4 -4
  95. package/dist/i18n/index.cjs.map +1 -1
  96. package/dist/i18n/index.d.cts +6 -6
  97. package/dist/i18n/index.d.ts +6 -6
  98. package/dist/i18n/index.js +5 -5
  99. package/dist/{immutable-guard-B0h-ipLz.d.ts → immutable-guard-BehB1YGB.d.ts} +1 -1
  100. package/dist/{immutable-guard-BZIcYhYX.d.cts → immutable-guard-yBEOYmif.d.cts} +1 -1
  101. package/dist/{index-CUVOMtgg.d.cts → index-D95VK1Qy.d.cts} +11 -3
  102. package/dist/{index-Cqzp4tt9.d.ts → index-XNB2r6bX.d.ts} +11 -3
  103. package/dist/index.cjs +700 -78
  104. package/dist/index.cjs.map +1 -1
  105. package/dist/index.d.cts +145 -15
  106. package/dist/index.d.ts +145 -15
  107. package/dist/index.js +164 -48
  108. package/dist/index.js.map +1 -1
  109. package/dist/indexing/index.cjs +92 -31
  110. package/dist/indexing/index.cjs.map +1 -1
  111. package/dist/indexing/index.d.cts +3 -3
  112. package/dist/indexing/index.d.ts +3 -3
  113. package/dist/indexing/index.js +4 -4
  114. package/dist/issue-ADVS4OVP.js +12 -0
  115. package/dist/{lazy-builder-D5GU14TS.d.ts → lazy-builder-ChSqcF5t.d.ts} +1 -1
  116. package/dist/{lazy-builder-Ci5_YG73.d.cts → lazy-builder-eYZzLEL1.d.cts} +1 -1
  117. package/dist/{ledger-64TTQMRS.js → ledger-CWSE3BLF.js} +4 -4
  118. package/dist/materialized-views/index.cjs +2 -2
  119. package/dist/materialized-views/index.cjs.map +1 -1
  120. package/dist/materialized-views/index.d.cts +7 -7
  121. package/dist/materialized-views/index.d.ts +7 -7
  122. package/dist/materialized-views/index.js +7 -7
  123. package/dist/noydb-GZGFBA4E.js +35 -0
  124. package/dist/overlay-views/index.cjs.map +1 -1
  125. package/dist/overlay-views/index.d.cts +7 -7
  126. package/dist/overlay-views/index.d.ts +7 -7
  127. package/dist/overlay-views/index.js +4 -4
  128. package/dist/periods/index.cjs.map +1 -1
  129. package/dist/periods/index.d.cts +6 -6
  130. package/dist/periods/index.d.ts +6 -6
  131. package/dist/periods/index.js +4 -4
  132. package/dist/{predicate-Bt5ft-9c.d.cts → predicate-BmhBSPCH.d.cts} +59 -2
  133. package/dist/{predicate-Bt5ft-9c.d.ts → predicate-BmhBSPCH.d.ts} +59 -2
  134. package/dist/{public-envelope-MHG6YVXW.js → public-envelope-SYHEYQ3X.js} +3 -3
  135. package/dist/query/index.cjs +580 -195
  136. package/dist/query/index.cjs.map +1 -1
  137. package/dist/query/index.d.cts +3 -3
  138. package/dist/query/index.d.ts +3 -3
  139. package/dist/query/index.js +6 -6
  140. package/dist/{registry-PV4G3OPA.js → registry-DK5YWAAA.js} +3 -3
  141. package/dist/registry-IUZQVVBB.js +8 -0
  142. package/dist/registry-XGLNADIE.js +8 -0
  143. package/dist/{revoke-5BOLVJ3N.js → revoke-ZDFKMR5E.js} +5 -5
  144. package/dist/session/index.cjs.map +1 -1
  145. package/dist/session/index.d.cts +7 -7
  146. package/dist/session/index.d.ts +7 -7
  147. package/dist/session/index.js +3 -3
  148. package/dist/shadow/index.cjs.map +1 -1
  149. package/dist/shadow/index.d.cts +6 -6
  150. package/dist/shadow/index.d.ts +6 -6
  151. package/dist/shadow/index.js +2 -2
  152. package/dist/{signer-GRIYBA22.js → signer-P5D7Y72U.js} +4 -4
  153. package/dist/snapshots/index.cjs.map +1 -1
  154. package/dist/snapshots/index.d.cts +6 -6
  155. package/dist/snapshots/index.d.ts +6 -6
  156. package/dist/snapshots/index.js +3 -3
  157. package/dist/{stale-LZYMMDDS.js → stale-JH67FU57.js} +2 -2
  158. package/dist/{state-vault-QFJWU23A.js → state-vault-TMXZRTY5.js} +3 -3
  159. package/dist/store/index.cjs.map +1 -1
  160. package/dist/store/index.d.cts +6 -6
  161. package/dist/store/index.d.ts +6 -6
  162. package/dist/store/index.js +2 -2
  163. package/dist/{strategy-CrS7PnbE.d.ts → strategy-CbneC7bS.d.cts} +1 -1
  164. package/dist/{strategy-CrS7PnbE.d.cts → strategy-CbneC7bS.d.ts} +1 -1
  165. package/dist/sync/index.cjs.map +1 -1
  166. package/dist/sync/index.d.cts +5 -5
  167. package/dist/sync/index.d.ts +5 -5
  168. package/dist/sync/index.js +3 -3
  169. package/dist/team/index.cjs.map +1 -1
  170. package/dist/team/index.d.cts +6 -6
  171. package/dist/team/index.d.ts +6 -6
  172. package/dist/team/index.js +7 -7
  173. package/dist/tx/index.cjs.map +1 -1
  174. package/dist/tx/index.d.cts +6 -6
  175. package/dist/tx/index.d.ts +6 -6
  176. package/dist/tx/index.js +3 -3
  177. package/dist/{types-pax34sec.d.ts → types-4t1-tWS4.d.ts} +77 -9
  178. package/dist/{types-CDwSSXiI.d.cts → types-BpPV5uyy.d.cts} +77 -9
  179. package/dist/{ulid-7bCSgIgb.d.cts → ulid-CiPrpGqm.d.cts} +1 -1
  180. package/dist/{ulid-C_t4hL3d.d.ts → ulid-DAfenvFd.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-UO4YUZOG.js → vault-group-KOM7QRJG.js} +125 -11
  184. package/dist/vault-group-KOM7QRJG.js.map +1 -0
  185. package/dist/{with-derivation-D8wFlb6V.d.cts → with-derivation-DBqJB3dQ.d.cts} +1 -1
  186. package/dist/{with-derivation-BjdOxUBn.d.ts → with-derivation-OK9M2sJE.d.ts} +1 -1
  187. package/dist/{with-materialized-view-DJb-HO65.d.ts → with-materialized-view-Dt-ufPWQ.d.ts} +1 -1
  188. package/dist/{with-materialized-view-5QMF1rS_.d.cts → with-materialized-view-NzuxYPDF.d.cts} +1 -1
  189. package/dist/{with-overlayed-view-DDNflPvC.d.cts → with-overlayed-view-CC0_ocy-.d.cts} +1 -1
  190. package/dist/{with-overlayed-view-CkqTefbz.d.ts → with-overlayed-view-eDvMs6LO.d.ts} +1 -1
  191. package/package.json +3 -3
  192. package/dist/chunk-4YDZ7JPZ.js.map +0 -1
  193. package/dist/chunk-NJMKHRQI.js.map +0 -1
  194. package/dist/chunk-P5MW7BG2.js.map +0 -1
  195. package/dist/chunk-TV3YZ35S.js +0 -90
  196. package/dist/chunk-TV3YZ35S.js.map +0 -1
  197. package/dist/chunk-YWBHS25M.js.map +0 -1
  198. package/dist/executor-AVJ7UEWA.js +0 -8
  199. package/dist/executor-IQO3KGXQ.js +0 -11
  200. package/dist/executor-VT7TKGE4.js +0 -8
  201. package/dist/issue-ZH27C23Y.js +0 -12
  202. package/dist/noydb-O76SKBST.js +0 -35
  203. package/dist/registry-2PKBQDCH.js +0 -8
  204. package/dist/registry-4VXFKCBJ.js +0 -8
  205. package/dist/vault-group-UO4YUZOG.js.map +0 -1
  206. /package/dist/{chunk-SJ24GHID.js.map → chunk-4TBBMHVC.js.map} +0 -0
  207. /package/dist/{chunk-HQXOEWLZ.js.map → chunk-56DJ7JVK.js.map} +0 -0
  208. /package/dist/{chunk-KKB42D3Q.js.map → chunk-5LQG6ZO2.js.map} +0 -0
  209. /package/dist/{chunk-TDECYU4Y.js.map → chunk-6AJBSQU4.js.map} +0 -0
  210. /package/dist/{chunk-O2JW656W.js.map → chunk-6RR3MNMG.js.map} +0 -0
  211. /package/dist/{chunk-7TEI2K2A.js.map → chunk-7HT2MEZ5.js.map} +0 -0
  212. /package/dist/{chunk-WQKZIQIL.js.map → chunk-7PS7EOCF.js.map} +0 -0
  213. /package/dist/{chunk-C3WRKABE.js.map → chunk-A5ZOOZFB.js.map} +0 -0
  214. /package/dist/{chunk-5NISHSBO.js.map → chunk-AAVWKNZW.js.map} +0 -0
  215. /package/dist/{chunk-SOU42FGB.js.map → chunk-BIYRQQV6.js.map} +0 -0
  216. /package/dist/{chunk-ILWQGTNH.js.map → chunk-BQ65SS5A.js.map} +0 -0
  217. /package/dist/{chunk-CWFQTAD4.js.map → chunk-C5T5AFWN.js.map} +0 -0
  218. /package/dist/{chunk-SYSKC237.js.map → chunk-COFPAMX6.js.map} +0 -0
  219. /package/dist/{chunk-D5Y3HIC6.js.map → chunk-CZI2A4MQ.js.map} +0 -0
  220. /package/dist/{chunk-KJF7EPUE.js.map → chunk-DKO2QFSA.js.map} +0 -0
  221. /package/dist/{chunk-QFYVGJLI.js.map → chunk-DQU36Q7I.js.map} +0 -0
  222. /package/dist/{chunk-NIUXQDWD.js.map → chunk-EGD5DXFT.js.map} +0 -0
  223. /package/dist/{chunk-KHQ3N5AB.js.map → chunk-F4OJZIWQ.js.map} +0 -0
  224. /package/dist/{chunk-3OUCWHV6.js.map → chunk-FWPKCXTN.js.map} +0 -0
  225. /package/dist/{chunk-QIVFGU2M.js.map → chunk-HOR4R722.js.map} +0 -0
  226. /package/dist/{chunk-NP6EZT44.js.map → chunk-IQLVUT37.js.map} +0 -0
  227. /package/dist/{chunk-4VCQH32J.js.map → chunk-JD3OZAI4.js.map} +0 -0
  228. /package/dist/{chunk-J67BP5EP.js.map → chunk-KI6HAJWL.js.map} +0 -0
  229. /package/dist/{chunk-AYNF7PVX.js.map → chunk-KIP6JLTF.js.map} +0 -0
  230. /package/dist/{chunk-PW26DAXS.js.map → chunk-L2FE64BU.js.map} +0 -0
  231. /package/dist/{chunk-QAWCVWCX.js.map → chunk-LX3CB26H.js.map} +0 -0
  232. /package/dist/{chunk-VAK6NQAK.js.map → chunk-NSCVNK5K.js.map} +0 -0
  233. /package/dist/{chunk-3XZRRBFW.js.map → chunk-OHVFWCJP.js.map} +0 -0
  234. /package/dist/{chunk-TEQGXA7L.js.map → chunk-PE4AQGFH.js.map} +0 -0
  235. /package/dist/{chunk-UNQEWORI.js.map → chunk-TS26M2SB.js.map} +0 -0
  236. /package/dist/{chunk-FNVFT4HZ.js.map → chunk-VU7SWWT5.js.map} +0 -0
  237. /package/dist/{chunk-GZJ5JBED.js.map → chunk-WBAYSNUQ.js.map} +0 -0
  238. /package/dist/{chunk-HHZ77DHM.js.map → chunk-WGHU7BLI.js.map} +0 -0
  239. /package/dist/{chunk-GL3Z7LH7.js.map → chunk-X73VS74Y.js.map} +0 -0
  240. /package/dist/{chunk-WIBHRONM.js.map → chunk-XWH4MXIU.js.map} +0 -0
  241. /package/dist/{chunk-M6KXHRIA.js.map → chunk-YHPM5D7Y.js.map} +0 -0
  242. /package/dist/{chunk-E3DIBDKA.js.map → chunk-YULZKK4F.js.map} +0 -0
  243. /package/dist/{chunk-JWFNOD2T.js.map → chunk-Z4DO7YSI.js.map} +0 -0
  244. /package/dist/{chunk-JPOQMXGT.js.map → chunk-ZNQYHJXX.js.map} +0 -0
  245. /package/dist/{crypto-YXH6SAOW.js.map → crypto-QXQOHMHF.js.map} +0 -0
  246. /package/dist/{delegation-K5ERUH6A.js.map → delegation-NIQ43IPU.js.map} +0 -0
  247. /package/dist/{executor-AVJ7UEWA.js.map → executor-6ZDSDZ6V.js.map} +0 -0
  248. /package/dist/{executor-IQO3KGXQ.js.map → executor-HSSRXDOB.js.map} +0 -0
  249. /package/dist/{executor-VT7TKGE4.js.map → executor-IDZDAFNH.js.map} +0 -0
  250. /package/dist/{issue-ZH27C23Y.js.map → issue-ADVS4OVP.js.map} +0 -0
  251. /package/dist/{ledger-64TTQMRS.js.map → ledger-CWSE3BLF.js.map} +0 -0
  252. /package/dist/{noydb-O76SKBST.js.map → noydb-GZGFBA4E.js.map} +0 -0
  253. /package/dist/{public-envelope-MHG6YVXW.js.map → public-envelope-SYHEYQ3X.js.map} +0 -0
  254. /package/dist/{registry-2PKBQDCH.js.map → registry-DK5YWAAA.js.map} +0 -0
  255. /package/dist/{registry-4VXFKCBJ.js.map → registry-IUZQVVBB.js.map} +0 -0
  256. /package/dist/{registry-PV4G3OPA.js.map → registry-XGLNADIE.js.map} +0 -0
  257. /package/dist/{revoke-5BOLVJ3N.js.map → revoke-ZDFKMR5E.js.map} +0 -0
  258. /package/dist/{signer-GRIYBA22.js.map → signer-P5D7Y72U.js.map} +0 -0
  259. /package/dist/{stale-LZYMMDDS.js.map → stale-JH67FU57.js.map} +0 -0
  260. /package/dist/{state-vault-QFJWU23A.js.map → state-vault-TMXZRTY5.js.map} +0 -0
package/dist/index.cjs CHANGED
@@ -46,7 +46,7 @@ var init_types = __esm({
46
46
  });
47
47
 
48
48
  // src/errors.ts
49
- var NoydbError, DecryptionError, TamperedError, InvalidKeyError, KeyringCorruptError, NoAccessError, ReadOnlyError, ReadOnlyAtInstantError, ReadOnlyFrameError, PermissionDeniedError, ExportCapabilityError, KeyringExpiredError, ImportCapabilityError, StoreCapabilityError, PrivilegeEscalationError, ReservedVaultNameError, PeriodClosedError, RecordLockedError, FieldFrozenError, InvariantError, AmendmentForbiddenError, DirectoryDisabledError, TierNotGrantedError, ElevationExpiredError, AlreadyElevatedError, TierDemoteDeniedError, DelegationTargetMissingError, ConflictError, LedgerContentionError, SequenceContentionError, SequenceOfflineError, NumberingUncertaintyError, BundleVersionConflictError, NetworkError, NotFoundError, ValidationError, SchemaValidationError, SchemaUpdateError, NonAdditiveSchemaChangeError, SchemaLockedError, SchemaFenceError, MigrationRequiredError, QuiesceTimeoutError, GroupCardinalityError, IndexRequiredError, UniqueConstraintError, UnsupportedIndexOptionError, IndexWriteFailureError, BundleIntegrityError, BundleSealMismatchError, ReservedCollectionNameError, DictKeyMissingError, DictKeyInUseError, MissingTranslationError, LocaleNotSpecifiedError, ScriptViolationError, TranslatorNotConfiguredError, BackupLedgerError, BackupCorruptedError, AttestationError, SessionExpiredError, SessionNotFoundError, SessionPolicyError, JoinTooLargeError, CrossJoinTooLargeError, CrossJoinSourceUnknownError, DanglingReferenceError, FilenameSanitizationError, PathEscapeError, DerivationCycleError, DerivationDepthError, DerivationOutputUnknownError, DerivationOutputShapeError, DerivationCapExceededError, MaterializedViewCycleError, MaterializedViewSourceUnknownError, MaterializedViewTooLargeError, MaterializedViewConfigError, OverlayBaseIsVirtualError, OverlayCollectionUnavailableError, OverlayNameCollisionError, OverlayIdMismatchError, SnapshotNotFoundError, UnknownShardError, ShardProvisioningError, VaultTemplateNotFoundError;
49
+ var NoydbError, DecryptionError, TamperedError, InvalidKeyError, KeyringCorruptError, NoAccessError, ReadOnlyError, ReadOnlyAtInstantError, ReadOnlyFrameError, PermissionDeniedError, ExportCapabilityError, KeyringExpiredError, ImportCapabilityError, StoreCapabilityError, PrivilegeEscalationError, ReservedVaultNameError, PeriodClosedError, RecordLockedError, FieldFrozenError, InvariantError, AmendmentForbiddenError, DirectoryDisabledError, TierNotGrantedError, ElevationExpiredError, AlreadyElevatedError, TierDemoteDeniedError, DelegationTargetMissingError, ConflictError, LedgerContentionError, SequenceContentionError, SequenceOfflineError, NumberingUncertaintyError, BundleVersionConflictError, NetworkError, NotFoundError, ValidationError, SchemaValidationError, SchemaUpdateError, NonAdditiveSchemaChangeError, SchemaLockedError, SchemaFenceError, MigrationRequiredError, QuiesceTimeoutError, GroupCardinalityError, IndexRequiredError, UniqueConstraintError, UnsupportedIndexOptionError, IndexWriteFailureError, BundleIntegrityError, BundleSealMismatchError, ReservedCollectionNameError, DictKeyMissingError, DictKeyInUseError, MissingTranslationError, LocaleNotSpecifiedError, ScriptViolationError, TranslatorNotConfiguredError, BackupLedgerError, BackupCorruptedError, AttestationError, SessionExpiredError, SessionNotFoundError, SessionPolicyError, JoinTooLargeError, CrossJoinTooLargeError, CrossJoinSourceUnknownError, DanglingReferenceError, FilenameSanitizationError, PathEscapeError, DerivationCycleError, DerivationDepthError, DerivationOutputUnknownError, DerivationOutputShapeError, DerivationCapExceededError, MaterializedViewCycleError, MaterializedViewSourceUnknownError, MaterializedViewTooLargeError, MaterializedViewConfigError, OverlayBaseIsVirtualError, OverlayCollectionUnavailableError, OverlayNameCollisionError, OverlayIdMismatchError, SnapshotNotFoundError, UnknownShardError, ShardProvisioningError, CrossShardJoinError, VaultTemplateNotFoundError;
50
50
  var init_errors = __esm({
51
51
  "src/errors.ts"() {
52
52
  "use strict";
@@ -988,6 +988,12 @@ Resolutions:
988
988
  this.vaultId = vaultId;
989
989
  }
990
990
  };
991
+ CrossShardJoinError = class extends NoydbError {
992
+ constructor(message) {
993
+ super("CROSS_SHARD_JOIN", message);
994
+ this.name = "CrossShardJoinError";
995
+ }
996
+ };
991
997
  VaultTemplateNotFoundError = class extends NoydbError {
992
998
  templateName;
993
999
  constructor(templateName) {
@@ -2391,6 +2397,30 @@ function parseToScaledInt(input, scale, rounding) {
2391
2397
  }
2392
2398
  return { ok: true, value: negative && magnitude !== 0n ? -magnitude : magnitude };
2393
2399
  }
2400
+ function decimalScaleOf(input) {
2401
+ const s = toCanonicalDecimalString(input);
2402
+ if (s === null) return null;
2403
+ const dot = s.indexOf(".");
2404
+ return dot === -1 ? 0 : s.length - dot - 1;
2405
+ }
2406
+ function rescaleScaledInt(value, fromScale, toScale, rounding = "half-up") {
2407
+ if (toScale >= fromScale) return value * 10n ** BigInt(toScale - fromScale);
2408
+ const drop = fromScale - toScale;
2409
+ const negative = value < 0n;
2410
+ const absStr = (negative ? -value : value).toString().padStart(drop + 1, "0");
2411
+ const keptStr = absStr.slice(0, absStr.length - drop);
2412
+ const tail = absStr.slice(absStr.length - drop);
2413
+ let magnitude = BigInt(keptStr);
2414
+ if (!/^0+$/.test(tail)) {
2415
+ const lastKeptDigit = Number(keptStr[keptStr.length - 1]);
2416
+ const firstDiscarded = Number(tail[0]);
2417
+ const hasMoreNonZeroAfterFirst = /[1-9]/.test(tail.slice(1));
2418
+ if (shouldRoundUp(negative, lastKeptDigit, firstDiscarded, hasMoreNonZeroAfterFirst, rounding)) {
2419
+ magnitude += 1n;
2420
+ }
2421
+ }
2422
+ return negative && magnitude !== 0n ? -magnitude : magnitude;
2423
+ }
2394
2424
  function formatScaledInt(value, scale) {
2395
2425
  const negative = value < 0n;
2396
2426
  const abs = (negative ? -value : value).toString();
@@ -2610,6 +2640,146 @@ var init_tiers = __esm({
2610
2640
  }
2611
2641
  });
2612
2642
 
2643
+ // src/money/where.ts
2644
+ function isMoneyValueObject2(v) {
2645
+ return typeof v === "object" && v !== null && "currency" in v;
2646
+ }
2647
+ function parseOperand(field, raw, desc) {
2648
+ let amount;
2649
+ let currency;
2650
+ if (desc.mode === "fixed") {
2651
+ currency = desc.fixedCurrency;
2652
+ amount = raw;
2653
+ } else if (isMoneyValueObject2(raw)) {
2654
+ currency = String(raw.currency);
2655
+ amount = raw.amount;
2656
+ } else {
2657
+ const sole = desc.soleCurrency();
2658
+ if (sole === void 0) {
2659
+ throw new MoneyUnsupportedError(
2660
+ `where("${field}"): field is multi-currency \u2014 compare against { amount, currency }, not a bare amount`
2661
+ );
2662
+ }
2663
+ currency = sole;
2664
+ amount = raw;
2665
+ }
2666
+ if (typeof amount !== "number" && typeof amount !== "string") {
2667
+ throw new MoneyUnsupportedError(
2668
+ `where("${field}"): operand ${JSON.stringify(raw)} is not a money amount`
2669
+ );
2670
+ }
2671
+ const r = parseToScaledInt(amount, desc.scaleFor(currency), desc.rounding);
2672
+ if (!r.ok) {
2673
+ throw new MoneyUnsupportedError(
2674
+ `where("${field}"): operand ${JSON.stringify(amount)} is not a finite decimal`
2675
+ );
2676
+ }
2677
+ return { scaled: r.value.toString(), currency };
2678
+ }
2679
+ function moneyFieldClause(field, op, value, desc) {
2680
+ switch (op) {
2681
+ case "==":
2682
+ case "!=":
2683
+ case "<":
2684
+ case "<=":
2685
+ case ">":
2686
+ case ">=": {
2687
+ const e = parseOperand(field, value, desc);
2688
+ return withMoney(field, op, value, desc, [e]);
2689
+ }
2690
+ case "between": {
2691
+ if (!Array.isArray(value) || value.length !== 2) {
2692
+ throw new MoneyUnsupportedError(`where("${field}"): 'between' needs a [lo, hi] tuple`);
2693
+ }
2694
+ const lo = parseOperand(field, value[0], desc);
2695
+ const hi = parseOperand(field, value[1], desc);
2696
+ if (lo.currency !== hi.currency) {
2697
+ throw new MoneyUnsupportedError(
2698
+ `where("${field}"): 'between' bounds mix currencies (${lo.currency} vs ${hi.currency})`
2699
+ );
2700
+ }
2701
+ return withMoney(field, op, value, desc, [lo, hi]);
2702
+ }
2703
+ case "in": {
2704
+ if (!Array.isArray(value)) {
2705
+ throw new MoneyUnsupportedError(`where("${field}"): 'in' needs an array of amounts`);
2706
+ }
2707
+ return withMoney(field, op, value, desc, value.map((v) => parseOperand(field, v, desc)));
2708
+ }
2709
+ default:
2710
+ throw new MoneyUnsupportedError(
2711
+ `where("${field}"): operator '${op}' is not supported on a money field`
2712
+ );
2713
+ }
2714
+ }
2715
+ function withMoney(field, op, originalValue, desc, entries) {
2716
+ const money2 = { mode: desc.mode, entries };
2717
+ const value = desc.mode !== "fixed" ? originalValue : entries.length === 1 && op !== "in" && op !== "between" ? entries[0].scaled : entries.map((e) => e.scaled);
2718
+ return { type: "field", field, op, value, money: money2 };
2719
+ }
2720
+ function readStored(actual, operand) {
2721
+ let amount;
2722
+ let currency;
2723
+ if (operand.mode === "fixed") {
2724
+ if (typeof actual !== "string" && typeof actual !== "number") return null;
2725
+ amount = actual;
2726
+ currency = operand.entries[0]?.currency ?? "";
2727
+ } else {
2728
+ if (!isMoneyValueObject2(actual)) return null;
2729
+ if (typeof actual.currency !== "string") return null;
2730
+ amount = actual.amount;
2731
+ currency = actual.currency;
2732
+ }
2733
+ if (typeof amount !== "string" && typeof amount !== "number") return null;
2734
+ try {
2735
+ return { scaled: BigInt(amount).toString(), currency };
2736
+ } catch {
2737
+ return null;
2738
+ }
2739
+ }
2740
+ function evaluateMoneyClause(actual, op, operand) {
2741
+ const stored = readStored(actual, operand);
2742
+ if (stored === null) return op === "!=";
2743
+ const a = BigInt(stored.scaled);
2744
+ if (op === "in") {
2745
+ return operand.entries.some(
2746
+ (e2) => e2.currency === stored.currency && BigInt(e2.scaled) === a
2747
+ );
2748
+ }
2749
+ if (op === "between") {
2750
+ const [lo, hi] = operand.entries;
2751
+ if (!lo || !hi || lo.currency !== stored.currency) return false;
2752
+ return a >= BigInt(lo.scaled) && a <= BigInt(hi.scaled);
2753
+ }
2754
+ const e = operand.entries[0];
2755
+ if (!e) return false;
2756
+ if (e.currency !== stored.currency) return op === "!=";
2757
+ const b = BigInt(e.scaled);
2758
+ switch (op) {
2759
+ case "==":
2760
+ return a === b;
2761
+ case "!=":
2762
+ return a !== b;
2763
+ case "<":
2764
+ return a < b;
2765
+ case "<=":
2766
+ return a <= b;
2767
+ case ">":
2768
+ return a > b;
2769
+ case ">=":
2770
+ return a >= b;
2771
+ default:
2772
+ return false;
2773
+ }
2774
+ }
2775
+ var init_where = __esm({
2776
+ "src/money/where.ts"() {
2777
+ "use strict";
2778
+ init_fixed_point();
2779
+ init_descriptor();
2780
+ }
2781
+ });
2782
+
2613
2783
  // src/query/predicate.ts
2614
2784
  function readPath(record, path) {
2615
2785
  if (record === null || record === void 0) return void 0;
@@ -2627,6 +2797,7 @@ function readPath(record, path) {
2627
2797
  function evaluateFieldClause(record, clause) {
2628
2798
  const actual = readPath(record, clause.field);
2629
2799
  const { op, value } = clause;
2800
+ if (clause.money) return evaluateMoneyClause(actual, op, clause.money);
2630
2801
  switch (op) {
2631
2802
  case "==":
2632
2803
  return actual === value;
@@ -2667,14 +2838,14 @@ function isComparable(a, b) {
2667
2838
  if (a instanceof Date && b instanceof Date) return true;
2668
2839
  return false;
2669
2840
  }
2670
- function evaluateClause(record, clause) {
2841
+ function evaluateClause(record, clause, fnRecord) {
2671
2842
  switch (clause.type) {
2672
2843
  case "field":
2673
2844
  return evaluateFieldClause(record, clause);
2674
2845
  case "filter":
2675
- return clause.fn(record);
2846
+ return clause.fn(fnRecord !== void 0 ? fnRecord : record);
2676
2847
  case "wherePredicate":
2677
- return clause.fn(record, clause.ctx);
2848
+ return clause.fn(fnRecord !== void 0 ? fnRecord : record, clause.ctx);
2678
2849
  case "crossJoin":
2679
2850
  throw new Error(
2680
2851
  `evaluateClause: 'crossJoin' clauses are expansion primitives and are not evaluated per-record. This is a query planner routing error \u2014 crossJoin clauses must be extracted from the clause list before calling evaluateClause or filterRecords.`
@@ -2682,20 +2853,28 @@ function evaluateClause(record, clause) {
2682
2853
  case "group":
2683
2854
  if (clause.op === "and") {
2684
2855
  for (const child of clause.clauses) {
2685
- if (!evaluateClause(record, child)) return false;
2856
+ if (!evaluateClause(record, child, fnRecord)) return false;
2686
2857
  }
2687
2858
  return true;
2688
2859
  } else {
2689
2860
  for (const child of clause.clauses) {
2690
- if (evaluateClause(record, child)) return true;
2861
+ if (evaluateClause(record, child, fnRecord)) return true;
2691
2862
  }
2692
2863
  return false;
2693
2864
  }
2694
2865
  }
2695
2866
  }
2867
+ function hasFnClause(clauses) {
2868
+ for (const c of clauses) {
2869
+ if (c.type === "filter" || c.type === "wherePredicate") return true;
2870
+ if (c.type === "group" && hasFnClause(c.clauses)) return true;
2871
+ }
2872
+ return false;
2873
+ }
2696
2874
  var init_predicate = __esm({
2697
2875
  "src/query/predicate.ts"() {
2698
2876
  "use strict";
2877
+ init_where();
2699
2878
  }
2700
2879
  });
2701
2880
 
@@ -4619,6 +4798,54 @@ var init_classify_skip = __esm({
4619
4798
  }
4620
4799
  });
4621
4800
 
4801
+ // src/federation/cross-shard-join.ts
4802
+ function coerceKey(value) {
4803
+ if (value === null || value === void 0) return null;
4804
+ if (typeof value === "string") return value;
4805
+ if (typeof value === "number" || typeof value === "bigint") return String(value);
4806
+ return null;
4807
+ }
4808
+ function warnOnceBroadcastMiss(field, as, key) {
4809
+ const dedup = `${field}\u2192${as}:${key}`;
4810
+ if (warnedBroadcastKeys.has(dedup)) return;
4811
+ warnedBroadcastKeys.add(dedup);
4812
+ console.warn(
4813
+ `[noy-db] broadcastJoin: no "${as}" dimension row for ${field}="${key}". Attaching null. Use mode: 'cascade' to silence.`
4814
+ );
4815
+ }
4816
+ async function applyBroadcastLegs(rows, legs) {
4817
+ if (legs.length === 0) return [...rows];
4818
+ const indexes = [];
4819
+ for (const leg of legs) {
4820
+ const map = /* @__PURE__ */ new Map();
4821
+ for (const rec of await leg.from.list()) {
4822
+ const k = coerceKey(readPath(rec, leg.on));
4823
+ if (k !== null && !map.has(k)) map.set(k, rec);
4824
+ }
4825
+ indexes.push({ leg, map });
4826
+ }
4827
+ return rows.map((row) => {
4828
+ const out = { ...row };
4829
+ for (const { leg, map } of indexes) {
4830
+ const key = coerceKey(readPath(row, leg.field));
4831
+ const match = key === null ? null : map.get(key) ?? null;
4832
+ if (match === null && leg.mode === "warn") {
4833
+ warnOnceBroadcastMiss(leg.field, leg.as, key ?? "<null>");
4834
+ }
4835
+ out[leg.as] = match;
4836
+ }
4837
+ return out;
4838
+ });
4839
+ }
4840
+ var warnedBroadcastKeys;
4841
+ var init_cross_shard_join = __esm({
4842
+ "src/federation/cross-shard-join.ts"() {
4843
+ "use strict";
4844
+ init_predicate();
4845
+ warnedBroadcastKeys = /* @__PURE__ */ new Set();
4846
+ }
4847
+ });
4848
+
4622
4849
  // src/federation/cross-vault-live.ts
4623
4850
  var CrossVaultLive;
4624
4851
  var init_cross_vault_live = __esm({
@@ -4847,6 +5074,7 @@ var init_vault_group = __esm({
4847
5074
  init_errors();
4848
5075
  init_constants();
4849
5076
  init_classify_skip();
5077
+ init_cross_shard_join();
4850
5078
  init_cross_vault_live();
4851
5079
  init_aggregate_across();
4852
5080
  SHARD_SEPARATOR = "--";
@@ -5010,31 +5238,89 @@ var init_vault_group = __esm({
5010
5238
  }
5011
5239
  };
5012
5240
  ShardedQuery = class _ShardedQuery {
5013
- constructor(group, collectionName, clauses) {
5241
+ constructor(group, collectionName, clauses, coPartitionedLegs = [], broadcastLegs = []) {
5014
5242
  this.group = group;
5015
5243
  this.collectionName = collectionName;
5016
5244
  this.clauses = clauses;
5245
+ this.coPartitionedLegs = coPartitionedLegs;
5246
+ this.broadcastLegs = broadcastLegs;
5017
5247
  }
5018
5248
  group;
5019
5249
  collectionName;
5020
5250
  clauses;
5251
+ coPartitionedLegs;
5252
+ broadcastLegs;
5021
5253
  where(field, op, value) {
5022
- return new _ShardedQuery(this.group, this.collectionName, [
5023
- ...this.clauses,
5024
- { field, op, value }
5025
- ]);
5254
+ return new _ShardedQuery(
5255
+ this.group,
5256
+ this.collectionName,
5257
+ [...this.clauses, { field, op, value }],
5258
+ this.coPartitionedLegs,
5259
+ this.broadcastLegs
5260
+ );
5261
+ }
5262
+ /** Co-partitioned join: each shard joins its own same-vault right collection (resolved via ref()), then union. */
5263
+ crossShardJoin(field, opts) {
5264
+ const leg = { field, as: opts.as, maxRows: opts.maxRows, strategy: opts.strategy };
5265
+ return new _ShardedQuery(
5266
+ this.group,
5267
+ this.collectionName,
5268
+ this.clauses,
5269
+ [...this.coPartitionedLegs, leg],
5270
+ this.broadcastLegs
5271
+ );
5272
+ }
5273
+ /** Broadcast dimension join: enrich every merged row from a single shared collection. */
5274
+ broadcastJoin(field, opts) {
5275
+ const leg = {
5276
+ field,
5277
+ as: opts.as,
5278
+ from: opts.from,
5279
+ on: opts.on ?? "id",
5280
+ mode: opts.mode ?? "warn"
5281
+ };
5282
+ return new _ShardedQuery(
5283
+ this.group,
5284
+ this.collectionName,
5285
+ this.clauses,
5286
+ this.coPartitionedLegs,
5287
+ [...this.broadcastLegs, leg]
5288
+ );
5026
5289
  }
5027
5290
  /** @internal — fan out the where-filtered records across eligible shards. */
5028
5291
  async fanoutRecords(options = {}) {
5029
5292
  const { eligible, skipped } = await this.group.resolveEligible(options);
5293
+ const probeRow = eligible[0];
5294
+ if (this.coPartitionedLegs.length > 0 && probeRow) {
5295
+ const probe = await this.group.openShard(probeRow.partitionKey);
5296
+ this.group.template.configure(probe);
5297
+ for (const leg of this.coPartitionedLegs) {
5298
+ if (!probe.resolveRef(this.collectionName, leg.field)) {
5299
+ throw new CrossShardJoinError(
5300
+ `crossShardJoin("${leg.field}"): no ref() declared for "${leg.field}" on collection "${this.collectionName}" in template "${this.group.sharding.vaultTemplate}". Add refs: { ${leg.field}: ref('<target>') } to the template's collection options.`
5301
+ );
5302
+ }
5303
+ }
5304
+ }
5030
5305
  const across = await this.group.db.queryAcross(
5031
5306
  eligible.map((r) => r.vaultId),
5032
5307
  async (vault) => {
5033
5308
  this.group.template.configure(vault);
5034
5309
  const coll = vault.collection(this.collectionName);
5035
5310
  await coll.list();
5311
+ for (const leg of this.coPartitionedLegs) {
5312
+ const desc = vault.resolveRef(this.collectionName, leg.field);
5313
+ if (desc) await vault.collection(desc.target).list();
5314
+ }
5036
5315
  let q = coll.query();
5037
5316
  for (const c of this.clauses) q = q.where(c.field, c.op, c.value);
5317
+ for (const leg of this.coPartitionedLegs) {
5318
+ q = q.join(leg.field, {
5319
+ as: leg.as,
5320
+ ...leg.maxRows !== void 0 ? { maxRows: leg.maxRows } : {},
5321
+ ...leg.strategy ? { strategy: leg.strategy } : {}
5322
+ });
5323
+ }
5038
5324
  return q.toArray();
5039
5325
  },
5040
5326
  { concurrency: options.concurrency ?? 1, create: false }
@@ -5046,10 +5332,11 @@ var init_vault_group = __esm({
5046
5332
  }
5047
5333
  return { records: results, skippedVaults: skipped };
5048
5334
  }
5049
- /** Fan out across eligible shards and merge results. */
5335
+ /** Fan out across eligible shards, merge, then apply any broadcast dimension legs. */
5050
5336
  async toArray(options = {}) {
5051
5337
  const { records, skippedVaults } = await this.fanoutRecords(options);
5052
- return { results: records, skippedVaults };
5338
+ const results = await applyBroadcastLegs(records, this.broadcastLegs);
5339
+ return { results, skippedVaults };
5053
5340
  }
5054
5341
  /** @internal — build the change-subscription + relevance binding for this query's group+collection. */
5055
5342
  liveBinding() {
@@ -5063,8 +5350,17 @@ var init_vault_group = __esm({
5063
5350
  isRelevant: (e) => e.collection === collectionName && e.vault.startsWith(`${group.name}--`)
5064
5351
  };
5065
5352
  }
5353
+ /** @internal — joined queries don't support reactive/aggregate surfaces in v1. */
5354
+ assertNoJoinLegs(surface) {
5355
+ if (this.coPartitionedLegs.length || this.broadcastLegs.length) {
5356
+ throw new CrossShardJoinError(
5357
+ `${surface}() is not supported on a ShardedQuery with crossShardJoin/broadcastJoin legs in v1. Use toArray() for joined cross-shard queries.`
5358
+ );
5359
+ }
5360
+ }
5066
5361
  /** Returns a reactive cross-shard live query — a facade over CrossVaultLive. */
5067
5362
  live(options = {}) {
5363
+ this.assertNoJoinLegs("live");
5068
5364
  const bind = this.liveBinding();
5069
5365
  const core = new CrossVaultLive({
5070
5366
  ...bind,
@@ -5092,10 +5388,12 @@ var init_vault_group = __esm({
5092
5388
  }
5093
5389
  /** One-shot distributed aggregate — central reduce over all shard records. */
5094
5390
  aggregate(spec) {
5391
+ this.assertNoJoinLegs("aggregate");
5095
5392
  return new CrossVaultAggregation(this, spec, this.liveBinding());
5096
5393
  }
5097
5394
  /** Begin a grouped cross-shard aggregate. */
5098
5395
  groupBy(field) {
5396
+ this.assertNoJoinLegs("groupBy");
5099
5397
  return new ShardedGroupedQuery(this, field);
5100
5398
  }
5101
5399
  };
@@ -5452,9 +5750,11 @@ __export(src_exports, {
5452
5750
  WeakPassphraseError: () => WeakPassphraseError,
5453
5751
  activeSessionCount: () => activeSessionCount,
5454
5752
  additiveOnly: () => additiveOnly,
5753
+ allocate: () => allocate,
5455
5754
  applyI18nLocale: () => applyI18nLocale,
5456
5755
  applyJoins: () => applyJoins,
5457
5756
  applyPatch: () => applyPatch,
5757
+ asMoney: () => asMoney,
5458
5758
  assertStrongPassphrase: () => assertStrongPassphrase,
5459
5759
  assertTierAccess: () => assertTierAccess,
5460
5760
  avg: () => avg,
@@ -5531,6 +5831,7 @@ __export(src_exports, {
5531
5831
  isI18nTextDescriptor: () => isI18nTextDescriptor,
5532
5832
  isMagicLinkGrantExpired: () => isMagicLinkGrantExpired,
5533
5833
  isMoneyDescriptor: () => isMoneyDescriptor,
5834
+ isMoneyString: () => isMoneyString,
5534
5835
  isPreCompressed: () => isPreCompressed,
5535
5836
  isPublicEnvelope: () => isPublicEnvelope,
5536
5837
  isSessionAlive: () => isSessionAlive,
@@ -5563,6 +5864,8 @@ __export(src_exports, {
5563
5864
  mintShamirRecoveryEntry: () => mintShamirRecoveryEntry,
5564
5865
  mintWrappedDeksBlob: () => mintWrappedDeksBlob,
5565
5866
  money: () => money,
5867
+ moneyNumber: () => moneyNumber,
5868
+ mulRate: () => mulRate,
5566
5869
  paddedIndex: () => paddedIndex,
5567
5870
  parseBytes: () => parseBytes,
5568
5871
  parseIndex: () => parseIndex,
@@ -11454,6 +11757,111 @@ function applyI18nLocale(record, i18nFields, locale, fallback, layer = "read") {
11454
11757
  // src/money/normalize.ts
11455
11758
  init_fixed_point();
11456
11759
  init_descriptor();
11760
+
11761
+ // src/money/paths.ts
11762
+ init_errors();
11763
+ var SEGMENT_RE = /^(\*|[^.[\]*]+)(\[\])?$/;
11764
+ var parseCache = /* @__PURE__ */ new Map();
11765
+ function parseMoneyPath(path) {
11766
+ const cached = parseCache.get(path);
11767
+ if (cached) return cached;
11768
+ if (typeof path !== "string" || path.length === 0) {
11769
+ throw new ValidationError("moneyFields: path must be a non-empty string");
11770
+ }
11771
+ const segments = [];
11772
+ for (const part of path.split(".")) {
11773
+ const m = SEGMENT_RE.exec(part);
11774
+ if (!m) {
11775
+ throw new ValidationError(
11776
+ `moneyFields: invalid path "${path}" \u2014 segment "${part}" must be a key, "key[]", "*", or "*[]"`
11777
+ );
11778
+ }
11779
+ const array = m[2] === "[]";
11780
+ segments.push(
11781
+ m[1] === "*" ? { kind: "wildcard", array } : { kind: "key", key: m[1], array }
11782
+ );
11783
+ }
11784
+ parseCache.set(path, segments);
11785
+ return segments;
11786
+ }
11787
+ function isSimpleMoneyPath(path) {
11788
+ return !path.includes(".") && !path.includes("[") && !path.includes("*");
11789
+ }
11790
+ function validateMoneyFieldPaths(moneyFields) {
11791
+ for (const path of Object.keys(moneyFields)) parseMoneyPath(path);
11792
+ }
11793
+ function transformAtMoneyPath(node, path, segments, index, visit, lenient) {
11794
+ if (node === null || node === void 0) return node;
11795
+ const seg = segments[index];
11796
+ const last = index === segments.length - 1;
11797
+ if (seg.kind === "key") {
11798
+ if (typeof node !== "object" || Array.isArray(node)) {
11799
+ if (lenient) return node;
11800
+ throw new ValidationError(
11801
+ `moneyFields: path "${path}" expected an object at segment "${seg.key}", got ${Array.isArray(node) ? "an array" : typeof node}`
11802
+ );
11803
+ }
11804
+ const obj2 = node;
11805
+ if (!(seg.key in obj2) || obj2[seg.key] === null || obj2[seg.key] === void 0) return node;
11806
+ if (seg.array) {
11807
+ const arr = obj2[seg.key];
11808
+ if (!Array.isArray(arr)) {
11809
+ if (lenient) return node;
11810
+ throw new ValidationError(
11811
+ `moneyFields: path "${path}" declares "${seg.key}[]" but the value is not an array`
11812
+ );
11813
+ }
11814
+ const cloned = [...arr];
11815
+ if (last) {
11816
+ for (let i = 0; i < cloned.length; i++) visit(cloned, i);
11817
+ } else {
11818
+ for (let i = 0; i < cloned.length; i++) {
11819
+ cloned[i] = transformAtMoneyPath(cloned[i], path, segments, index + 1, visit, lenient);
11820
+ }
11821
+ }
11822
+ return { ...obj2, [seg.key]: cloned };
11823
+ }
11824
+ const clone3 = { ...obj2 };
11825
+ if (last) {
11826
+ visit(clone3, seg.key);
11827
+ } else {
11828
+ clone3[seg.key] = transformAtMoneyPath(clone3[seg.key], path, segments, index + 1, visit, lenient);
11829
+ }
11830
+ return clone3;
11831
+ }
11832
+ if (seg.array) {
11833
+ if (!Array.isArray(node)) {
11834
+ if (lenient) return node;
11835
+ throw new ValidationError(`moneyFields: path "${path}" declares "*[]" but the value is not an array`);
11836
+ }
11837
+ const cloned = [...node];
11838
+ if (last) {
11839
+ for (let i = 0; i < cloned.length; i++) visit(cloned, i);
11840
+ } else {
11841
+ for (let i = 0; i < cloned.length; i++) {
11842
+ cloned[i] = transformAtMoneyPath(cloned[i], path, segments, index + 1, visit, lenient);
11843
+ }
11844
+ }
11845
+ return cloned;
11846
+ }
11847
+ if (typeof node !== "object" || Array.isArray(node)) {
11848
+ if (lenient) return node;
11849
+ throw new ValidationError(
11850
+ `moneyFields: path "${path}" applies "*" to a non-object (${Array.isArray(node) ? 'array \u2014 use "*[]"' : typeof node})`
11851
+ );
11852
+ }
11853
+ const obj = node;
11854
+ const clone2 = { ...obj };
11855
+ for (const key of Object.keys(obj)) {
11856
+ const v = clone2[key];
11857
+ if (v === null || v === void 0) continue;
11858
+ if (last) visit(clone2, key);
11859
+ else clone2[key] = transformAtMoneyPath(v, path, segments, index + 1, visit, lenient);
11860
+ }
11861
+ return clone2;
11862
+ }
11863
+
11864
+ // src/money/normalize.ts
11457
11865
  function isMoneyValueObject(v) {
11458
11866
  return typeof v === "object" && v !== null && "currency" in v;
11459
11867
  }
@@ -11465,33 +11873,68 @@ function quantizeAmount(field, input, scale, rounding) {
11465
11873
  }
11466
11874
  return r.value.toString();
11467
11875
  }
11876
+ function canonicalizeStoredMoney(record, moneyFields) {
11877
+ if (record === null || record === void 0) return record;
11878
+ if (!moneyFields || Object.keys(moneyFields).length === 0) return record;
11879
+ return decodeMoneyFields(record, moneyFields, "raw");
11880
+ }
11881
+ function canonicalizeIncomingMoney(record, moneyFields) {
11882
+ if (!moneyFields || Object.keys(moneyFields).length === 0) return record;
11883
+ try {
11884
+ return decodeMoneyFields(
11885
+ quantizeMoneyFields(record, moneyFields),
11886
+ moneyFields,
11887
+ "raw"
11888
+ );
11889
+ } catch {
11890
+ return record;
11891
+ }
11892
+ }
11893
+ function quantizeValue(field, raw, desc) {
11894
+ if (desc.mode === "fixed") {
11895
+ const currency2 = desc.fixedCurrency;
11896
+ return quantizeAmount(field, raw, desc.scaleFor(currency2), desc.rounding);
11897
+ }
11898
+ let amount;
11899
+ let currency;
11900
+ if (isMoneyValueObject(raw)) {
11901
+ currency = String(raw.currency);
11902
+ amount = raw.amount;
11903
+ } else {
11904
+ const sole = desc.soleCurrency();
11905
+ if (sole === void 0) {
11906
+ throw new TypeError(
11907
+ `money: field "${field}" is multi-currency \u2014 write { amount, currency }, not a bare amount`
11908
+ );
11909
+ }
11910
+ currency = sole;
11911
+ amount = raw;
11912
+ }
11913
+ const scale = desc.scaleFor(currency);
11914
+ return { amount: quantizeAmount(field, amount, scale, desc.rounding), currency };
11915
+ }
11468
11916
  function quantizeMoneyFields(record, moneyFields) {
11469
- const out = { ...record };
11470
- for (const [field, desc] of Object.entries(moneyFields)) {
11471
- const raw = out[field];
11472
- if (raw === null || raw === void 0) continue;
11473
- if (desc.mode === "fixed") {
11474
- const currency2 = desc.fixedCurrency;
11475
- out[field] = quantizeAmount(field, raw, desc.scaleFor(currency2), desc.rounding);
11917
+ let out = { ...record };
11918
+ for (const [path, desc] of Object.entries(moneyFields)) {
11919
+ if (isSimpleMoneyPath(path)) {
11920
+ const raw = out[path];
11921
+ if (raw === null || raw === void 0) continue;
11922
+ out[path] = quantizeValue(path, raw, desc);
11476
11923
  continue;
11477
11924
  }
11478
- let amount;
11479
- let currency;
11480
- if (isMoneyValueObject(raw)) {
11481
- currency = String(raw.currency);
11482
- amount = raw.amount;
11483
- } else {
11484
- const sole = desc.soleCurrency();
11485
- if (sole === void 0) {
11486
- throw new TypeError(
11487
- `money: field "${field}" is multi-currency \u2014 write { amount, currency }, not a bare amount`
11488
- );
11489
- }
11490
- currency = sole;
11491
- amount = raw;
11492
- }
11493
- const scale = desc.scaleFor(currency);
11494
- out[field] = { amount: quantizeAmount(field, amount, scale, desc.rounding), currency };
11925
+ out = transformAtMoneyPath(
11926
+ out,
11927
+ path,
11928
+ parseMoneyPath(path),
11929
+ 0,
11930
+ (container, key) => {
11931
+ const raw = container[key];
11932
+ if (raw === null || raw === void 0) return;
11933
+ container[key] = quantizeValue(path, raw, desc);
11934
+ },
11935
+ /* lenient */
11936
+ false
11937
+ );
11495
11938
  }
11496
11939
  return out;
11497
11940
  }
@@ -11504,33 +11947,70 @@ function formatCurrency(decimal, currency, scale, locale) {
11504
11947
  });
11505
11948
  return fmt.format(decimal);
11506
11949
  }
11950
+ function decodeValue(stored, desc) {
11951
+ let currency;
11952
+ let scaledIntString;
11953
+ if (desc.mode === "fixed") {
11954
+ if (typeof stored !== "string" && typeof stored !== "number") return null;
11955
+ currency = desc.fixedCurrency;
11956
+ scaledIntString = String(stored);
11957
+ } else {
11958
+ if (!isMoneyValueObject(stored)) return null;
11959
+ const amount = stored.amount;
11960
+ if (typeof stored.currency !== "string" || typeof amount !== "string" && typeof amount !== "number") return null;
11961
+ currency = stored.currency;
11962
+ scaledIntString = String(amount);
11963
+ }
11964
+ const scale = desc.scaleFor(currency);
11965
+ let decimal;
11966
+ try {
11967
+ decimal = formatScaledInt(BigInt(scaledIntString), scale);
11968
+ } catch {
11969
+ return null;
11970
+ }
11971
+ return {
11972
+ decoded: desc.mode === "fixed" ? decimal : { amount: decimal, currency },
11973
+ decimal,
11974
+ currency,
11975
+ scale
11976
+ };
11977
+ }
11507
11978
  function decodeMoneyFields(record, moneyFields, locale) {
11508
- const out = { ...record };
11979
+ let out = { ...record };
11509
11980
  const format = locale !== "raw";
11510
11981
  const fmtLocale = typeof locale === "string" && locale !== "raw" ? locale : "en-US";
11511
- for (const [field, desc] of Object.entries(moneyFields)) {
11512
- const stored = out[field];
11513
- if (stored === null || stored === void 0) continue;
11514
- let currency;
11515
- let scaledIntString;
11516
- if (desc.mode === "fixed") {
11517
- if (typeof stored !== "string" && typeof stored !== "number") continue;
11518
- currency = desc.fixedCurrency;
11519
- scaledIntString = String(stored);
11520
- } else {
11521
- if (!isMoneyValueObject(stored)) continue;
11522
- const amount = stored.amount;
11523
- if (typeof stored.currency !== "string" || typeof amount !== "string" && typeof amount !== "number") continue;
11524
- currency = stored.currency;
11525
- scaledIntString = String(amount);
11526
- }
11527
- const scale = desc.scaleFor(currency);
11528
- const decimal = formatScaledInt(BigInt(scaledIntString), scale);
11529
- out[field] = desc.mode === "fixed" ? decimal : { amount: decimal, currency };
11530
- if (format) {
11531
- out[`${field}Formatted`] = formatCurrency(decimal, currency, scale, fmtLocale);
11532
- out[`${field}Number`] = Number(decimal);
11982
+ for (const [path, desc] of Object.entries(moneyFields)) {
11983
+ if (isSimpleMoneyPath(path)) {
11984
+ const stored = out[path];
11985
+ if (stored === null || stored === void 0) continue;
11986
+ const r = decodeValue(stored, desc);
11987
+ if (r === null) continue;
11988
+ out[path] = r.decoded;
11989
+ if (format) {
11990
+ out[`${path}Formatted`] = formatCurrency(r.decimal, r.currency, r.scale, fmtLocale);
11991
+ out[`${path}Number`] = Number(r.decimal);
11992
+ }
11993
+ continue;
11533
11994
  }
11995
+ out = transformAtMoneyPath(
11996
+ out,
11997
+ path,
11998
+ parseMoneyPath(path),
11999
+ 0,
12000
+ (container, key) => {
12001
+ const stored = container[key];
12002
+ if (stored === null || stored === void 0) return;
12003
+ const r = decodeValue(stored, desc);
12004
+ if (r === null) return;
12005
+ container[key] = r.decoded;
12006
+ if (format && typeof key === "string" && !Array.isArray(container)) {
12007
+ container[`${key}Formatted`] = formatCurrency(r.decimal, r.currency, r.scale, fmtLocale);
12008
+ container[`${key}Number`] = Number(r.decimal);
12009
+ }
12010
+ },
12011
+ /* lenient */
12012
+ true
12013
+ );
11534
12014
  }
11535
12015
  return out;
11536
12016
  }
@@ -11883,6 +12363,7 @@ var NO_AGGREGATE = {
11883
12363
 
11884
12364
  // src/query/builder.ts
11885
12365
  init_money_reducer();
12366
+ init_where();
11886
12367
  var EMPTY_PLAN = {
11887
12368
  clauses: [],
11888
12369
  orderBy: [],
@@ -11974,9 +12455,18 @@ var Query = class _Query {
11974
12455
  this.predicates
11975
12456
  );
11976
12457
  }
11977
- /** Add a field comparison. Multiple where() calls are AND-combined. */
12458
+ /**
12459
+ * Add a field comparison. Multiple where() calls are AND-combined.
12460
+ *
12461
+ * A declared money field compares in MAJOR units (#336): the operand
12462
+ * (`10000`, `'10000.00'`, or `{ amount, currency }` in multi mode) is
12463
+ * quantized into stored scaled-int space at build time and evaluated
12464
+ * BigInt-exact per record. A malformed operand or a string operator
12465
+ * (`contains`/`startsWith`) throws here, at the call site.
12466
+ */
11978
12467
  where(field, op, value) {
11979
- const clause = { type: "field", field, op, value };
12468
+ const desc = this.source.moneyFields?.[field];
12469
+ const clause = desc ? moneyFieldClause(field, op, value, desc) : { type: "field", field, op, value };
11980
12470
  return new _Query(
11981
12471
  this.source,
11982
12472
  { ...this.plan, clauses: [...this.plan.clauses, clause] },
@@ -12302,7 +12792,7 @@ var Query = class _Query {
12302
12792
  }
12303
12793
  const { candidates, remainingClauses } = candidateRecords(this.source, this.plan.clauses);
12304
12794
  if (remainingClauses.length === 0) return candidates.length;
12305
- return filterRecords(candidates, remainingClauses).length;
12795
+ return filterRecords(candidates, remainingClauses, fnViewDecoder(this.source)).length;
12306
12796
  }
12307
12797
  /**
12308
12798
  * Reduce the matching records through a named set of reducers.
@@ -12359,7 +12849,7 @@ var Query = class _Query {
12359
12849
  return executeClausePipeline(source, clauses, joinCtx);
12360
12850
  }
12361
12851
  const { candidates, remainingClauses } = candidateRecords(source, clauses);
12362
- return remainingClauses.length === 0 ? candidates : filterRecords(candidates, remainingClauses);
12852
+ return remainingClauses.length === 0 ? candidates : filterRecords(candidates, remainingClauses, fnViewDecoder(source));
12363
12853
  };
12364
12854
  const upstreams = [];
12365
12855
  if (source.subscribe) {
@@ -12382,7 +12872,7 @@ var Query = class _Query {
12382
12872
  return executeClausePipeline(source, clauses, joinCtx);
12383
12873
  }
12384
12874
  const { candidates, remainingClauses } = candidateRecords(source, clauses);
12385
- return remainingClauses.length === 0 ? candidates : filterRecords(candidates, remainingClauses);
12875
+ return remainingClauses.length === 0 ? candidates : filterRecords(candidates, remainingClauses, fnViewDecoder(source));
12386
12876
  };
12387
12877
  const upstreams = [];
12388
12878
  if (source.subscribe) {
@@ -12534,7 +13024,7 @@ function executePlanWithSource(source, plan, joinContext) {
12534
13024
  result = executeClausePipeline(source, plan.clauses, joinContext);
12535
13025
  } else {
12536
13026
  const { candidates, remainingClauses } = candidateRecords(source, plan.clauses);
12537
- result = remainingClauses.length === 0 ? [...candidates] : filterRecords(candidates, remainingClauses);
13027
+ result = remainingClauses.length === 0 ? [...candidates] : filterRecords(candidates, remainingClauses, fnViewDecoder(source));
12538
13028
  }
12539
13029
  if (plan.orderBy.length > 0) {
12540
13030
  result = sortRecords(result, plan.orderBy);
@@ -12557,6 +13047,7 @@ function candidateRecords(source, clauses) {
12557
13047
  const clause = clauses[i];
12558
13048
  if (clause.type !== "field") continue;
12559
13049
  if (!indexes.has(clause.field)) continue;
13050
+ if (clause.money?.mode === "multi") continue;
12560
13051
  let ids = null;
12561
13052
  if (clause.op === "==") {
12562
13053
  ids = indexes.lookupEqual(clause.field, clause.value);
@@ -12602,13 +13093,20 @@ function executePlan(records, plan) {
12602
13093
  }
12603
13094
  return result;
12604
13095
  }
12605
- function filterRecords(records, clauses) {
13096
+ function fnViewDecoder(source) {
13097
+ const mf = source.moneyFields;
13098
+ if (!mf || Object.keys(mf).length === 0) return void 0;
13099
+ return (r) => decodeMoneyFields(r, mf, "raw");
13100
+ }
13101
+ function filterRecords(records, clauses, decodeForFns) {
12606
13102
  if (clauses.length === 0) return [...records];
13103
+ const needsFnView = decodeForFns !== void 0 && hasFnClause(clauses);
12607
13104
  const out = [];
12608
13105
  for (const r of records) {
13106
+ const fnView = needsFnView ? decodeForFns(r) : void 0;
12609
13107
  let matches = true;
12610
13108
  for (const clause of clauses) {
12611
- if (!evaluateClause(r, clause)) {
13109
+ if (!evaluateClause(r, clause, fnView)) {
12612
13110
  matches = false;
12613
13111
  break;
12614
13112
  }
@@ -12620,10 +13118,11 @@ function filterRecords(records, clauses) {
12620
13118
  function executeClausePipeline(source, clauses, joinContext) {
12621
13119
  let rel = [...source.snapshot()];
12622
13120
  let filterBatch = [];
13121
+ const decodeForFns = fnViewDecoder(source);
12623
13122
  for (const clause of clauses) {
12624
13123
  if (clause.type === "crossJoin") {
12625
13124
  if (filterBatch.length > 0) {
12626
- rel = filterRecords(rel, filterBatch);
13125
+ rel = filterRecords(rel, filterBatch, decodeForFns);
12627
13126
  filterBatch = [];
12628
13127
  }
12629
13128
  const rightSource = joinContext.resolveSource(clause.target);
@@ -12636,7 +13135,7 @@ function executeClausePipeline(source, clauses, joinContext) {
12636
13135
  }
12637
13136
  }
12638
13137
  if (filterBatch.length > 0) {
12639
- rel = filterRecords(rel, filterBatch);
13138
+ rel = filterRecords(rel, filterBatch, decodeForFns);
12640
13139
  }
12641
13140
  return rel;
12642
13141
  }
@@ -13054,6 +13553,7 @@ init_groupby();
13054
13553
  // src/query/scan-builder.ts
13055
13554
  init_predicate();
13056
13555
  init_errors();
13556
+ init_where();
13057
13557
  var DEFAULT_SCAN_PAGE_SIZE = 100;
13058
13558
  var ScanBuilder = class _ScanBuilder {
13059
13559
  pageProvider;
@@ -13117,7 +13617,8 @@ var ScanBuilder = class _ScanBuilder {
13117
13617
  * evaluates clauses per record in O(1) per clause.
13118
13618
  */
13119
13619
  where(field, op, value) {
13120
- const clause = { type: "field", field, op, value };
13620
+ const desc = this.moneyFields?.[field];
13621
+ const clause = desc ? moneyFieldClause(field, op, value, desc) : { type: "field", field, op, value };
13121
13622
  return new _ScanBuilder(
13122
13623
  this.pageProvider,
13123
13624
  this.pageSize,
@@ -13463,8 +13964,9 @@ var ScanBuilder = class _ScanBuilder {
13463
13964
  */
13464
13965
  recordMatches(record) {
13465
13966
  if (this.clauses.length === 0) return true;
13967
+ const fnView = this.moneyFields && Object.keys(this.moneyFields).length > 0 && hasFnClause(this.clauses) ? this.decodeMoney(record) : void 0;
13466
13968
  for (const clause of this.clauses) {
13467
- if (!evaluateClause(record, clause)) return false;
13969
+ if (!evaluateClause(record, clause, fnView)) return false;
13468
13970
  }
13469
13971
  return true;
13470
13972
  }
@@ -14628,6 +15130,7 @@ var Collection = class {
14628
15130
  this.joinResolver = opts.joinResolver;
14629
15131
  this.i18nFields = opts.i18nFields;
14630
15132
  this.dictKeyFields = opts.dictKeyFields;
15133
+ if (opts.moneyFields) validateMoneyFieldPaths(opts.moneyFields);
14631
15134
  this.moneyFields = opts.moneyFields;
14632
15135
  this.computed = opts.computed;
14633
15136
  this.dictLabelResolver = opts.dictLabelResolver;
@@ -14761,7 +15264,9 @@ var Collection = class {
14761
15264
  * declaration; this reconciles that ordering. First-wins. Not public.
14762
15265
  */
14763
15266
  _applyMoneyFields(moneyFields) {
14764
- if (this.moneyFields === void 0) this.moneyFields = moneyFields;
15267
+ if (this.moneyFields !== void 0) return;
15268
+ validateMoneyFieldPaths(moneyFields);
15269
+ this.moneyFields = moneyFields;
14765
15270
  }
14766
15271
  /** @internal — attach computed fields post-construction. See {@link _applyMoneyFields}. */
14767
15272
  _applyComputed(computed) {
@@ -14928,6 +15433,7 @@ var Collection = class {
14928
15433
  if (!hasWritePermission(this.keyring, this.name)) {
14929
15434
  throw new ReadOnlyError();
14930
15435
  }
15436
+ record = canonicalizeIncomingMoney(record, this.moneyFields);
14931
15437
  if (this.subsystemBus?.hasGateHandlers("beforePut")) {
14932
15438
  const existingEnv = await this.adapter.get(this.vault, this.name, id);
14933
15439
  let existingRecord = null;
@@ -14944,7 +15450,7 @@ var Collection = class {
14944
15450
  collection: this.name,
14945
15451
  docId: id,
14946
15452
  incoming: record,
14947
- existing: existingRecord,
15453
+ existing: canonicalizeStoredMoney(existingRecord, this.moneyFields),
14948
15454
  existingVersion: existingEnv?._v ?? 0,
14949
15455
  existingTs: existingEnv?._ts,
14950
15456
  userId: this.keyring.userId,
@@ -15213,7 +15719,7 @@ var Collection = class {
15213
15719
  */
15214
15720
  async dispatchDerivations(id, record, version) {
15215
15721
  if (this.derivationSource === void 0) return;
15216
- const incoming = record;
15722
+ const incoming = canonicalizeStoredMoney(record, this.moneyFields);
15217
15723
  if (incoming && typeof incoming === "object" && "_derivedFrom" in incoming) return;
15218
15724
  const registry = this.derivationSource.registry();
15219
15725
  const strategies = registry.strategiesForSource(this.name);
@@ -15446,7 +15952,7 @@ var Collection = class {
15446
15952
  vault: this.vault,
15447
15953
  collection: this.name,
15448
15954
  docId: id,
15449
- existing: existingRecord,
15955
+ existing: canonicalizeStoredMoney(existingRecord, this.moneyFields),
15450
15956
  existingVersion: existingEnv._v,
15451
15957
  existingTs: existingEnv._ts,
15452
15958
  internal,
@@ -25643,9 +26149,9 @@ function withMaterializedView(spec) {
25643
26149
  throw new ValidationError("withMaterializedView: query must be a function returning a Query<T>");
25644
26150
  }
25645
26151
  if (spec.unionSources) {
25646
- if (spec.unionSources.length < 2) {
26152
+ if (spec.unionSources.length < 1) {
25647
26153
  throw new MaterializedViewConfigError(
25648
- "unionSources requires at least 2 source collections"
26154
+ "unionSources requires at least 1 source collection"
25649
26155
  );
25650
26156
  }
25651
26157
  const seen = /* @__PURE__ */ new Set();
@@ -25737,6 +26243,117 @@ init_errors();
25737
26243
  init_descriptor();
25738
26244
  init_iso4217();
25739
26245
 
26246
+ // src/money/arith.ts
26247
+ init_fixed_point();
26248
+ init_descriptor();
26249
+ function parseAmount(label, amount, scale, rounding) {
26250
+ const r = parseToScaledInt(amount, scale, rounding);
26251
+ if (!r.ok) {
26252
+ throw new MoneyUnsupportedError(
26253
+ r.reason === "precision" ? `${label}: amount ${JSON.stringify(amount)} has more precision than scale ${scale} and no rounding mode is configured` : `${label}: amount ${JSON.stringify(amount)} is not a finite decimal`
26254
+ );
26255
+ }
26256
+ return r.value;
26257
+ }
26258
+ function resolveScale(label, amount, explicit) {
26259
+ if (explicit !== void 0) {
26260
+ if (!Number.isInteger(explicit) || explicit < 0) {
26261
+ throw new MoneyUnsupportedError(`${label}: scale must be a non-negative integer`);
26262
+ }
26263
+ return explicit;
26264
+ }
26265
+ const inferred = decimalScaleOf(amount);
26266
+ if (inferred === null) {
26267
+ throw new MoneyUnsupportedError(`${label}: amount ${JSON.stringify(amount)} is not a finite decimal`);
26268
+ }
26269
+ return inferred;
26270
+ }
26271
+ function mulRate(amount, rate, opts = {}) {
26272
+ const scale = resolveScale("mulRate", amount, opts.scale);
26273
+ const rounding = opts.rounding ?? "half-up";
26274
+ const a = parseAmount("mulRate", amount, scale, rounding);
26275
+ const rateScale = decimalScaleOf(rate);
26276
+ if (rateScale === null) {
26277
+ throw new MoneyUnsupportedError(`mulRate: rate ${JSON.stringify(rate)} is not a finite decimal`);
26278
+ }
26279
+ const r = parseToScaledInt(rate, rateScale);
26280
+ if (!r.ok) {
26281
+ throw new MoneyUnsupportedError(`mulRate: rate ${JSON.stringify(rate)} is not a finite decimal`);
26282
+ }
26283
+ const product = a * r.value;
26284
+ return formatScaledInt(rescaleScaledInt(product, scale + rateScale, scale, rounding), scale);
26285
+ }
26286
+ function allocate(amount, weights, opts = {}) {
26287
+ if (weights.length === 0) {
26288
+ throw new MoneyUnsupportedError("allocate: weights must not be empty");
26289
+ }
26290
+ const scale = resolveScale("allocate", amount, opts.scale);
26291
+ const a = parseAmount("allocate", amount, scale);
26292
+ let weightScale = 0;
26293
+ for (const w of weights) {
26294
+ const s = decimalScaleOf(w);
26295
+ if (s === null) {
26296
+ throw new MoneyUnsupportedError(`allocate: weight ${JSON.stringify(w)} is not a finite decimal`);
26297
+ }
26298
+ if (s > weightScale) weightScale = s;
26299
+ }
26300
+ const scaledWeights = weights.map((w) => {
26301
+ const r = parseToScaledInt(w, weightScale);
26302
+ if (!r.ok || r.value < 0n) {
26303
+ throw new MoneyUnsupportedError(`allocate: weight ${JSON.stringify(w)} must be a non-negative decimal`);
26304
+ }
26305
+ return r.value;
26306
+ });
26307
+ const sumW = scaledWeights.reduce((acc, w) => acc + w, 0n);
26308
+ if (sumW === 0n) {
26309
+ throw new MoneyUnsupportedError("allocate: weights must not all be zero");
26310
+ }
26311
+ const negative = a < 0n;
26312
+ const mag = negative ? -a : a;
26313
+ const base = [];
26314
+ const remainders = [];
26315
+ let distributed = 0n;
26316
+ for (let i = 0; i < scaledWeights.length; i++) {
26317
+ const product = mag * scaledWeights[i];
26318
+ const share = product / sumW;
26319
+ base.push(share);
26320
+ distributed += share;
26321
+ remainders.push({ index: i, rem: product % sumW });
26322
+ }
26323
+ let leftover = mag - distributed;
26324
+ remainders.sort((x, y) => y.rem > x.rem ? 1 : y.rem < x.rem ? -1 : x.index - y.index);
26325
+ for (const { index } of remainders) {
26326
+ if (leftover === 0n) break;
26327
+ base[index] = base[index] + 1n;
26328
+ leftover -= 1n;
26329
+ }
26330
+ return base.map((p) => formatScaledInt(negative && p !== 0n ? -p : p, scale));
26331
+ }
26332
+
26333
+ // src/money/branded.ts
26334
+ init_fixed_point();
26335
+ init_descriptor();
26336
+ function asMoney(value) {
26337
+ if (!isMoneyLike(value)) {
26338
+ throw new MoneyUnsupportedError(`asMoney: ${JSON.stringify(value)} is not a finite decimal`);
26339
+ }
26340
+ return String(value).trim();
26341
+ }
26342
+ function isMoneyString(value) {
26343
+ return typeof value === "string" && isMoneyLike(value);
26344
+ }
26345
+ function moneyNumber(value) {
26346
+ if (!isMoneyLike(value)) {
26347
+ throw new MoneyUnsupportedError(`moneyNumber: ${JSON.stringify(value)} is not a finite decimal`);
26348
+ }
26349
+ return Number(value);
26350
+ }
26351
+ function isMoneyLike(value) {
26352
+ if (typeof value === "number") return Number.isFinite(value);
26353
+ if (typeof value !== "string") return false;
26354
+ return decimalScaleOf(value) !== null;
26355
+ }
26356
+
25740
26357
  // src/i18n/script.ts
25741
26358
  init_errors();
25742
26359
  var LATIN_BASE = /* @__PURE__ */ new Set([
@@ -26679,9 +27296,11 @@ function shortJSON(value) {
26679
27296
  WeakPassphraseError,
26680
27297
  activeSessionCount,
26681
27298
  additiveOnly,
27299
+ allocate,
26682
27300
  applyI18nLocale,
26683
27301
  applyJoins,
26684
27302
  applyPatch,
27303
+ asMoney,
26685
27304
  assertStrongPassphrase,
26686
27305
  assertTierAccess,
26687
27306
  avg,
@@ -26758,6 +27377,7 @@ function shortJSON(value) {
26758
27377
  isI18nTextDescriptor,
26759
27378
  isMagicLinkGrantExpired,
26760
27379
  isMoneyDescriptor,
27380
+ isMoneyString,
26761
27381
  isPreCompressed,
26762
27382
  isPublicEnvelope,
26763
27383
  isSessionAlive,
@@ -26790,6 +27410,8 @@ function shortJSON(value) {
26790
27410
  mintShamirRecoveryEntry,
26791
27411
  mintWrappedDeksBlob,
26792
27412
  money,
27413
+ moneyNumber,
27414
+ mulRate,
26793
27415
  paddedIndex,
26794
27416
  parseBytes,
26795
27417
  parseIndex,