@noy-db/hub 0.2.0-pre.11 → 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 (265) 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 +1452 -16
  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-77DWLQRY.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-73YLDCNF.js → chunk-7JJE3OMJ.js} +5 -5
  28. package/dist/{chunk-GKI4SDP7.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-YVZRTCGG.js → chunk-DLTU4M2I.js} +6 -6
  37. package/dist/{chunk-GAUEWM7D.js → chunk-EKNUBIIQ.js} +4 -4
  38. package/dist/{chunk-QCXNMCHN.js → chunk-GFPR7VJS.js} +4 -4
  39. package/dist/{chunk-V2PZC6AW.js → chunk-HBAJDI2N.js} +5 -5
  40. package/dist/{chunk-PVUUIWHY.js → chunk-HLGDYFWR.js} +10 -3
  41. package/dist/chunk-HLGDYFWR.js.map +1 -0
  42. package/dist/{chunk-RRNA5GKT.js → chunk-IEPT7HVP.js} +2 -2
  43. package/dist/{chunk-R233SLY3.js → chunk-IUBHXEPJ.js} +2 -2
  44. package/dist/{chunk-CH22FZHT.js → chunk-L6BYRCYB.js} +2 -2
  45. package/dist/{chunk-PC3ZZBTO.js → chunk-LOA2VCMS.js} +5 -5
  46. package/dist/{chunk-TGALXXLV.js → chunk-LSEW3ZZ2.js} +3 -3
  47. package/dist/{chunk-Y26YV5R3.js → chunk-LWSD4QPT.js} +3 -3
  48. package/dist/{chunk-SLV4LAKX.js → chunk-LYNNZEQD.js} +1 -1
  49. package/dist/chunk-LYNNZEQD.js.map +1 -0
  50. package/dist/{chunk-26NK23DZ.js → chunk-M45IRXDM.js} +3 -3
  51. package/dist/{chunk-CXJG63MA.js → chunk-NP6EZT44.js} +20 -6
  52. package/dist/chunk-NP6EZT44.js.map +1 -0
  53. package/dist/{chunk-ZBBW7YQN.js → chunk-O53RIZCC.js} +5 -5
  54. package/dist/chunk-OPDTLHFA.js +783 -0
  55. package/dist/chunk-OPDTLHFA.js.map +1 -0
  56. package/dist/{chunk-LSTBFLL2.js → chunk-P3Z5Y2TS.js} +2 -2
  57. package/dist/{chunk-QSOYKKMD.js → chunk-P4EDT5ZP.js} +2 -2
  58. package/dist/{chunk-PC6ZEDRL.js → chunk-RHQYVHFH.js} +2 -2
  59. package/dist/{chunk-3DGHRDCX.js → chunk-RRDWXNBQ.js} +3 -3
  60. package/dist/{chunk-6MFH4BMK.js → chunk-SJJQKNMP.js} +4 -4
  61. package/dist/{chunk-EBVBE7UK.js → chunk-SZ4N3IL5.js} +5 -5
  62. package/dist/{chunk-MPOLUAMI.js → chunk-TMHJEYW7.js} +497 -57
  63. package/dist/chunk-TMHJEYW7.js.map +1 -0
  64. package/dist/{chunk-JQ4NEJJ6.js → chunk-UA6G45ME.js} +3 -3
  65. package/dist/{chunk-6YLPHBKR.js → chunk-UOC7JMZO.js} +13 -4
  66. package/dist/chunk-UOC7JMZO.js.map +1 -0
  67. package/dist/{chunk-DAP2XL7Q.js → chunk-VOXMU6LB.js} +2 -2
  68. package/dist/chunk-WNRGOVLG.js +64 -0
  69. package/dist/chunk-WNRGOVLG.js.map +1 -0
  70. package/dist/{chunk-YW5DBAPG.js → chunk-WUG3E423.js} +4 -4
  71. package/dist/{chunk-LJXYPGRH.js → chunk-XHM2SARW.js} +3 -3
  72. package/dist/{chunk-RC6SU5NO.js → chunk-XSIFXX54.js} +2 -2
  73. package/dist/{chunk-CXFOITNS.js → chunk-ZC7MNVYN.js} +2 -2
  74. package/dist/{chunk-6T2UDBKG.js → chunk-ZCFS7U4J.js} +2 -2
  75. package/dist/consent/index.cjs.map +1 -1
  76. package/dist/consent/index.d.cts +4 -4
  77. package/dist/consent/index.d.ts +4 -4
  78. package/dist/consent/index.js +3 -3
  79. package/dist/{crypto-2CRLG4F4.js → crypto-AJB72OKN.js} +3 -3
  80. package/dist/{delegation-ZTRT2PRV.js → delegation-6FCWDRUS.js} +5 -5
  81. package/dist/derivations/index.cjs.map +1 -1
  82. package/dist/derivations/index.d.cts +5 -5
  83. package/dist/derivations/index.d.ts +5 -5
  84. package/dist/derivations/index.js +4 -4
  85. package/dist/{dev-unlock-BH6y3Hx0.d.ts → dev-unlock-D3mpVFRc.d.ts} +1 -1
  86. package/dist/{dev-unlock-H1Xwxc3U.d.cts → dev-unlock-ckqa_Nso.d.cts} +1 -1
  87. package/dist/executor-7KSCEIFA.js +8 -0
  88. package/dist/executor-D2QMNGRJ.js +8 -0
  89. package/dist/executor-O5AZK7UW.js +11 -0
  90. package/dist/{fanout-sidecar-F3ZRFU4H.js → fanout-sidecar-ZSKEQ6NI.js} +2 -2
  91. package/dist/guards/index.cjs +53 -1
  92. package/dist/guards/index.cjs.map +1 -1
  93. package/dist/guards/index.d.cts +12 -6
  94. package/dist/guards/index.d.ts +12 -6
  95. package/dist/guards/index.js +5 -3
  96. package/dist/{hash-D89JdDbj.d.ts → hash-CTZVkXLx.d.ts} +1 -1
  97. package/dist/{hash-_sDFvtmX.d.cts → hash-rDSSd_oW.d.cts} +1 -1
  98. package/dist/history/index.cjs.map +1 -1
  99. package/dist/history/index.d.cts +5 -5
  100. package/dist/history/index.d.ts +5 -5
  101. package/dist/history/index.js +5 -5
  102. package/dist/i18n/index.cjs.map +1 -1
  103. package/dist/i18n/index.d.cts +4 -4
  104. package/dist/i18n/index.d.ts +4 -4
  105. package/dist/i18n/index.js +6 -6
  106. package/dist/immutable-guard-C51vAHuh.d.cts +67 -0
  107. package/dist/immutable-guard-DyD0qg2k.d.ts +67 -0
  108. package/dist/index-CkFHr4OP.d.ts +1190 -0
  109. package/dist/index-Cmop06zJ.d.cts +1190 -0
  110. package/dist/index.cjs +1620 -58
  111. package/dist/index.cjs.map +1 -1
  112. package/dist/index.d.cts +46 -13
  113. package/dist/index.d.ts +46 -13
  114. package/dist/index.js +76 -44
  115. package/dist/index.js.map +1 -1
  116. package/dist/indexing/index.cjs.map +1 -1
  117. package/dist/indexing/index.js +2 -2
  118. package/dist/issue-YIYG4OW5.js +12 -0
  119. package/dist/{ledger-NYCGJX2D.js → ledger-5JMVF7PY.js} +5 -5
  120. package/dist/materialized-views/index.cjs.map +1 -1
  121. package/dist/materialized-views/index.d.cts +5 -6
  122. package/dist/materialized-views/index.d.ts +5 -6
  123. package/dist/materialized-views/index.js +6 -6
  124. package/dist/noydb-D5SLAJ6V.js +34 -0
  125. package/dist/overlay-views/index.cjs.map +1 -1
  126. package/dist/overlay-views/index.d.cts +5 -5
  127. package/dist/overlay-views/index.d.ts +5 -5
  128. package/dist/overlay-views/index.js +4 -4
  129. package/dist/periods/index.cjs.map +1 -1
  130. package/dist/periods/index.d.cts +4 -4
  131. package/dist/periods/index.d.ts +4 -4
  132. package/dist/periods/index.js +5 -5
  133. package/dist/{public-envelope-QOXZEHKH.js → public-envelope-PFLZI5MO.js} +4 -4
  134. package/dist/query/index.cjs +293 -10
  135. package/dist/query/index.cjs.map +1 -1
  136. package/dist/query/index.d.cts +2 -2
  137. package/dist/query/index.d.ts +2 -2
  138. package/dist/query/index.js +4 -4
  139. package/dist/registry-BVQ5ITMF.js +8 -0
  140. package/dist/registry-JLP3QOLD.js +8 -0
  141. package/dist/{registry-ST2VNFZC.js → registry-NCY445U5.js} +3 -3
  142. package/dist/{revoke-RT7QYB4G.js → revoke-7RLGQWZ7.js} +6 -6
  143. package/dist/session/index.cjs.map +1 -1
  144. package/dist/session/index.d.cts +5 -5
  145. package/dist/session/index.d.ts +5 -5
  146. package/dist/session/index.js +3 -3
  147. package/dist/shadow/index.cjs.map +1 -1
  148. package/dist/shadow/index.d.cts +4 -4
  149. package/dist/shadow/index.d.ts +4 -4
  150. package/dist/shadow/index.js +2 -2
  151. package/dist/{signer-QNU66JF5.js → signer-6JF44I4A.js} +5 -5
  152. package/dist/snapshots/index.cjs.map +1 -1
  153. package/dist/snapshots/index.d.cts +4 -4
  154. package/dist/snapshots/index.d.ts +4 -4
  155. package/dist/snapshots/index.js +4 -4
  156. package/dist/{stale-VKXSXJF4.js → stale-UBLP3RJ3.js} +2 -2
  157. package/dist/store/index.cjs.map +1 -1
  158. package/dist/store/index.d.cts +4 -4
  159. package/dist/store/index.d.ts +4 -4
  160. package/dist/store/index.js +2 -2
  161. package/dist/strategy-rtpKDfTC.d.cts +2029 -0
  162. package/dist/strategy-rtpKDfTC.d.ts +2029 -0
  163. package/dist/sync/index.cjs.map +1 -1
  164. package/dist/sync/index.d.cts +3 -3
  165. package/dist/sync/index.d.ts +3 -3
  166. package/dist/sync/index.js +4 -4
  167. package/dist/team/index.cjs.map +1 -1
  168. package/dist/team/index.d.cts +4 -4
  169. package/dist/team/index.d.ts +4 -4
  170. package/dist/team/index.js +8 -8
  171. package/dist/tx/index.cjs +8 -1
  172. package/dist/tx/index.cjs.map +1 -1
  173. package/dist/tx/index.d.cts +4 -4
  174. package/dist/tx/index.d.ts +4 -4
  175. package/dist/tx/index.js +3 -3
  176. package/dist/{types-DiSXn3a4.d.cts → types-BGwjsDef.d.cts} +511 -6
  177. package/dist/{types-CD8mc8zR.d.ts → types-DRdfwgTG.d.ts} +511 -6
  178. package/dist/{ulid-DQ1hcJvZ.d.cts → ulid-D4d0Xto3.d.cts} +1 -1
  179. package/dist/{ulid-8p83wbR4.d.ts → ulid-DOTPZ5_h.d.ts} +1 -1
  180. package/dist/util/index.cjs.map +1 -1
  181. package/dist/util/index.js +1 -1
  182. package/dist/vault-group-Z4KB75ZH.js +450 -0
  183. package/dist/vault-group-Z4KB75ZH.js.map +1 -0
  184. package/dist/{with-derivation-DWMTpgEH.d.ts → with-derivation-B082Y_WQ.d.ts} +1 -1
  185. package/dist/{with-derivation-CVT7-dUt.d.cts → with-derivation-CB1EdcFF.d.cts} +1 -1
  186. package/dist/{with-materialized-view-BTTU3BNK.d.cts → with-materialized-view-CzRg1Dpr.d.cts} +1 -1
  187. package/dist/{with-materialized-view-X0CoL8-L.d.ts → with-materialized-view-Dw4SwjKl.d.ts} +1 -1
  188. package/dist/{with-overlayed-view-DcacRRsS.d.cts → with-overlayed-view-C9YFKXzn.d.cts} +1 -1
  189. package/dist/{with-overlayed-view-DQjO_DSG.d.ts → with-overlayed-view-CaCXeW26.d.ts} +1 -1
  190. package/package.json +3 -3
  191. package/dist/chunk-2LPPNWF6.js +0 -340
  192. package/dist/chunk-2LPPNWF6.js.map +0 -1
  193. package/dist/chunk-6YLPHBKR.js.map +0 -1
  194. package/dist/chunk-77DWLQRY.js.map +0 -1
  195. package/dist/chunk-C3WE6UJY.js +0 -19
  196. package/dist/chunk-C3WE6UJY.js.map +0 -1
  197. package/dist/chunk-CXJG63MA.js.map +0 -1
  198. package/dist/chunk-MPOLUAMI.js.map +0 -1
  199. package/dist/chunk-O6EJ6WTI.js.map +0 -1
  200. package/dist/chunk-PVUUIWHY.js.map +0 -1
  201. package/dist/chunk-SLV4LAKX.js.map +0 -1
  202. package/dist/executor-S76VN45G.js +0 -8
  203. package/dist/executor-UCXLIGLW.js +0 -11
  204. package/dist/executor-ZCNZJMGR.js +0 -8
  205. package/dist/index-B8bjExET.d.cts +0 -2434
  206. package/dist/index-DfUbNad8.d.ts +0 -2434
  207. package/dist/issue-IVTVSKWW.js +0 -12
  208. package/dist/noydb-SH4RLE47.js +0 -34
  209. package/dist/registry-UFIK7CSR.js +0 -8
  210. package/dist/registry-ZGYYSM5I.js +0 -8
  211. package/dist/strategy-CT2LCKAX.d.cts +0 -613
  212. package/dist/strategy-CT2LCKAX.d.ts +0 -613
  213. package/dist/with-guard-BRvt53da.d.ts +0 -18
  214. package/dist/with-guard-Dx2zZnTA.d.cts +0 -18
  215. /package/dist/{chunk-7CEGU63S.js.map → chunk-4BHFNKTP.js.map} +0 -0
  216. /package/dist/{chunk-5OEJ6GOT.js.map → chunk-5ARRXIVR.js.map} +0 -0
  217. /package/dist/{chunk-YM7LFCG7.js.map → chunk-6BYBVRZU.js.map} +0 -0
  218. /package/dist/{chunk-73YLDCNF.js.map → chunk-7JJE3OMJ.js.map} +0 -0
  219. /package/dist/{chunk-GKI4SDP7.js.map → chunk-7LVRIW4G.js.map} +0 -0
  220. /package/dist/{chunk-IMYKDWB4.js.map → chunk-B7GGYNKQ.js.map} +0 -0
  221. /package/dist/{chunk-BDV7INMP.js.map → chunk-BXOUVUES.js.map} +0 -0
  222. /package/dist/{chunk-FO3UEG4S.js.map → chunk-C2CIIQRG.js.map} +0 -0
  223. /package/dist/{chunk-ZROPXHJY.js.map → chunk-CHBXWJZQ.js.map} +0 -0
  224. /package/dist/{chunk-RYIL3PI2.js.map → chunk-CILT6V3V.js.map} +0 -0
  225. /package/dist/{chunk-YVZRTCGG.js.map → chunk-DLTU4M2I.js.map} +0 -0
  226. /package/dist/{chunk-GAUEWM7D.js.map → chunk-EKNUBIIQ.js.map} +0 -0
  227. /package/dist/{chunk-QCXNMCHN.js.map → chunk-GFPR7VJS.js.map} +0 -0
  228. /package/dist/{chunk-V2PZC6AW.js.map → chunk-HBAJDI2N.js.map} +0 -0
  229. /package/dist/{chunk-RRNA5GKT.js.map → chunk-IEPT7HVP.js.map} +0 -0
  230. /package/dist/{chunk-R233SLY3.js.map → chunk-IUBHXEPJ.js.map} +0 -0
  231. /package/dist/{chunk-CH22FZHT.js.map → chunk-L6BYRCYB.js.map} +0 -0
  232. /package/dist/{chunk-PC3ZZBTO.js.map → chunk-LOA2VCMS.js.map} +0 -0
  233. /package/dist/{chunk-TGALXXLV.js.map → chunk-LSEW3ZZ2.js.map} +0 -0
  234. /package/dist/{chunk-Y26YV5R3.js.map → chunk-LWSD4QPT.js.map} +0 -0
  235. /package/dist/{chunk-26NK23DZ.js.map → chunk-M45IRXDM.js.map} +0 -0
  236. /package/dist/{chunk-ZBBW7YQN.js.map → chunk-O53RIZCC.js.map} +0 -0
  237. /package/dist/{chunk-LSTBFLL2.js.map → chunk-P3Z5Y2TS.js.map} +0 -0
  238. /package/dist/{chunk-QSOYKKMD.js.map → chunk-P4EDT5ZP.js.map} +0 -0
  239. /package/dist/{chunk-PC6ZEDRL.js.map → chunk-RHQYVHFH.js.map} +0 -0
  240. /package/dist/{chunk-3DGHRDCX.js.map → chunk-RRDWXNBQ.js.map} +0 -0
  241. /package/dist/{chunk-6MFH4BMK.js.map → chunk-SJJQKNMP.js.map} +0 -0
  242. /package/dist/{chunk-EBVBE7UK.js.map → chunk-SZ4N3IL5.js.map} +0 -0
  243. /package/dist/{chunk-JQ4NEJJ6.js.map → chunk-UA6G45ME.js.map} +0 -0
  244. /package/dist/{chunk-DAP2XL7Q.js.map → chunk-VOXMU6LB.js.map} +0 -0
  245. /package/dist/{chunk-YW5DBAPG.js.map → chunk-WUG3E423.js.map} +0 -0
  246. /package/dist/{chunk-LJXYPGRH.js.map → chunk-XHM2SARW.js.map} +0 -0
  247. /package/dist/{chunk-RC6SU5NO.js.map → chunk-XSIFXX54.js.map} +0 -0
  248. /package/dist/{chunk-CXFOITNS.js.map → chunk-ZC7MNVYN.js.map} +0 -0
  249. /package/dist/{chunk-6T2UDBKG.js.map → chunk-ZCFS7U4J.js.map} +0 -0
  250. /package/dist/{crypto-2CRLG4F4.js.map → crypto-AJB72OKN.js.map} +0 -0
  251. /package/dist/{delegation-ZTRT2PRV.js.map → delegation-6FCWDRUS.js.map} +0 -0
  252. /package/dist/{executor-S76VN45G.js.map → executor-7KSCEIFA.js.map} +0 -0
  253. /package/dist/{executor-UCXLIGLW.js.map → executor-D2QMNGRJ.js.map} +0 -0
  254. /package/dist/{executor-ZCNZJMGR.js.map → executor-O5AZK7UW.js.map} +0 -0
  255. /package/dist/{fanout-sidecar-F3ZRFU4H.js.map → fanout-sidecar-ZSKEQ6NI.js.map} +0 -0
  256. /package/dist/{issue-IVTVSKWW.js.map → issue-YIYG4OW5.js.map} +0 -0
  257. /package/dist/{ledger-NYCGJX2D.js.map → ledger-5JMVF7PY.js.map} +0 -0
  258. /package/dist/{noydb-SH4RLE47.js.map → noydb-D5SLAJ6V.js.map} +0 -0
  259. /package/dist/{public-envelope-QOXZEHKH.js.map → public-envelope-PFLZI5MO.js.map} +0 -0
  260. /package/dist/{registry-ST2VNFZC.js.map → registry-BVQ5ITMF.js.map} +0 -0
  261. /package/dist/{registry-UFIK7CSR.js.map → registry-JLP3QOLD.js.map} +0 -0
  262. /package/dist/{registry-ZGYYSM5I.js.map → registry-NCY445U5.js.map} +0 -0
  263. /package/dist/{revoke-RT7QYB4G.js.map → revoke-7RLGQWZ7.js.map} +0 -0
  264. /package/dist/{signer-QNU66JF5.js.map → signer-6JF44I4A.js.map} +0 -0
  265. /package/dist/{stale-VKXSXJF4.js.map → stale-UBLP3RJ3.js.map} +0 -0
@@ -0,0 +1,2029 @@
1
+ /**
2
+ * Aggregation reducers for the query DSL.
3
+ *
4
+ * the reducer protocol plus five built-in factories
5
+ * (`count`, `sum`, `avg`, `min`, `max`) consumed by `Query.aggregate()`
6
+ * and, in the future, `Scan.aggregate()`. Every factory accepts
7
+ * an optional `{ seed }` parameter that is plumbed through the
8
+ * protocol but unused by the executor — that's the load-bearing
9
+ * half of constraint #2. When partition-aware aggregation
10
+ * lands, the seed carries the previous partition's running total into
11
+ * the next partition without requiring a protocol change.
12
+ *
13
+ * Reducers are intentionally generic over their internal state type
14
+ * `S` so compound reducers (avg keeps `{sum, count}`, min/max keep a
15
+ * value bag) can model internal bookkeeping without leaking the
16
+ * implementation through the accumulator's public shape. `finalize`
17
+ * collapses `S` back into the user-visible `R`.
18
+ *
19
+ * Reducers are pure data — `init` / `step` / `finalize` / optional
20
+ * `remove` are stateless functions that receive and return `S`. This
21
+ * is the shape that admits O(1) incremental maintenance in a future
22
+ * optimization (delta-aware `LiveAggregation` applies `step` or
23
+ * `remove` per delta), without blocking the simpler "full re-run on
24
+ * source change" that ships.
25
+ */
26
+ /**
27
+ * A single reducer: factory-produced, ready to plug into an
28
+ * `.aggregate()` spec.
29
+ *
30
+ * Type parameters:
31
+ * - `R` — user-visible result type (what the aggregation returns
32
+ * for this slot, e.g. `number` for `sum()`)
33
+ * - `S` — internal state type, defaults to `R` for simple reducers
34
+ * that don't need compound bookkeeping
35
+ *
36
+ * A reducer is stateless: every method is pure over `S`. `init()` is
37
+ * called once per aggregation run to build the initial state; `step()`
38
+ * folds a record into the state; `remove()` (optional) un-folds a
39
+ * record, enabling incremental live maintenance; `finalize()` reads
40
+ * the final answer out of the state at the end of the run.
41
+ */
42
+ interface Reducer<R, S = R> {
43
+ /** Build the initial state for a fresh aggregation run. */
44
+ init(): S;
45
+ /** Fold a record into the state. Returns the new state. */
46
+ step(state: S, record: unknown): S;
47
+ /**
48
+ * Un-fold a record from the state. Returns the new state.
49
+ *
50
+ * Optional — reducers without `remove` cannot be maintained
51
+ * incrementally and must be re-run from scratch when the underlying
52
+ * record set changes. `sum`, `count`, `avg` implement `remove` in
53
+ * O(1); `min` and `max` implement it in O(N) worst case (when the
54
+ * extremum itself is removed and the next extremum must be
55
+ * recomputed from the remaining contributing values).
56
+ */
57
+ remove?(state: S, record: unknown): S;
58
+ /** Collapse the internal state into the user-visible result. */
59
+ finalize(state: S): R;
60
+ /**
61
+ * Combine two independent partial states into one (then `finalize` once).
62
+ * Optional. MUST be associative + commutative with `init()` as identity.
63
+ * Never merge finalized results — only states. Enables parallel /
64
+ * hierarchical aggregation (e.g. cross-shard or advisor→firm rollup).
65
+ */
66
+ merge?(a: S, b: S): S;
67
+ /**
68
+ * Identifying operation tag stamped by each built-in factory.
69
+ * Used by `summariseAggregateOp` in the introspection walker to
70
+ * render human-readable aggregate descriptors in `dumpSchema()`.
71
+ * Optional so third-party custom reducers are unaffected.
72
+ */
73
+ readonly op?: 'count' | 'sum' | 'avg' | 'min' | 'max';
74
+ /**
75
+ * Field name for field-based reducers (`sum`, `avg`, `min`, `max`).
76
+ * Absent on `count` which aggregates over record count, not a field.
77
+ */
78
+ readonly field?: string;
79
+ /**
80
+ * Money-only: target currency for `sum` over a multi-currency money
81
+ * field. Consumed by `wrapMoneyReducers` to convert per-currency
82
+ * subtotals to one figure. Ignored for non-money fields.
83
+ */
84
+ readonly convertTo?: string;
85
+ /**
86
+ * Money-only: FX rate map (`'USD->EUR' → rate`) used with `convertTo`.
87
+ */
88
+ readonly fx?: Record<string, number | string>;
89
+ }
90
+ /**
91
+ * Common options accepted by every reducer factory.
92
+ *
93
+ * `seed` — optional initial value for the internal state. **Unused by
94
+ * the executor**, plumbed through the protocol for constraint
95
+ * #2 (partition-aware aggregation seam). In, partitioned
96
+ * aggregations will pass the previous partition's carry as `seed` so
97
+ * a long time series can be rolled forward one partition at a time
98
+ * without re-aggregating closed partitions.
99
+ *
100
+ * always uses `init()` with the factory's zero value, regardless
101
+ * of whether `seed` was passed. Do not remove the parameter — that's
102
+ * the whole point of having it exist now.
103
+ */
104
+ interface ReducerOptions<TSeed = unknown> {
105
+ /** constraint #2 — seed is plumbed through but unused in. */
106
+ readonly seed?: TSeed;
107
+ /**
108
+ * Money-only (honored by `sum` over a multi-currency money field):
109
+ * convert per-currency subtotals to this currency for a single figure.
110
+ */
111
+ readonly convertTo?: string;
112
+ /** Money-only: FX rate map (`'USD->EUR' → rate`) used with `convertTo`. */
113
+ readonly fx?: Record<string, number | string>;
114
+ }
115
+ /**
116
+ * Count the number of records that match the query. Ignores field
117
+ * values entirely — the count is over the number of records, not over
118
+ * the number of non-null field values in any column.
119
+ */
120
+ declare function count(opts?: ReducerOptions<number>): Reducer<number>;
121
+ /**
122
+ * Sum a numeric field across all matching records. Non-number values
123
+ * at the field path are coerced to 0 — consumers who want a different
124
+ * behavior (throw, skip, treat as NaN) should filter upstream via
125
+ * `.where()` or write a custom reducer.
126
+ */
127
+ declare function sum(field: string, opts?: ReducerOptions<number>): Reducer<number>;
128
+ /**
129
+ * Arithmetic mean of a numeric field across all matching records.
130
+ *
131
+ * Returns `null` for an empty result set (zero records is not a
132
+ * well-defined denominator — returning NaN would poison downstream
133
+ * arithmetic, and throwing would force every consumer to wrap in
134
+ * try/catch just to handle "no matches"). Consumers who want an
135
+ * explicit zero should coalesce with `?? 0`.
136
+ *
137
+ * Internal state is `{sum, count}` so the running average can be
138
+ * maintained incrementally — on each delta, both fields update in
139
+ * O(1) and `finalize` divides. Directly storing `avg` as state would
140
+ * not admit incremental removal without also tracking count.
141
+ */
142
+ declare function avg(field: string, opts?: ReducerOptions<{
143
+ sum: number;
144
+ count: number;
145
+ }>): Reducer<number | null, {
146
+ sum: number;
147
+ count: number;
148
+ }>;
149
+ interface MinMaxState {
150
+ /**
151
+ * Multiset of contributing field values. Stored as a plain array
152
+ * because we need to support `remove` and a plain array gives us
153
+ * O(1) push + O(N) worst-case removal — which matches the
154
+ * documented min/max removal complexity. A sorted structure would
155
+ * let us drop the O(N) rescan but adds complexity that doesn't
156
+ * need; consumers hitting the O(N) ceiling should file an issue.
157
+ */
158
+ readonly values: number[];
159
+ }
160
+ /**
161
+ * Smallest numeric value of a field across all matching records.
162
+ * Returns `null` for an empty result set. See `avg()` for the
163
+ * reasoning on `null` vs NaN vs throwing.
164
+ *
165
+ * Incremental complexity: O(1) for `step`, O(N) worst case for
166
+ * `remove` when the current minimum is removed (the state holds the
167
+ * full multiset of contributing values and `finalize` scans for the
168
+ * new minimum). Consumers with very large result sets and frequent
169
+ * removals of the current extremum should either accept the cost or
170
+ * wait for a future optimization.
171
+ */
172
+ declare function min(field: string, opts?: ReducerOptions<number>): Reducer<number | null, MinMaxState>;
173
+ /**
174
+ * Largest numeric value of a field across all matching records.
175
+ * Mirror of `min()` — see that doc for semantics, null-on-empty
176
+ * behavior, and the O(N) removal caveat.
177
+ */
178
+ declare function max(field: string, opts?: ReducerOptions<number>): Reducer<number | null, MinMaxState>;
179
+
180
+ /**
181
+ * Aggregate execution — the runtime behind `Query.aggregate()`.
182
+ *
183
+ * takes an `AggregateSpec` (a record of named reducers
184
+ * built from `reducers.ts`) and runs every reducer over the records
185
+ * produced by the underlying query. Two terminal surfaces:
186
+ *
187
+ * - `.run(): R` — synchronous one-shot reduction. Matches the
188
+ * existing `Query.toArray()` / `.first()` / `.count()` style.
189
+ * - `.live(): LiveAggregation<R>` — reactive primitive that
190
+ * re-runs the reduction whenever the query's source notifies of
191
+ * a change. uses naive full re-run; incremental delta
192
+ * maintenance is admitted by the reducer protocol (`remove()`)
193
+ * but not wired to the executor yet — a follow-up optimization
194
+ * can switch from full re-run to delta-based without breaking
195
+ * the public API. Consumers get correct, reactive values today.
196
+ *
197
+ * The `Aggregation<R>` wrapper is deliberately tiny — it exists so
198
+ * `.aggregate(spec)` can be chained with either `.run()` or `.live()`
199
+ * without the builder needing two separate terminal methods. It
200
+ * holds the closure over the query execution (produces the current
201
+ * matching record set) and the spec, and stitches them together in
202
+ * either mode.
203
+ *
204
+ * This file depends ONLY on `reducers.ts` — it has no knowledge of
205
+ * the `Query` class. Tests can therefore exercise the reduction
206
+ * surface with plain record arrays, without spinning up a Collection.
207
+ */
208
+
209
+ /**
210
+ * A named set of reducers, keyed by output field name. Each key
211
+ * becomes a field on the aggregated result.
212
+ *
213
+ * ```ts
214
+ * const spec = {
215
+ * total: sum('amount'),
216
+ * n: count(),
217
+ * avgAmount: avg('amount'),
218
+ * }
219
+ * ```
220
+ */
221
+ type AggregateSpec = Readonly<Record<string, Reducer<unknown, unknown>>>;
222
+ /**
223
+ * Map an `AggregateSpec` to its reduced result shape — each key
224
+ * carries the finalized result type from its reducer. A spec built
225
+ * from `{ total: sum('amount'), n: count() }` yields a result of
226
+ * `{ total: number, n: number }`.
227
+ *
228
+ * This uses a mapped type with a conditional to extract `R` from
229
+ * each `Reducer<R, _>`. The `infer` captures the user-visible result
230
+ * type, discarding the internal state type `S`.
231
+ */
232
+ type AggregateResult<Spec extends AggregateSpec> = {
233
+ [K in keyof Spec]: Spec[K] extends Reducer<infer R, unknown> ? R : never;
234
+ };
235
+ /**
236
+ * Pure reduction over a record array. Runs every reducer's
237
+ * `init → step* → finalize` pipeline exactly once over the records.
238
+ *
239
+ * Called by `Aggregation.run()` and by the live-mode refresh path.
240
+ * Exported for tests and for future `scan().aggregate()` reuse
241
+ * — the streaming path will call the same reducer protocol with a
242
+ * per-page loop instead of a single array.
243
+ */
244
+ declare function reduceRecords<Spec extends AggregateSpec>(records: readonly unknown[], spec: Spec): AggregateResult<Spec>;
245
+ /**
246
+ * A minimal reactive primitive for aggregation results.
247
+ *
248
+ * Same spirit as the `LiveQuery` in : frame-agnostic, a plain
249
+ * object with `value` / `error` fields and a `subscribe(cb)`
250
+ * notification channel that Vue / React / Solid adapters wrap in
251
+ * their own primitive. Intentionally NOT a Promise — aggregations
252
+ * have a well-defined "current value" at every instant, and the
253
+ * reactive consumer wants to read that value synchronously.
254
+ *
255
+ * Error semantics mirror `LiveQuery`: if a re-run throws, the
256
+ * previous successful `value` is preserved and the error is stored
257
+ * in `error` so consumers can render an error state without losing
258
+ * the last-known-good result. The throw does NOT propagate out of
259
+ * the source's change handler (which would tear down the upstream
260
+ * emitter).
261
+ *
262
+ * `stop()` tears down the upstream subscription. It is idempotent —
263
+ * calling it multiple times is safe — and subscribe calls after
264
+ * stop are no-ops (they immediately return a no-op unsubscribe).
265
+ * Always call `stop()` when done; Vue's `onUnmounted` is the
266
+ * canonical place. Raw consumers must do it themselves.
267
+ */
268
+ interface LiveAggregation<R> {
269
+ /** Current reduced value. Undefined only if the first compute threw. */
270
+ readonly value: R | undefined;
271
+ /** Last execution error, if any. Cleared on the next successful run. */
272
+ readonly error: unknown;
273
+ /** Notify on every recomputation (success or error). Returns unsubscribe. */
274
+ subscribe(cb: () => void): () => void;
275
+ /** Tear down the upstream subscription. Idempotent. */
276
+ stop(): void;
277
+ }
278
+ /**
279
+ * Upstream change-notification hook for live aggregation.
280
+ *
281
+ * Matches the shape that `QuerySource.subscribe` already uses — a
282
+ * single method that accepts a callback and returns an unsubscribe
283
+ * function. The `Aggregation` wrapper collects upstreams from the
284
+ * query's source and wires them into a single re-run trigger.
285
+ */
286
+ interface AggregationUpstream {
287
+ subscribe(cb: () => void): () => void;
288
+ }
289
+ /**
290
+ * Chainable wrapper returned by `Query.aggregate(spec)`. Holds the
291
+ * execute-records closure and the spec; terminal methods (`run`,
292
+ * `live`) stitch them together in either mode.
293
+ *
294
+ * Why a wrapper instead of two terminal methods on `Query` directly?
295
+ *
296
+ * The `.aggregate(spec)` call is where the spec is bound — both
297
+ * `.run()` and `.live()` need the same spec, and the consumer's
298
+ * fluent style is `query.where(...).aggregate(spec).run()` or
299
+ * `.aggregate(spec).live()`. Wrapping lets the spec be named once
300
+ * and reused for either terminal, and keeps the `Query` class
301
+ * from growing a pair of near-duplicate method overloads
302
+ * (`aggregateRun` / `aggregateLive`) that would be harder to
303
+ * discover.
304
+ */
305
+ declare class Aggregation<R> {
306
+ private readonly executeRecords;
307
+ private readonly spec;
308
+ private readonly upstreams;
309
+ constructor(executeRecords: () => readonly unknown[], spec: AggregateSpec, upstreams: readonly AggregationUpstream[]);
310
+ /**
311
+ * Execute the query and reduce the results synchronously.
312
+ * Returns the reduced shape matching the spec — e.g. a spec of
313
+ * `{ total: sum('amount'), n: count() }` returns
314
+ * `{ total: number, n: number }`.
315
+ */
316
+ run(): R;
317
+ /**
318
+ * Build a reactive `LiveAggregation<R>` that re-runs the reduction
319
+ * whenever any upstream source notifies of a change. The initial
320
+ * value is computed eagerly in the constructor, so consumers can
321
+ * read `live.value` immediately after calling `.live()`.
322
+ *
323
+ * Always call `live.stop()` when finished — it tears down the
324
+ * upstream subscriptions. Vue's `onUnmounted` is the canonical
325
+ * place.
326
+ *
327
+ * **Implementation note:** every upstream change triggers a full
328
+ * re-reduction. Incremental maintenance (O(1) per delta for
329
+ * sum/count/avg via the reducer protocol's `remove()` method) is a
330
+ * planned follow-up optimization — the protocol already supports
331
+ * it, but the executor doesn't drive it yet. Consumers get
332
+ * correct, reactive values today; future PRs can switch to
333
+ * delta-based maintenance without changing this API.
334
+ */
335
+ live(): LiveAggregation<R>;
336
+ }
337
+ /**
338
+ * Build a `LiveAggregation<V>` from a recompute closure and a list
339
+ * of upstreams. Exposed so sibling files in the query DSL
340
+ * (currently `groupby.ts`) can reuse the reactive primitive
341
+ * without reaching into `LiveAggregationImpl` directly. This keeps
342
+ * the implementation class private while still allowing planned
343
+ * composition with `.groupBy().aggregate().live()`.
344
+ */
345
+ declare function buildLiveAggregation<V>(recompute: () => V, upstreams: readonly AggregationUpstream[]): LiveAggregation<V>;
346
+
347
+ /**
348
+ * Pure fixed-point decimal core for the money descriptor.
349
+ *
350
+ * All conversion goes decimal-string ⇄ scaled `BigInt`. There is no
351
+ * floating-point arithmetic anywhere: a value like `123.45` becomes
352
+ * `12345n` purely by string manipulation, never by `value * 100` (which
353
+ * would reintroduce the very drift money() exists to eliminate). BigInt
354
+ * has no magnitude ceiling, so values past `Number.MAX_SAFE_INTEGER`
355
+ * stay exact end-to-end.
356
+ *
357
+ * This module knows nothing about currencies, descriptors, or storage —
358
+ * it is the isolated, exhaustively-tested arithmetic kernel.
359
+ */
360
+ type RoundingMode = 'half-up' | 'half-even' | 'half-down' | 'up' | 'down' | 'ceil' | 'floor';
361
+
362
+ /**
363
+ * All NOYDB error classes — a single import surface for `catch` blocks and
364
+ * `instanceof` checks.
365
+ *
366
+ * ## Class hierarchy
367
+ *
368
+ * ```
369
+ * Error
370
+ * └─ NoydbError (code: string)
371
+ * ├─ Crypto errors
372
+ * │ ├─ DecryptionError — AES-GCM tag failure
373
+ * │ ├─ TamperedError — ciphertext modified after write
374
+ * │ └─ InvalidKeyError — wrong passphrase / corrupt keyring
375
+ * ├─ Access errors
376
+ * │ ├─ NoAccessError — no DEK for this collection
377
+ * │ ├─ ReadOnlyError — ro permission, write attempted
378
+ * │ ├─ PermissionDeniedError — role too low for operation
379
+ * │ ├─ PrivilegeEscalationError — grant wider than grantor holds
380
+ * │ └─ StoreCapabilityError — optional store method missing
381
+ * ├─ Sync errors
382
+ * │ ├─ ConflictError — optimistic-lock version mismatch
383
+ * │ ├─ BundleVersionConflictError — bundle push rejected by remote
384
+ * │ └─ NetworkError — push/pull network failure
385
+ * ├─ Data errors
386
+ * │ ├─ NotFoundError — get(id) on missing record
387
+ * │ ├─ ValidationError — application-level guard failed
388
+ * │ └─ SchemaValidationError — Standard Schema v1 rejection
389
+ * ├─ Query errors
390
+ * │ ├─ JoinTooLargeError — join row ceiling exceeded
391
+ * │ ├─ CrossJoinTooLargeError — cross-join row ceiling exceeded
392
+ * │ ├─ CrossJoinSourceUnknownError — target collection not in vault
393
+ * │ ├─ DanglingReferenceError — strict ref() points at nothing
394
+ * │ ├─ GroupCardinalityError — groupBy bucket cap exceeded
395
+ * │ ├─ IndexRequiredError — lazy-mode query touches unindexed field
396
+ * │ ├─ IndexWriteFailureError — index side-car put/delete failed post-main
397
+ * │ ├─ UniqueConstraintError — duplicate value on unique index
398
+ * │ └─ UnsupportedIndexOptionError — unique+lazy or unique+crdt at registration
399
+ * ├─ i18n / Dictionary errors
400
+ * │ ├─ ReservedCollectionNameError
401
+ * │ ├─ DictKeyMissingError
402
+ * │ ├─ DictKeyInUseError
403
+ * │ ├─ MissingTranslationError
404
+ * │ ├─ LocaleNotSpecifiedError
405
+ * │ └─ TranslatorNotConfiguredError
406
+ * ├─ Backup errors
407
+ * │ ├─ BackupLedgerError — hash-chain verification failed
408
+ * │ └─ BackupCorruptedError — envelope hash mismatch in dump
409
+ * ├─ Bundle errors
410
+ * │ └─ BundleIntegrityError — .noydb body sha256 mismatch
411
+ * ├─ Session errors
412
+ * │ ├─ SessionExpiredError
413
+ * │ ├─ SessionNotFoundError
414
+ * │ └─ SessionPolicyError
415
+ * ├─ Snapshot errors
416
+ * │ └─ SnapshotNotFoundError — snapshot key absent from snapshot store
417
+ * └─ Computed field errors
418
+ * └─ ComputedFieldError — computed function threw during a write
419
+ * ```
420
+ *
421
+ * ## Catching all NOYDB errors
422
+ *
423
+ * ```ts
424
+ * import { NoydbError, InvalidKeyError, ConflictError } from '@noy-db/hub'
425
+ *
426
+ * try {
427
+ * await vault.unlock(passphrase)
428
+ * } catch (e) {
429
+ * if (e instanceof InvalidKeyError) { showBadPassphraseUI(); return }
430
+ * if (e instanceof NoydbError) { logToSentry(e.code, e); return }
431
+ * throw e // unexpected — re-throw
432
+ * }
433
+ * ```
434
+ *
435
+ * @module
436
+ */
437
+ /**
438
+ * Base class for all NOYDB errors.
439
+ *
440
+ * Every error thrown by `@noy-db/hub` extends this class, so consumers can
441
+ * catch all NOYDB errors in a single `catch (e) { if (e instanceof NoydbError) ... }`
442
+ * block. The `code` field is a machine-readable string (e.g. `'DECRYPTION_FAILED'`)
443
+ * suitable for `switch` statements and logging pipelines.
444
+ */
445
+ declare class NoydbError extends Error {
446
+ /** Machine-readable error code. Stable across library versions. */
447
+ readonly code: string;
448
+ constructor(code: string, message: string);
449
+ }
450
+ /**
451
+ * Thrown when AES-GCM decryption fails.
452
+ *
453
+ * The most common cause is a wrong passphrase or a corrupted ciphertext.
454
+ * A `DecryptionError` at the wrong passphrase level is caught internally
455
+ * and re-thrown as `InvalidKeyError` — so in practice this surfaces for
456
+ * per-record corruption rather than authentication failures.
457
+ */
458
+ declare class DecryptionError extends NoydbError {
459
+ constructor(message?: string);
460
+ }
461
+ /**
462
+ * Thrown when GCM tag verification fails, indicating the ciphertext was
463
+ * modified after encryption.
464
+ *
465
+ * AES-256-GCM is authenticated encryption — the tag over the ciphertext
466
+ * is checked on every decrypt. If any byte was flipped (accidental
467
+ * corruption or deliberate tampering), decryption throws this error.
468
+ * Treat it as a security alert: the stored bytes are not what NOYDB wrote.
469
+ */
470
+ declare class TamperedError extends NoydbError {
471
+ constructor(message?: string);
472
+ }
473
+ /**
474
+ * Thrown when key unwrapping fails, typically because the passphrase is wrong
475
+ * or the keyring file is corrupted.
476
+ *
477
+ * NOYDB uses AES-KW (RFC 3394) to wrap DEKs with the KEK. If AES-KW
478
+ * unwrapping fails, it means either the KEK was derived from the wrong
479
+ * passphrase (PBKDF2 with 600K iterations) or the keyring bytes are
480
+ * corrupted. This is the error shown to the user on a failed unlock attempt.
481
+ */
482
+ declare class InvalidKeyError extends NoydbError {
483
+ constructor(message?: string);
484
+ }
485
+ /**
486
+ * Thrown when a keyring's wrapped-DEK set unwraps partially — at least
487
+ * one DEK succeeds (proving the KEK is correct) but at least one fails.
488
+ * The passphrase is right; the failed entries are corrupted.
489
+ *
490
+ * This is distinct from {@link InvalidKeyError} so that
491
+ * `NoydbOptions.onInvalidKey: 'reset'` does NOT fire — resetting on
492
+ * partial corruption would destroy the still-valid DEKs and the data
493
+ * they protect, which is silent data loss in response to a feature
494
+ * designed for stale-credential recovery.
495
+ */
496
+ declare class KeyringCorruptError extends NoydbError {
497
+ readonly failedCollections: readonly string[];
498
+ readonly intactCount: number;
499
+ constructor(opts: {
500
+ failedCollections: readonly string[];
501
+ intactCount: number;
502
+ message?: string;
503
+ });
504
+ }
505
+ /**
506
+ * Thrown when the authenticated user does not have a DEK for the requested
507
+ * collection — i.e. the collection is not in their keyring at all.
508
+ *
509
+ * This is the "no key for this door" error. It is different from
510
+ * `ReadOnlyError` (user has a key but it only grants ro) and from
511
+ * `PermissionDeniedError` (user's role doesn't allow the operation).
512
+ */
513
+ declare class NoAccessError extends NoydbError {
514
+ constructor(message?: string);
515
+ }
516
+ /**
517
+ * Thrown when a user with read-only (`ro`) permission attempts a write
518
+ * operation (`put` or `delete`) on a collection.
519
+ *
520
+ * The user has a DEK for the collection (they can decrypt and read), but
521
+ * their keyring grants only `ro`. To fix: re-grant the user with `rw`
522
+ * permission, or do not attempt writes as a viewer/client role.
523
+ */
524
+ declare class ReadOnlyError extends NoydbError {
525
+ constructor(message?: string);
526
+ }
527
+ /**
528
+ * Thrown when a write is attempted against a historical view produced
529
+ * by `vault.at(timestamp)`. Time-machine views are read-only by
530
+ * contract — mutating the past would require either the shadow-vault
531
+ * mechanism or a ledger-history rewrite (which breaks
532
+ * the tamper-evidence guarantee).
533
+ *
534
+ * Distinct from {@link ReadOnlyError} (keyring-level) and
535
+ * {@link PermissionDeniedError} (role-level): this error is about the
536
+ * *view* being historical, independent of the caller's permissions.
537
+ */
538
+ declare class ReadOnlyAtInstantError extends NoydbError {
539
+ constructor(operation: string, timestamp: string);
540
+ }
541
+ /**
542
+ * Thrown when a write is attempted against a shadow-vault frame
543
+ * produced by `vault.frame()`. Frames are read-only by contract —
544
+ * the use case is screen-sharing / demos / compliance review where
545
+ * the operator wants to prevent accidental edits.
546
+ *
547
+ * Behavioural enforcement only — the underlying keyring still holds
548
+ * write-capable DEKs. See {@link VaultFrame} for the full caveat.
549
+ */
550
+ declare class ReadOnlyFrameError extends NoydbError {
551
+ constructor(operation: string);
552
+ }
553
+ /**
554
+ * Thrown when the authenticated user's role does not permit the requested
555
+ * operation — e.g. a `viewer` calling `grantAccess()`, or an `operator`
556
+ * calling `rotateKeys()`.
557
+ *
558
+ * This is a role-level check (what the user's role allows), distinct from
559
+ * `NoAccessError` (collection not in keyring) and `ReadOnlyError` (in
560
+ * keyring, but write not allowed).
561
+ */
562
+ declare class PermissionDeniedError extends NoydbError {
563
+ constructor(message?: string);
564
+ }
565
+ /**
566
+ * Thrown when an `@noy-db/as-*` export is attempted without the
567
+ * required capability bit on the invoking keyring.
568
+ *
569
+ * Two sub-cases discriminated by the `tier` field:
570
+ *
571
+ * - `tier: 'plaintext'` — a plaintext-tier export (`as-xlsx`,
572
+ * `as-csv`, `as-blob`, `as-zip`, …) was attempted but the
573
+ * keyring's `exportCapability.plaintext` does not include the
574
+ * requested `format` (nor the `'*'` wildcard). Default for every
575
+ * role is `plaintext: []` — the owner must positively grant.
576
+ * - `tier: 'bundle'` — an encrypted `as-noydb` bundle export was
577
+ * attempted but the keyring's `exportCapability.bundle` is
578
+ * `false`. Default for `owner`/`admin` is `true`; for
579
+ * `operator`/`viewer`/`client` it is `false`.
580
+ *
581
+ * Distinct from `PermissionDeniedError` (role-level check) and
582
+ * `NoAccessError` (collection not readable). Surfaces separately so
583
+ * UI layers can show a "request the export capability from your
584
+ * admin" flow rather than a generic permission error.
585
+ */
586
+ declare class ExportCapabilityError extends NoydbError {
587
+ readonly tier: 'plaintext' | 'bundle';
588
+ readonly format?: string;
589
+ readonly userId: string;
590
+ constructor(opts: {
591
+ tier: 'plaintext' | 'bundle';
592
+ userId: string;
593
+ format?: string;
594
+ message?: string;
595
+ });
596
+ }
597
+ /**
598
+ * Thrown when a keyring file's `expires_at` cutoff has passed.
599
+ * Surfaced by `loadKeyring` before any DEK unwrap is attempted —
600
+ * past the cutoff the slot refuses to open even with the right
601
+ * passphrase. Distinct from PBKDF2 / unwrap errors so consumer code
602
+ * can show a precise "this bundle slot has expired" message instead
603
+ * of the generic decryption-failure UX.
604
+ *
605
+ * Used predominantly on `BundleRecipient` slots produced by
606
+ * `writeNoydbBundle({ recipients: [...] })` to time-box audit access.
607
+ */
608
+ declare class KeyringExpiredError extends NoydbError {
609
+ readonly userId: string;
610
+ readonly expiresAt: string;
611
+ constructor(opts: {
612
+ userId: string;
613
+ expiresAt: string;
614
+ });
615
+ }
616
+ /**
617
+ * Thrown when an `@noy-db/as-*` import is attempted but the invoking
618
+ * keyring lacks the required import-capability bit.
619
+ *
620
+ * - `tier: 'plaintext'` — a plaintext-tier import (`as-csv`, `as-json`,
621
+ * `as-ndjson`, `as-zip`, …) was attempted but the keyring's
622
+ * `importCapability.plaintext` does not include the requested
623
+ * `format` (nor the `'*'` wildcard).
624
+ * - `tier: 'bundle'` — a `.noydb` bundle import was attempted but the
625
+ * keyring's `importCapability.bundle` is not `true`.
626
+ *
627
+ * Default for every role on every dimension is closed — owners and
628
+ * admins must positively grant the capability. Distinct from
629
+ * `PermissionDeniedError` and `NoAccessError` so UI layers can show a
630
+ * specific "request the import capability" flow.
631
+ */
632
+ declare class ImportCapabilityError extends NoydbError {
633
+ readonly tier: 'plaintext' | 'bundle';
634
+ readonly format?: string;
635
+ readonly userId: string;
636
+ constructor(opts: {
637
+ tier: 'plaintext' | 'bundle';
638
+ userId: string;
639
+ format?: string;
640
+ message?: string;
641
+ });
642
+ }
643
+ /**
644
+ * Thrown when a grant would give the grantee a permission the grantor
645
+ * does not themselves hold — the "admin cannot grant what admin cannot
646
+ * do" rule from the admin-delegation work.
647
+ *
648
+ * Distinct from `PermissionDeniedError` so callers can tell the two
649
+ * cases apart in logs and tests:
650
+ *
651
+ * - `PermissionDeniedError` — "you are not allowed to perform this
652
+ * operation at all" (wrong role).
653
+ * - `PrivilegeEscalationError` — "you are allowed to grant, but not
654
+ * with these specific permissions" (widening attempt).
655
+ *
656
+ * Under the admin model the grantee of an admin-grants-admin call
657
+ * inherits the caller's entire DEK set by construction, so this error
658
+ * is structurally unreachable in typical flows. The check and error
659
+ * class exist so that future per-collection admin scoping cannot
660
+ * accidentally bypass the subset rule — the guard is already wired in.
661
+ *
662
+ * `offendingCollection` carries the first collection name that failed
663
+ * the subset check, to make the violation actionable in error output.
664
+ */
665
+ /**
666
+ * Thrown when a caller invokes an API that requires an optional
667
+ * store capability the active store does not implement.
668
+ *
669
+ * Today the only call site is `Noydb.listAccessibleVaults()`,
670
+ * which depends on the optional `NoydbStore.listVaults()`
671
+ * method. The error message names the missing method and the calling
672
+ * API so consumers know exactly which combination is unsupported,
673
+ * and the `capability` field is machine-readable so library code can
674
+ * pattern-match in catch blocks (e.g. fall back to a candidate-list
675
+ * shape).
676
+ *
677
+ * The class lives in `errors.ts` rather than as a generic
678
+ * `ValidationError` because the diagnostic shape is different: a
679
+ * `ValidationError` says "the inputs you passed are wrong"; this
680
+ * error says "the inputs are fine, but the store you wired up
681
+ * doesn't support what you're asking for." Different fix, different
682
+ * documentation.
683
+ */
684
+ declare class StoreCapabilityError extends NoydbError {
685
+ /** The store method/capability that was missing. */
686
+ readonly capability: string;
687
+ constructor(capability: string, callerApi: string, storeName?: string);
688
+ }
689
+ declare class PrivilegeEscalationError extends NoydbError {
690
+ readonly offendingCollection: string;
691
+ constructor(offendingCollection: string, message?: string);
692
+ }
693
+ /**
694
+ * Thrown by `Collection.put` / `.delete` when the target record's
695
+ * envelope `_ts` falls within a closed accounting period.
696
+ *
697
+ * Distinct from `ReadOnlyError` (keyring-level), `ReadOnlyAtInstantError`
698
+ * (historical view), and `ReadOnlyFrameError` (shadow vault): this
699
+ * error is about the STORED RECORD being sealed by an operator call
700
+ * to `vault.closePeriod()`, independent of caller permissions or
701
+ * view type. The `periodName` and `endDate` fields name the sealing
702
+ * period so audit UIs can surface a "this record is locked in
703
+ * FY2026-Q1 (closed 2026-03-31)" message without parsing the error
704
+ * string.
705
+ *
706
+ * To apply a correction after close, book a compensating entry in a
707
+ * new period rather than unlocking the old one. Re-opening a closed
708
+ * period is deliberately unsupported.
709
+ */
710
+ declare class PeriodClosedError extends NoydbError {
711
+ readonly periodName: string;
712
+ readonly endDate: string;
713
+ readonly recordTs: string;
714
+ constructor(periodName: string, endDate: string, recordTs: string);
715
+ }
716
+ /**
717
+ * Thrown when a `put()` or `delete()` is rejected by a guard's `check`
718
+ * function. The `reason` is the message the guard supplied — typically a
719
+ * short business description (e.g. "invoice is issued"). The full
720
+ * collection + id are surfaced so audit UIs can link back to the record.
721
+ */
722
+ declare class RecordLockedError extends NoydbError {
723
+ readonly collection: string;
724
+ readonly id: string;
725
+ readonly reason: string;
726
+ constructor(collection: string, id: string, reason: string);
727
+ }
728
+ /**
729
+ * Thrown when a `put()` changes one or more fields that are frozen by a
730
+ * `frozenFields` guard. The `fields` list contains the specific paths
731
+ * that were detected as changed.
732
+ */
733
+ declare class FieldFrozenError extends NoydbError {
734
+ readonly collection: string;
735
+ readonly id: string;
736
+ readonly fields: readonly string[];
737
+ constructor(collection: string, id: string, fields: readonly string[]);
738
+ }
739
+ /**
740
+ * Thrown by an amendment invariant when the proposed change-set violates
741
+ * the declared business rule (e.g. disbursement total not preserved).
742
+ * Triggers a full transaction rollback via the existing revert pass.
743
+ */
744
+ declare class InvariantError extends NoydbError {
745
+ constructor(message: string);
746
+ }
747
+ /**
748
+ * Thrown at `withTransactions({ amendment: true })` open if the caller's
749
+ * role is not in the guard's allowed amendment roles. Fail-fast: thrown
750
+ * before any writes are attempted.
751
+ */
752
+ declare class AmendmentForbiddenError extends NoydbError {
753
+ readonly userId: string;
754
+ readonly role: string;
755
+ constructor(userId: string, role: string);
756
+ }
757
+ /**
758
+ * Thrown by `listUsersWithEnvelopes` when the vault's user directory
759
+ * has been disabled (via `db.setDirectoryEnabled(vault, false)`) and
760
+ * the caller's role is neither `owner` nor `admin`. Owner/admin can
761
+ * still enumerate users — the toggle is a UX privacy switch, not a
762
+ * security boundary.
763
+ *
764
+ * Honest caveat: this is a UX flag, not a privacy guarantee. The
765
+ * envelope ciphertext is still in the store, the keyring file is
766
+ * still listed at `_keyring/*`, and anyone with direct store read
767
+ * access can count keyrings without going through the hub. See
768
+ * `docs/subsystems/user-envelope.md` → "Directory visibility".
769
+ */
770
+ declare class DirectoryDisabledError extends NoydbError {
771
+ readonly vault: string;
772
+ constructor(vault: string);
773
+ }
774
+ /**
775
+ * Thrown when a user tries to act at a tier they are not cleared for.
776
+ *
777
+ * This is the umbrella error for tier write refusals:
778
+ * - `put({ tier: N })` when the user's keyring lacks tier-N DEK.
779
+ * - `elevate(id, N)` when the caller cannot reach tier N.
780
+ *
781
+ * Distinct from `TierAccessDeniedError` which covers *read* refusals on
782
+ * the invisibility/ghost path.
783
+ */
784
+ declare class TierNotGrantedError extends NoydbError {
785
+ readonly tier: number;
786
+ readonly collection: string;
787
+ constructor(collection: string, tier: number);
788
+ }
789
+ /**
790
+ * Thrown when an elevated-handle operation runs after the elevation's
791
+ * TTL expired. Reads continue at the original tier; only writes
792
+ * through the scoped handle flip to throwing once expired.
793
+ */
794
+ declare class ElevationExpiredError extends NoydbError {
795
+ readonly tier: number;
796
+ readonly expiresAt: number;
797
+ constructor(opts: {
798
+ tier: number;
799
+ expiresAt: number;
800
+ });
801
+ }
802
+ /**
803
+ * Thrown by `vault.elevate(...)` when an elevation is already active
804
+ * on the vault. Adopters must `release()` the existing handle before
805
+ * starting a new elevation.
806
+ */
807
+ declare class AlreadyElevatedError extends NoydbError {
808
+ readonly activeTier: number;
809
+ constructor(activeTier: number);
810
+ }
811
+ /**
812
+ * Thrown when `demote()` is called by someone who is not the original
813
+ * elevator and not an owner.
814
+ */
815
+ declare class TierDemoteDeniedError extends NoydbError {
816
+ constructor(id: string, tier: number);
817
+ }
818
+ /**
819
+ * Thrown when `db.delegate()` is called against a user that has no
820
+ * keyring in the target vault — the delegation token cannot be
821
+ * constructed without the target user's KEK wrap.
822
+ */
823
+ declare class DelegationTargetMissingError extends NoydbError {
824
+ readonly toUser: string;
825
+ constructor(toUser: string);
826
+ }
827
+ /**
828
+ * Thrown when a `put()` detects an optimistic concurrency conflict.
829
+ *
830
+ * NOYDB uses version numbers (`_v`) for optimistic locking. If a `put()`
831
+ * is called with `expectedVersion: N` but the stored record is at version
832
+ * `M ≠ N`, the write is rejected and the caller must re-read, re-apply their
833
+ * change, and retry. The `version` field carries the actual stored version
834
+ * so callers can decide whether to retry or surface the conflict to the user.
835
+ */
836
+ declare class ConflictError extends NoydbError {
837
+ /** The actual stored version at the time of conflict. */
838
+ readonly version: number;
839
+ constructor(version: number, message?: string);
840
+ }
841
+ /**
842
+ * Thrown by `LedgerStore.append()` after exhausting its CAS retry
843
+ * budget under multi-writer contention. Two browser tabs, a
844
+ * web app + an offline mobile peer, or a server worker pool all
845
+ * producing ledger entries against the same vault can race on the
846
+ * "read head, write head+1" cycle; the optimistic-CAS retry loop
847
+ * resolves the race for `casAtomic: true` stores, but pathological
848
+ * contention (or a buggy peer) can still exhaust the budget. When
849
+ * that happens, the chain is intact — the failed writer simply
850
+ * couldn't claim a slot. Caller's choice whether to retry, queue,
851
+ * or surface the failure to the user.
852
+ */
853
+ declare class LedgerContentionError extends NoydbError {
854
+ readonly attempts: number;
855
+ constructor(attempts: number);
856
+ }
857
+ /**
858
+ * Thrown by `vault.sequence(name).next()` after exhausting its CAS retry
859
+ * budget under contention. The counter is intact; the caller may retry.
860
+ */
861
+ declare class SequenceContentionError extends NoydbError {
862
+ readonly sequence: string;
863
+ readonly attempts: number;
864
+ constructor(sequence: string, attempts: number);
865
+ }
866
+ /**
867
+ * Thrown by `vault.sequence(name).next()` when the backing store is not
868
+ * CAS-capable (`capabilities.casAtomic !== true`). Gap-free numbering
869
+ * requires single-authority serialization, which an offline / non-CAS
870
+ * store cannot provide — this is a deliberate online-only wall.
871
+ */
872
+ declare class SequenceOfflineError extends NoydbError {
873
+ constructor();
874
+ }
875
+ /**
876
+ * Thrown when a bundle push is rejected because the remote has been updated
877
+ * since the local bundle was last pulled.
878
+ *
879
+ * Unlike `ConflictError` (per-record), this is a whole-bundle conflict —
880
+ * the remote's bundle handle has changed. The caller must pull the new
881
+ * bundle, merge, and re-push. `remoteVersion` is the handle of the newer
882
+ * remote bundle for use in diagnostics.
883
+ */
884
+ declare class BundleVersionConflictError extends NoydbError {
885
+ /** The bundle handle of the newer remote version that rejected the push. */
886
+ readonly remoteVersion: string;
887
+ constructor(remoteVersion: string, message?: string);
888
+ }
889
+ /**
890
+ * Thrown when a sync operation (push or pull) fails due to a network error.
891
+ *
892
+ * NOYDB's offline-first design means network errors are expected during sync.
893
+ * Callers should catch `NetworkError`, surface connectivity status in the UI,
894
+ * and rely on the `SyncScheduler` to retry when connectivity is restored.
895
+ */
896
+ declare class NetworkError extends NoydbError {
897
+ constructor(message?: string);
898
+ }
899
+ /**
900
+ * Thrown when `collection.get(id)` is called with an ID that does not exist.
901
+ *
902
+ * NOYDB collections are memory-first, so this error is synchronous and cheap —
903
+ * it does not make a network round-trip. Callers that expect the record to be
904
+ * absent should use `collection.getOrNull(id)` instead.
905
+ */
906
+ declare class NotFoundError extends NoydbError {
907
+ constructor(message?: string);
908
+ }
909
+ /**
910
+ * Thrown when application-level validation fails before encryption.
911
+ *
912
+ * Distinct from `SchemaValidationError` (Standard Schema v1 validator)
913
+ * and `MissingTranslationError` (i18nText). `ValidationError` is the
914
+ * general-purpose validation base — use it for custom guards in `put()`
915
+ * hooks or store middleware.
916
+ */
917
+ declare class ValidationError extends NoydbError {
918
+ constructor(message?: string);
919
+ }
920
+ /**
921
+ * Thrown when a Standard Schema v1 validator rejects a record on
922
+ * `put()` (input validation) or on read (output validation). Carries
923
+ * the raw issue list so callers can render field-level errors.
924
+ *
925
+ * `direction` distinguishes the two cases:
926
+ * - `'input'`: the user passed bad data into `put()`. This is a
927
+ * normal error case that application code should handle — typically
928
+ * by showing validation messages in the UI.
929
+ * - `'output'`: stored data does not match the current schema. This
930
+ * indicates a schema drift (the schema was changed without
931
+ * migrating the existing records) and should be treated as a bug
932
+ * — the application should not swallow it silently.
933
+ *
934
+ * The `issues` type is deliberately `readonly unknown[]` on this class
935
+ * so that `errors.ts` doesn't need to import from `schema.ts` (and
936
+ * create a dependency cycle). Callers who know they're holding a
937
+ * `SchemaValidationError` can cast to the more precise
938
+ * `readonly StandardSchemaV1Issue[]` from `schema.ts`.
939
+ */
940
+ declare class SchemaValidationError extends NoydbError {
941
+ readonly issues: readonly unknown[];
942
+ readonly direction: 'input' | 'output';
943
+ constructor(message: string, issues: readonly unknown[], direction: 'input' | 'output');
944
+ }
945
+ /** Base for schema-evolution strategy rejections. */
946
+ declare class SchemaUpdateError extends NoydbError {
947
+ constructor(code: string, message: string);
948
+ }
949
+ /** A non-additive schema change was rejected by the `additiveOnly()` strategy. */
950
+ declare class NonAdditiveSchemaChangeError extends SchemaUpdateError {
951
+ constructor(message: string);
952
+ }
953
+ /** A schema change was rejected by the `lockSchema()` strategy. */
954
+ declare class SchemaLockedError extends SchemaUpdateError {
955
+ constructor(message: string);
956
+ }
957
+ /** Write attempted while a schema cutover fence is up (draining/migrating, or this collection has a pending cutover). */
958
+ declare class SchemaFenceError extends SchemaUpdateError {
959
+ constructor(message: string);
960
+ }
961
+ /** Write attempted by a client whose generation snapshot is behind the live fence — reload required. */
962
+ declare class MigrationRequiredError extends SchemaUpdateError {
963
+ constructor(message: string);
964
+ }
965
+ /** A coordinated cutover timed out waiting for active clients to quiesce. */
966
+ declare class QuiesceTimeoutError extends SchemaUpdateError {
967
+ constructor(message: string);
968
+ }
969
+ /**
970
+ * Thrown when `.groupBy().aggregate()` produces more than the hard
971
+ * cardinality cap (default 100_000 groups)..
972
+ *
973
+ * The cap exists because `.groupBy()` materializes one bucket per
974
+ * distinct key value in memory, and runaway cardinality — a groupBy
975
+ * on a high-uniqueness field like `id` or `createdAt` — is almost
976
+ * always a query mistake rather than legitimate use. A hard error is
977
+ * better than silent OOM: the consumer sees an actionable message
978
+ * naming the field and the observed cardinality, with guidance to
979
+ * either narrow the query with `.where()` or accept the ceiling
980
+ * override.
981
+ *
982
+ * A separate one-shot warning fires at 10% of the cap (10_000
983
+ * groups) so consumers get a heads-up before the hard error — same
984
+ * pattern as `JoinTooLargeError` and the `.join()` row ceiling.
985
+ *
986
+ * **Not overridable in.** The 100k cap is a fixed constant so
987
+ * the failure mode is consistent across the codebase; a
988
+ * `{ maxGroups }` override can be added later without a break if a
989
+ * real consumer asks.
990
+ */
991
+ declare class GroupCardinalityError extends NoydbError {
992
+ /** The field being grouped on. */
993
+ readonly field: string;
994
+ /** Observed number of distinct groups at the moment the cap tripped. */
995
+ readonly cardinality: number;
996
+ /** The cap that was exceeded. */
997
+ readonly maxGroups: number;
998
+ constructor(field: string, cardinality: number, maxGroups: number);
999
+ }
1000
+ /**
1001
+ * Thrown in lazy mode when a `.query()` / `.where()` / `.orderBy()` clause
1002
+ * references a field that does not have a declared index.
1003
+ *
1004
+ * Lazy-mode queries only work when every touched field is indexed.
1005
+ * This is deliberate — silent scan-fallback would hide the performance
1006
+ * cliff that lazy-mode indexes exist to prevent.
1007
+ *
1008
+ * Payload:
1009
+ * - `collection` — name of the collection queried
1010
+ * - `touchedFields` — every field referenced by the query (filter + order)
1011
+ * - `missingFields` — subset of `touchedFields` that have no declared index
1012
+ */
1013
+ declare class IndexRequiredError extends NoydbError {
1014
+ readonly collection: string;
1015
+ readonly touchedFields: readonly string[];
1016
+ readonly missingFields: readonly string[];
1017
+ constructor(args: {
1018
+ collection: string;
1019
+ touchedFields: readonly string[];
1020
+ missingFields: readonly string[];
1021
+ });
1022
+ }
1023
+ /**
1024
+ * Thrown by `Collection.put()` when writing a record would violate a
1025
+ * unique-index constraint — the same field value (or composite field
1026
+ * tuple) is already held by a *different* record id in the collection.
1027
+ *
1028
+ * Properties:
1029
+ * - `collection` — name of the collection the write was targeting
1030
+ * - `recordId` — the id of the record being written (the would-be violator)
1031
+ * - `fields` — the constrained field(s), e.g. `['taxId']` or `['workerId','employerEntityId']`
1032
+ * - `conflictingId` — the id of the record already holding the value
1033
+ *
1034
+ * Null-distinct semantics: if any constrained field is `null`/`undefined`,
1035
+ * the row is exempt (the constraint does not fire). This matches standard
1036
+ * SQL NULL-distinct behavior.
1037
+ */
1038
+ declare class UniqueConstraintError extends NoydbError {
1039
+ readonly collection: string;
1040
+ readonly recordId: string;
1041
+ readonly fields: readonly string[];
1042
+ readonly conflictingId: string;
1043
+ constructor(collection: string, recordId: string, fields: readonly string[], conflictingId: string);
1044
+ }
1045
+ /**
1046
+ * Thrown at collection registration when an index option is declared that
1047
+ * is incompatible with the collection's operating mode.
1048
+ *
1049
+ * Currently covers two cases:
1050
+ * - `unique: true` on a lazy-mode (`prefetch: false`) collection — lazy mode
1051
+ * does not pre-load all records, so an in-memory uniqueness map cannot be
1052
+ * maintained reliably.
1053
+ * - `unique: true` on a CRDT collection (`crdt: 'lww-map' | 'rga' | 'yjs'`) —
1054
+ * CRDT put() short-circuits the unique-constraint check, so enforcement would
1055
+ * silently not fire.
1056
+ *
1057
+ * Both cases are caught eagerly at `vault.collection()` time so the developer
1058
+ * sees the incompatibility immediately rather than shipping silently-ignored
1059
+ * constraints.
1060
+ *
1061
+ * The `option` field names the incompatible option (`'unique'`) so catch blocks
1062
+ * can pattern-match without inspecting the error message.
1063
+ */
1064
+ declare class UnsupportedIndexOptionError extends NoydbError {
1065
+ readonly option: string;
1066
+ constructor(option: string, message: string);
1067
+ }
1068
+ /**
1069
+ * Thrown (or surfaced via the `index:write-partial` event) when one or more
1070
+ * per-indexed-field side-car writes fail after the main record write has
1071
+ * already succeeded.
1072
+ *
1073
+ * Not thrown out of `.put()` / `.delete()` directly — those succeed when the
1074
+ * main record succeeds. Instead, `IndexWriteFailureError` instances are collected
1075
+ * into the session-scoped reconcile queue and emitted on the Collection
1076
+ * emitter as `index:write-partial`.
1077
+ *
1078
+ * Payload:
1079
+ * - `recordId` — the id of the main record whose side-car writes failed
1080
+ * - `field` — the indexed field whose side-car write failed
1081
+ * - `op` — `'put'` or `'delete'`, indicating which mutation was in flight
1082
+ * - `cause` — the underlying error from the store
1083
+ */
1084
+ declare class IndexWriteFailureError extends NoydbError {
1085
+ readonly recordId: string;
1086
+ readonly field: string;
1087
+ readonly op: 'put' | 'delete';
1088
+ readonly cause: unknown;
1089
+ constructor(args: {
1090
+ recordId: string;
1091
+ field: string;
1092
+ op: 'put' | 'delete';
1093
+ cause: unknown;
1094
+ });
1095
+ }
1096
+ /**
1097
+ * Thrown by `readNoydbBundle()` when the body bytes don't match
1098
+ * the integrity hash declared in the bundle header — i.e. someone
1099
+ * modified the bytes between write and read.
1100
+ *
1101
+ * Distinct from a generic `Error` (which would be thrown for
1102
+ * format violations like a missing magic prefix or malformed
1103
+ * header JSON) so consumers can pattern-match the corruption case
1104
+ * and handle it differently from a producer bug. A
1105
+ * `BundleIntegrityError` indicates "the bytes you got are not
1106
+ * what was written"; a plain `Error` from `parsePrefixAndHeader`
1107
+ * indicates "what was written wasn't a valid bundle in the first
1108
+ * place."
1109
+ *
1110
+ * Also thrown when decompression fails after the integrity hash
1111
+ * passed — that's a producer bug (the wrong algorithm byte was
1112
+ * written) but it surfaces with the same error class because the
1113
+ * end result is "the body cannot be turned back into a dump."
1114
+ */
1115
+ declare class BundleIntegrityError extends NoydbError {
1116
+ constructor(message: string);
1117
+ }
1118
+ /**
1119
+ * Thrown by `readNoydbBundle` when the bundle carries
1120
+ * sealed per-user passphrases but no supplied `SealingKeyProvider`
1121
+ * has a `.id` (= `pid`) matching the sealed entry's `pid`.
1122
+ *
1123
+ * Carries the failing pid + the user id so the recipient can
1124
+ * surface an actionable prompt:
1125
+ *
1126
+ * ```
1127
+ * BundleSealMismatchError: bundle carries sealed passphrase for user "alice"
1128
+ * under provider "macos-keychain:com.acme.app/alice@acme.example",
1129
+ * but no registered provider matches that pid.
1130
+ * ```
1131
+ *
1132
+ * Three resolution paths the message names (per foundation §11.9.4):
1133
+ *
1134
+ * 1. Configure a provider matching the pid and retry import.
1135
+ * 2. Pass `attemptUnsealAcrossProviders: true` to try each
1136
+ * registered provider regardless of pid.
1137
+ * 3. Inspect without unsealing — pass no `sealingProviders` to
1138
+ * receive the sealed entries unmodified for offline analysis.
1139
+ */
1140
+ declare class BundleSealMismatchError extends NoydbError {
1141
+ readonly userId: string;
1142
+ readonly pid: string;
1143
+ constructor(userId: string, pid: string);
1144
+ }
1145
+ /**
1146
+ * Thrown when `vault.collection()` is called with a name that is
1147
+ * reserved for NOYDB internal use (any name starting with `_dict_`).
1148
+ *
1149
+ * Dictionary collections are accessed exclusively via
1150
+ * `vault.dictionary(name)` — attempting to open one as a regular
1151
+ * collection would bypass the dictionary invariants (ACL, rename
1152
+ * tracking, reserved-name policy).
1153
+ */
1154
+ declare class ReservedCollectionNameError extends NoydbError {
1155
+ /** The rejected collection name. */
1156
+ readonly collectionName: string;
1157
+ constructor(collectionName: string);
1158
+ }
1159
+ /**
1160
+ * Thrown by `DictionaryHandle.get()` and `DictionaryHandle.delete()` when
1161
+ * the requested key does not exist in the dictionary.
1162
+ *
1163
+ * Distinct from `NotFoundError` (which is for data records) so callers
1164
+ * can distinguish "data record missing" from "dictionary key missing"
1165
+ * without inspecting error messages.
1166
+ */
1167
+ declare class DictKeyMissingError extends NoydbError {
1168
+ /** The dictionary name. */
1169
+ readonly dictionaryName: string;
1170
+ /** The key that was not found. */
1171
+ readonly key: string;
1172
+ constructor(dictionaryName: string, key: string);
1173
+ }
1174
+ /**
1175
+ * Thrown by `DictionaryHandle.delete()` in strict mode when the key to
1176
+ * be deleted is still referenced by one or more records.
1177
+ *
1178
+ * The caller must either rename the key first (the only sanctioned
1179
+ * mass-mutation path) or pass `{ mode: 'warn' }` to skip the check
1180
+ * (development only).
1181
+ */
1182
+ declare class DictKeyInUseError extends NoydbError {
1183
+ /** The dictionary name. */
1184
+ readonly dictionaryName: string;
1185
+ /** The key that is still referenced. */
1186
+ readonly key: string;
1187
+ /** Name of the first collection found to reference this key. */
1188
+ readonly usedBy: string;
1189
+ /** Number of records in `usedBy` that reference this key. */
1190
+ readonly count: number;
1191
+ constructor(dictionaryName: string, key: string, usedBy: string, count: number);
1192
+ }
1193
+ /**
1194
+ * Thrown by `Collection.put()` when an `i18nText` field is missing one
1195
+ * or more required translations.
1196
+ *
1197
+ * The `missing` array names each locale code that was absent from the
1198
+ * field value. The `field` property names the field so callers can
1199
+ * render a field-level error message without parsing the string.
1200
+ */
1201
+ declare class MissingTranslationError extends NoydbError {
1202
+ /** The field name whose translation(s) are missing. */
1203
+ readonly field: string;
1204
+ /** Locale codes that were required but absent. */
1205
+ readonly missing: readonly string[];
1206
+ constructor(field: string, missing: readonly string[], message?: string);
1207
+ }
1208
+ /**
1209
+ * Thrown when reading an `i18nText` field without specifying a locale —
1210
+ * either at the call site (`get(id, { locale })`) or on the vault
1211
+ * (`openVault(name, { locale })`).
1212
+ *
1213
+ * Also thrown when `resolveI18nText()` exhausts the fallback chain and
1214
+ * no translation is available for the requested locale.
1215
+ *
1216
+ * The `field` property names the field that triggered the error so the
1217
+ * caller can surface it in the UI.
1218
+ */
1219
+ declare class LocaleNotSpecifiedError extends NoydbError {
1220
+ /** The field name that required a locale. */
1221
+ readonly field: string;
1222
+ constructor(field: string, message?: string);
1223
+ }
1224
+ /**
1225
+ * Thrown at write time when an `i18nText` slot's value contains
1226
+ * characters outside the script set allowed for that locale, and the
1227
+ * field's `onScriptViolation` policy is `'reject'` (the default).
1228
+ *
1229
+ * Distinct from {@link MissingTranslationError} (write-shape) and
1230
+ * {@link LocaleNotSpecifiedError} (read-hole) so callers can tell a
1231
+ * wrong-script value from a missing one.
1232
+ */
1233
+ declare class ScriptViolationError extends NoydbError {
1234
+ /** The field whose value violated its script constraint. */
1235
+ readonly field: string;
1236
+ /** The locale slot (e.g. `'en'`) that was checked. */
1237
+ readonly locale: string;
1238
+ /** The Unicode scripts allowed for this slot. */
1239
+ readonly expected: readonly string[];
1240
+ /** A short sample of the offending characters, for diagnostics. */
1241
+ readonly sample: string;
1242
+ constructor(field: string, locale: string, expected: readonly string[], sample: string, message?: string);
1243
+ }
1244
+ /**
1245
+ * Thrown when a collection has an `i18nText` field with
1246
+ * `autoTranslate: true` but no `plaintextTranslator` was configured
1247
+ * on `createNoydb()`.
1248
+ *
1249
+ * The error is raised at `put()` time (not at schema construction) so
1250
+ * the mis-configuration is surfaced by the first write rather than
1251
+ * silently at startup.
1252
+ */
1253
+ declare class TranslatorNotConfiguredError extends NoydbError {
1254
+ /** The field that requested auto-translation. */
1255
+ readonly field: string;
1256
+ /** The collection the put was targeting. */
1257
+ readonly collection: string;
1258
+ constructor(field: string, collection: string);
1259
+ }
1260
+ /**
1261
+ * Thrown when `Vault.load()` finds that a backup's hash chain
1262
+ * doesn't verify, or that its embedded `ledgerHead.hash` doesn't
1263
+ * match the chain head reconstructed from the loaded entries.
1264
+ *
1265
+ * Distinct from `BackupCorruptedError` so callers can choose to
1266
+ * recover from one but not the other (e.g., a corrupted JSON file is
1267
+ * unrecoverable; a chain mismatch might mean the backup is from an
1268
+ * incompatible noy-db version).
1269
+ */
1270
+ declare class BackupLedgerError extends NoydbError {
1271
+ /** First-broken-entry index, if known. */
1272
+ readonly divergedAt?: number;
1273
+ constructor(message: string, divergedAt?: number);
1274
+ }
1275
+ /**
1276
+ * Thrown when `Vault.load()` finds that the backup's data
1277
+ * collection content doesn't match the ledger's recorded
1278
+ * `payloadHash`es. This is the "envelope was tampered with after
1279
+ * dump" detection — the chain itself can be intact, but if any
1280
+ * encrypted record bytes were swapped, this check catches it.
1281
+ */
1282
+ declare class BackupCorruptedError extends NoydbError {
1283
+ /** The (collection, id) pair whose envelope failed the hash check. */
1284
+ readonly collection: string;
1285
+ readonly id: string;
1286
+ constructor(collection: string, id: string, message: string);
1287
+ }
1288
+ /**
1289
+ * Thrown by partition-extraction primitives when the
1290
+ * transitive-closure walk fails — e.g. the FK graph is deeper than
1291
+ * `maxDepth`, signalling a runaway or unexpectedly cyclic graph.
1292
+ */
1293
+ declare class PartitionExtractionError extends NoydbError {
1294
+ constructor(message: string);
1295
+ }
1296
+ /**
1297
+ * Thrown by `adoptPartition` when the transfer seal can't be
1298
+ * opened — a wrong/short transfer key (AES-GCM auth-tag failure) or a
1299
+ * malformed sealed payload.
1300
+ */
1301
+ declare class TransferSealError extends NoydbError {
1302
+ constructor(message: string);
1303
+ }
1304
+ /**
1305
+ * Thrown when an adoption-lifecycle precondition fails — re-adopting a
1306
+ * partition already consumed in this store, or owner-creation on a
1307
+ * vault that isn't in the adopted-unowned state.
1308
+ */
1309
+ declare class AdoptionStateError extends NoydbError {
1310
+ constructor(message: string);
1311
+ }
1312
+ /** Document-attestation failures: undeclared field-schema, non-owner issue, missing field, signer failure. */
1313
+ declare class AttestationError extends NoydbError {
1314
+ constructor(message: string);
1315
+ }
1316
+ /**
1317
+ * Thrown by `resolveSession()` when the session token's `expiresAt`
1318
+ * timestamp is in the past. The session key is also removed from the
1319
+ * in-memory store when this is thrown, so retrying with the same sessionId
1320
+ * will produce `SessionNotFoundError`.
1321
+ *
1322
+ * Separate from `SessionNotFoundError` so callers can distinguish between
1323
+ * "session is gone" (key store cleared, tab reloaded) and "session is
1324
+ * still in the store but has exceeded its lifetime" (idle timeout, absolute
1325
+ * timeout, policy-driven expiry). The remediation differs: expired sessions
1326
+ * should prompt a fresh unlock; not-found sessions may indicate a bug or a
1327
+ * cross-tab scenario where the session was never established.
1328
+ */
1329
+ declare class SessionExpiredError extends NoydbError {
1330
+ readonly sessionId: string;
1331
+ constructor(sessionId: string);
1332
+ }
1333
+ /**
1334
+ * Thrown by `resolveSession()` when the session key cannot be found in
1335
+ * the module-level store. This happens when:
1336
+ * - The session was explicitly revoked via `revokeSession()`.
1337
+ * - The JS context was reloaded (tab navigation, page refresh, worker restart).
1338
+ * - `Noydb.close()` was called (which calls `revokeAllSessions()`).
1339
+ * - The sessionId is wrong or was generated by a different JS context.
1340
+ *
1341
+ * The session token (if the caller holds it) is permanently useless after
1342
+ * this error — the key is gone and cannot be recovered.
1343
+ */
1344
+ declare class SessionNotFoundError extends NoydbError {
1345
+ readonly sessionId: string;
1346
+ constructor(sessionId: string);
1347
+ }
1348
+ /**
1349
+ * Thrown when a session policy blocks an operation — for example,
1350
+ * `requireReAuthFor: ['export']` is set and the caller attempts to
1351
+ * call `exportStream()` without re-authenticating for this session.
1352
+ *
1353
+ * The `operation` field names the specific operation that was blocked
1354
+ * (e.g. `'export'`, `'grant'`, `'rotate'`) so the caller can surface
1355
+ * a targeted prompt ("Please re-enter your passphrase to export data").
1356
+ */
1357
+ declare class SessionPolicyError extends NoydbError {
1358
+ readonly operation: string;
1359
+ constructor(operation: string, message?: string);
1360
+ }
1361
+ /**
1362
+ * Thrown when a `.join()` would exceed its configured row ceiling on
1363
+ * either side. The ceiling defaults to 50,000 per side and can be
1364
+ * overridden via the `{ maxRows }` option on `.join()`.
1365
+ *
1366
+ * Carries both row counts so the error message can show which side
1367
+ * tripped the limit (e.g. "left had 60,000 rows, right had 1,200,
1368
+ * max was 50,000"). The `side` field is machine-readable so test
1369
+ * code and devtools can match on it without regex-parsing the
1370
+ * message.
1371
+ *
1372
+ * The row ceiling exists because joins are bounded in-memory
1373
+ * operations over materialized record sets. Consumers whose
1374
+ * collections genuinely exceed the ceiling should track
1375
+ * (streaming joins over `scan()`) or filter the left side further
1376
+ * with `where()` / `limit()` before joining.
1377
+ */
1378
+ declare class JoinTooLargeError extends NoydbError {
1379
+ readonly leftRows: number;
1380
+ readonly rightRows: number;
1381
+ readonly maxRows: number;
1382
+ readonly side: 'left' | 'right';
1383
+ constructor(opts: {
1384
+ leftRows: number;
1385
+ rightRows: number;
1386
+ maxRows: number;
1387
+ side: 'left' | 'right';
1388
+ message: string;
1389
+ });
1390
+ }
1391
+ /**
1392
+ * Thrown by `.crossJoin()` when the cumulative cartesian product (or lateral
1393
+ * filtered count) exceeds the configured ceiling. Check before allocating.
1394
+ * Mirrors the pattern of `JoinTooLargeError` and the `.join()` row ceiling.
1395
+ *
1396
+ * @see CrossJoinClause.maxRows — per-clause override
1397
+ * @see DEFAULT_CROSS_JOIN_MAX_ROWS — package default (50_000)
1398
+ */
1399
+ declare class CrossJoinTooLargeError extends NoydbError {
1400
+ readonly target: string;
1401
+ readonly expected: number;
1402
+ readonly limit: number;
1403
+ constructor(opts: {
1404
+ target: string;
1405
+ expected: number;
1406
+ limit: number;
1407
+ });
1408
+ }
1409
+ /**
1410
+ * Thrown at cross-join execution time when the target collection is not
1411
+ * reachable from the current vault. The left collection is included in the
1412
+ * message for context.
1413
+ */
1414
+ declare class CrossJoinSourceUnknownError extends NoydbError {
1415
+ readonly target: string;
1416
+ readonly leftCollection: string;
1417
+ constructor(target: string, leftCollection: string);
1418
+ }
1419
+ /**
1420
+ * Thrown by `.join()` in strict `ref()` mode when a left-side record
1421
+ * points at a right-side id that does not exist in the target
1422
+ * collection.
1423
+ *
1424
+ * Distinct from `RefIntegrityError` so test code can pattern-match
1425
+ * on the *read-time* dangling case without catching *write-time*
1426
+ * integrity violations. Both indicate "ref points at nothing" but
1427
+ * happen at different lifecycle phases and deserve different
1428
+ * remediation in documentation: a RefIntegrityError on `put()`
1429
+ * means the input is invalid; a DanglingReferenceError on `.join()`
1430
+ * means stored data has drifted and `vault.checkIntegrity()`
1431
+ * is the right tool to find the full set of orphans.
1432
+ */
1433
+ declare class DanglingReferenceError extends NoydbError {
1434
+ readonly field: string;
1435
+ readonly target: string;
1436
+ readonly refId: string;
1437
+ constructor(opts: {
1438
+ field: string;
1439
+ target: string;
1440
+ refId: string;
1441
+ message: string;
1442
+ });
1443
+ }
1444
+ /**
1445
+ * Thrown by {@link sanitizeFilename} when an input filename cannot be
1446
+ * made safe — NUL byte, empty after normalization, missing
1447
+ * `opaqueId` for the opaque profile, `..` segment, or a `maxBytes`
1448
+ * cap too small to hold a single code point.
1449
+ */
1450
+ declare class FilenameSanitizationError extends NoydbError {
1451
+ constructor(message: string);
1452
+ }
1453
+ /**
1454
+ * Thrown when a write target resolves OUTSIDE the requested
1455
+ * directory after sanitization — the canonical Zip-Slip class. The
1456
+ * sanitizer's job is to strip path-traversal segments; this error
1457
+ * is the defense-in-depth fallback at the FS write site.
1458
+ */
1459
+ declare class PathEscapeError extends NoydbError {
1460
+ readonly attempted: string;
1461
+ readonly targetDir: string;
1462
+ constructor(opts: {
1463
+ attempted: string;
1464
+ targetDir: string;
1465
+ });
1466
+ }
1467
+ /**
1468
+ * Thrown at vault open if the derivation graph contains a cycle.
1469
+ * `path` is the offending chain (e.g. `['a', 'b', 'c', 'a']`).
1470
+ */
1471
+ declare class DerivationCycleError extends NoydbError {
1472
+ readonly path: readonly string[];
1473
+ constructor(path: readonly string[]);
1474
+ }
1475
+ /**
1476
+ * Thrown when a cascade of source → output → source → … exceeds the
1477
+ * configured `maxDepth` (default 5).
1478
+ */
1479
+ declare class DerivationDepthError extends NoydbError {
1480
+ readonly limit: number;
1481
+ readonly attempted: number;
1482
+ constructor(limit: number, attempted: number);
1483
+ }
1484
+ /**
1485
+ * Thrown at registration if a `withDerivation` strategy references an
1486
+ * output `collection` that isn't otherwise declared (no schema, no use
1487
+ * elsewhere). Surfacing this early catches typos in collection names.
1488
+ */
1489
+ declare class DerivationOutputUnknownError extends NoydbError {
1490
+ readonly collection: string;
1491
+ constructor(collection: string);
1492
+ }
1493
+ /**
1494
+ * Thrown when the user's `derive` function returns a value that doesn't
1495
+ * match the declared output spec (e.g. wrong shape, wrong key set).
1496
+ */
1497
+ declare class DerivationOutputShapeError extends NoydbError {
1498
+ readonly outputKey: string;
1499
+ constructor(outputKey: string, detail: string);
1500
+ }
1501
+ /**
1502
+ * Thrown by array-shape derivations when the `derive` function
1503
+ * returns more rows than the output's `maxFanout` cap. The cap exists
1504
+ * to keep dispatch cost bounded — without it a single source-row
1505
+ * update could fan out to thousands of derived rows, dominating the
1506
+ * write path.
1507
+ *
1508
+ * Defaults to `maxFanout: 64`. Raise on the output spec for
1509
+ * carry-forward expansion cases (e.g. monthly rows across multi-year
1510
+ * contracts).
1511
+ */
1512
+ declare class DerivationCapExceededError extends NoydbError {
1513
+ readonly outputKey: string;
1514
+ readonly returned: number;
1515
+ readonly maxFanout: number;
1516
+ constructor(outputKey: string, returned: number, maxFanout: number);
1517
+ }
1518
+ /**
1519
+ * Thrown at vault open if the materialized-view graph contains a
1520
+ * cycle. `path` is the offending chain (e.g. `['a-mv', 'b-mv', 'a-mv']`).
1521
+ * Detected by the same shared DFS that catches `DerivationCycleError`;
1522
+ * surfaces with a distinct error type so consumers can disambiguate.
1523
+ */
1524
+ declare class MaterializedViewCycleError extends NoydbError {
1525
+ readonly path: readonly string[];
1526
+ constructor(path: readonly string[]);
1527
+ }
1528
+ /**
1529
+ * Thrown at MV registration if the query references a source
1530
+ * collection that isn't declared on the vault. Surfacing this early
1531
+ * catches typos in collection names.
1532
+ */
1533
+ declare class MaterializedViewSourceUnknownError extends NoydbError {
1534
+ readonly mvName: string;
1535
+ readonly collection: string;
1536
+ constructor(mvName: string, collection: string);
1537
+ }
1538
+ /**
1539
+ * Thrown by the MV executor when a refresh produces more rows than
1540
+ * the configured ceiling. Default ceiling is 100k rows; override
1541
+ * per-MV via `maxRows`. Mirrors `JoinTooLargeError` /
1542
+ * `GroupCardinalityError` from the query DSL — the explosion is
1543
+ * detected BEFORE writes hit the store, so the source-write
1544
+ * transaction can roll back cleanly via strict-mode.
1545
+ */
1546
+ declare class MaterializedViewTooLargeError extends NoydbError {
1547
+ readonly mvName: string;
1548
+ readonly expected: number;
1549
+ readonly limit: number;
1550
+ constructor(mvName: string, expected: number, limit: number);
1551
+ }
1552
+ /**
1553
+ * Thrown by `withMaterializedView()` at registration time when the
1554
+ * strategy is structurally malformed. Distinct from
1555
+ * `MaterializedViewSourceUnknownError` (the source list is well-formed
1556
+ * but names a collection the vault doesn't know) and
1557
+ * `MaterializedViewCycleError` (the source graph has a cycle): this
1558
+ * error fires before either check, at the moment the spec is being
1559
+ * normalized.
1560
+ *
1561
+ * Today the trigger cases are all about the `query` / `unionSources`
1562
+ * dichotomy:
1563
+ * - both `query` and `unionSources` were set (mutually exclusive),
1564
+ * - neither `query` nor `unionSources` was set,
1565
+ * - `unionSources` has fewer than 2 arms,
1566
+ * - two arms in `unionSources` reference the same `collection`.
1567
+ *
1568
+ * The error message is prefixed with `[noy-db] withMaterializedView:`
1569
+ * so it's grep-friendly in logs and looks consistent with the existing
1570
+ * `ValidationError` messages from the same factory.
1571
+ */
1572
+ declare class MaterializedViewConfigError extends NoydbError {
1573
+ constructor(message: string);
1574
+ }
1575
+ /**
1576
+ * Thrown at vault open when a `withOverlayedView` declaration uses
1577
+ * another virtual-overlay name as its `base`. Multi-overlay stacking
1578
+ * is a v2 non-goal — the shallow expansion in
1579
+ * `QueryDependencyAnalyzer` would truncate at the inner overlay
1580
+ * name, leaving downstream MVs silently stale.
1581
+ */
1582
+ declare class OverlayBaseIsVirtualError extends NoydbError {
1583
+ readonly overlayName: string;
1584
+ readonly base: string;
1585
+ constructor(overlayName: string, base: string);
1586
+ }
1587
+ /**
1588
+ * Thrown at vault open when a `withOverlayedView`'s `overlay`
1589
+ * references an unknown collection or an MV-owned collection. The
1590
+ * overlay collection is user-writable; MV-owned collections aren't.
1591
+ */
1592
+ declare class OverlayCollectionUnavailableError extends NoydbError {
1593
+ readonly overlayName: string;
1594
+ readonly overlay: string;
1595
+ constructor(overlayName: string, overlay: string);
1596
+ }
1597
+ /**
1598
+ * Thrown at vault open when a `withOverlayedView`'s virtual `name`
1599
+ * collides with an MV output or a concrete source collection.
1600
+ */
1601
+ declare class OverlayNameCollisionError extends NoydbError {
1602
+ readonly overlayName: string;
1603
+ constructor(overlayName: string);
1604
+ }
1605
+ /**
1606
+ * Thrown by the virtual overlay's `put(id, record)` when the
1607
+ * consumer-supplied `id` doesn't match `rowKey(record)`. Catches
1608
+ * fat-finger separator typos that would otherwise silently produce
1609
+ * orphaned overlay rows. Direct writes to the underlying overlay
1610
+ * collection (bypass the virtual layer) skip this validation.
1611
+ */
1612
+ declare class OverlayIdMismatchError extends NoydbError {
1613
+ readonly actual: string;
1614
+ readonly expected: string;
1615
+ constructor(actual: string, expected: string);
1616
+ }
1617
+ /**
1618
+ * Thrown when a requested snapshot version does not exist in the
1619
+ * snapshot store — either it was never created, was pruned by the
1620
+ * retention policy, or was deleted manually.
1621
+ *
1622
+ * The `version` field carries the key that was looked up so callers
1623
+ * can surface an actionable "snapshot X not found" message without
1624
+ * parsing the error string.
1625
+ */
1626
+ declare class SnapshotNotFoundError extends NoydbError {
1627
+ readonly version: string;
1628
+ constructor(version: string);
1629
+ }
1630
+ /**
1631
+ * Thrown when a write targets a partition key that has no shard and
1632
+ * `sharding.autoCreate` is disabled.
1633
+ */
1634
+ declare class UnknownShardError extends NoydbError {
1635
+ readonly partitionKey: string;
1636
+ constructor(partitionKey: string, groupName: string);
1637
+ }
1638
+ /**
1639
+ * Thrown by `createShard` when the registry has a row for a partition
1640
+ * but the corresponding vault is not provisioned in the store —
1641
+ * a registry/store divergence. Refusing to recreate avoids masking
1642
+ * data loss.
1643
+ */
1644
+ declare class ShardProvisioningError extends NoydbError {
1645
+ readonly vaultId: string;
1646
+ constructor(vaultId: string, partitionKey: string);
1647
+ }
1648
+ /** Thrown when a VaultGroup references a template name that was never registered. */
1649
+ declare class VaultTemplateNotFoundError extends NoydbError {
1650
+ readonly templateName: string;
1651
+ constructor(templateName: string);
1652
+ }
1653
+
1654
+ /**
1655
+ * The `money()` field descriptor — a branded schema-layer descriptor, a
1656
+ * sibling of `i18nText()` / `dictKey()`. It owns currency, scale, and
1657
+ * rounding policy for a field; the pure arithmetic lives in
1658
+ * {@link ./fixed-point} and default scale resolution in
1659
+ * {@link ./iso4217}.
1660
+ *
1661
+ * Two modes:
1662
+ * - **fixed** `money({ currency: 'EUR' })` — one currency for the
1663
+ * field; the value stores a bare scaled-integer string.
1664
+ * - **multi** `money({ currencies: 'any' | [...] })` — currency travels
1665
+ * per record; the value stores `{ amount, currency }`.
1666
+ *
1667
+ * `currency` and `currencies` are mutually exclusive.
1668
+ */
1669
+
1670
+ interface MoneyOptionsFixed {
1671
+ currency: string;
1672
+ /** Override the ISO-4217 default scale (required for unlisted codes). */
1673
+ scale?: number;
1674
+ rounding?: RoundingMode;
1675
+ }
1676
+ interface MoneyOptionsMulti {
1677
+ currencies: 'any' | readonly string[];
1678
+ /** Per-currency scale overrides (required for unlisted codes). */
1679
+ scaleOverrides?: Record<string, number>;
1680
+ rounding?: RoundingMode;
1681
+ }
1682
+ type MoneyOptions = MoneyOptionsFixed | MoneyOptionsMulti;
1683
+ interface MoneyDescriptor {
1684
+ readonly _noydbMoney: true;
1685
+ readonly mode: 'fixed' | 'multi';
1686
+ readonly options: MoneyOptions;
1687
+ readonly rounding: RoundingMode | undefined;
1688
+ /** The currency for fixed mode; `undefined` in multi mode. */
1689
+ readonly fixedCurrency: string | undefined;
1690
+ /** Resolve the scale for a currency, throwing if not allowed / unknown. */
1691
+ scaleFor(currency: string): number;
1692
+ /** Whether this descriptor permits the given currency. */
1693
+ allows(currency: string): boolean;
1694
+ /**
1695
+ * The single currency this descriptor implies, if any — fixed mode, or
1696
+ * multi mode with exactly one allow-listed currency. Lets a multi field
1697
+ * accept a bare amount unambiguously. `undefined` otherwise.
1698
+ */
1699
+ soleCurrency(): string | undefined;
1700
+ }
1701
+ /** Raised when a written value carries more precision than `scale` allows. */
1702
+ declare class MoneyPrecisionError extends NoydbError {
1703
+ readonly field: string;
1704
+ readonly value: unknown;
1705
+ readonly scale: number;
1706
+ constructor(field: string, value: unknown, scale: number);
1707
+ }
1708
+ /** Raised when a currency is disallowed or has no resolvable scale. */
1709
+ declare class MoneyCurrencyError extends NoydbError {
1710
+ readonly currency: string;
1711
+ readonly reason: 'not-allowed' | 'unknown-scale';
1712
+ readonly field?: string | undefined;
1713
+ constructor(currency: string, reason: 'not-allowed' | 'unknown-scale', field?: string | undefined);
1714
+ }
1715
+ /** Raised when an aggregate operation is not supported on a money field. */
1716
+ declare class MoneyUnsupportedError extends NoydbError {
1717
+ readonly field: string;
1718
+ constructor(field: string, message?: string);
1719
+ }
1720
+ /** Create a {@link MoneyDescriptor}. */
1721
+ declare function money(options: MoneyOptions): MoneyDescriptor;
1722
+ /** Runtime predicate for detecting a {@link MoneyDescriptor}. */
1723
+ declare function isMoneyDescriptor(x: unknown): x is MoneyDescriptor;
1724
+
1725
+ /**
1726
+ * Query DSL `.groupBy()` —.
1727
+ *
1728
+ * Chains after `.where()` / `.filter()` / `.or()` / `.and()` on a
1729
+ * Query and before a reducer spec, so consumers can compute
1730
+ * per-bucket aggregates without folding in userland:
1731
+ *
1732
+ * ```ts
1733
+ * const byClient = invoices.query()
1734
+ * .where('status', '==', 'open')
1735
+ * .groupBy('clientId')
1736
+ * .aggregate({ total: sum('amount'), n: count() })
1737
+ * .run()
1738
+ * // → [ { clientId: 'c1', total: 5250, n: 3 }, … ]
1739
+ * ```
1740
+ *
1741
+ * Execution pipeline:
1742
+ *
1743
+ * 1. Run the query's where/filter clauses (same candidate /
1744
+ * filter pipeline as `.aggregate()` directly on Query).
1745
+ * 2. Partition the matching records into buckets keyed by
1746
+ * `readPath(record, field)`. JS `Map` preserves insertion
1747
+ * order, so the first-seen key for a bucket determines its
1748
+ * position in the result array — consumers who want a
1749
+ * specific ordering should `.sort()` downstream.
1750
+ * 3. Enforce cardinality: warn once per field at 10% of the cap
1751
+ * (10_000 buckets), throw `GroupCardinalityError` at 100% of
1752
+ * the cap (100_000 buckets).
1753
+ * 4. For each bucket, build a per-group reducer state and
1754
+ * step every record in the bucket through it.
1755
+ * 5. Emit one result row per bucket, shaped as
1756
+ * `{ [field]: key, ...reduced }`.
1757
+ *
1758
+ * **Null / undefined keys:** `Map` distinguishes `null` from
1759
+ * `undefined`, so records with a missing group field get their own
1760
+ * bucket, and records with an explicit `null` value get a separate
1761
+ * bucket from that. Consumers who want them merged can coalesce
1762
+ * upstream with `.filter()`.
1763
+ *
1764
+ * **Live mode:** `.groupBy().aggregate().live()` re-runs the full
1765
+ * grouping pipeline on every source change. Per-bucket incremental
1766
+ * delta maintenance is a future optimization — the reducer
1767
+ * protocol's `remove()` hook admits it, but ships naive
1768
+ * re-grouping for simplicity.
1769
+ *
1770
+ * **Type-level stable-key narrowing:** when
1771
+ * `dictKey` lands, `groupBy<DictField>()` will narrow the group key
1772
+ * type to the stable dictionary key rather than the resolved locale
1773
+ * label. That prevents grouping by the locale-resolved label,
1774
+ * which would produce different buckets per reader. types the
1775
+ * key as `unknown` at the result shape; the dictKey narrowing
1776
+ * layers on top without an API break.
1777
+ *
1778
+ * Partition-awareness seam: when partitioned collections land,
1779
+ * per-partition grouping will need to merge sub-results across
1780
+ * partitions. The reducer protocol's `{ seed }` parameter
1781
+ * (already plumbed through in `reducers.ts`) is the mechanism —
1782
+ * groupBy doesn't need its own seam for the moment, because it
1783
+ * delegates to the reducer protocol for all per-bucket state.
1784
+ */
1785
+
1786
+ /**
1787
+ * Cardinality thresholds for `.groupBy()`. The warn threshold gives
1788
+ * consumers a heads-up before the hard error; the cap is a fixed
1789
+ * constant in (not overridable). A `{ maxGroups }` override
1790
+ * can be added later without a break if a real consumer asks.
1791
+ */
1792
+ declare const GROUPBY_WARN_CARDINALITY = 10000;
1793
+ declare const GROUPBY_MAX_CARDINALITY = 100000;
1794
+ /**
1795
+ * Test-only: clear the per-field cardinality warning dedup between
1796
+ * tests. Production code never calls this — matching the
1797
+ * `resetJoinWarnings` pattern in `join.ts`.
1798
+ */
1799
+ declare function resetGroupByWarnings(): void;
1800
+ /**
1801
+ * Result row shape for a grouped aggregation. Each row carries the
1802
+ * group key value under the grouping field name plus every reducer
1803
+ * output from the spec.
1804
+ *
1805
+ * types the group key as `unknown` at the result shape — the
1806
+ * runtime read via `readPath` can return any value, and narrowing
1807
+ * to a specific type would require the caller to assert at the
1808
+ * call site. `dictKey` narrowing layers on top of this by
1809
+ * adding an overload that constrains `F` when the grouping field
1810
+ * is a `dictKey`.
1811
+ */
1812
+ type GroupedRow<F extends string, R> = {
1813
+ [K in F]: unknown;
1814
+ } & R;
1815
+ /**
1816
+ * Multi-key variant — result-row shape for variadic
1817
+ * `.groupBy(...fields)`. Every grouped field name appears on the row
1818
+ * (typed as `unknown` for the same reason as `GroupedRow`), plus the
1819
+ * reducer outputs from the spec.
1820
+ */
1821
+ type GroupedRowN<F extends readonly string[], R> = {
1822
+ [K in F[number]]: unknown;
1823
+ } & R;
1824
+ /**
1825
+ * Shared base class for the chainable grouped-query wrappers. Holds
1826
+ * the constructor + protected fields that both single-key
1827
+ * `GroupedQuery<T, F>` and variadic `GroupedQueryN<T, F>` need; each
1828
+ * subclass only overrides `aggregate()` with its own result-row
1829
+ * generic.
1830
+ *
1831
+ * Not exported — implementation detail. Adding `.having()` /
1832
+ * `.live()` / `.orderByGroup()` etc. in the future lands here once
1833
+ * and both subclasses pick it up automatically.
1834
+ *
1835
+ * @internal
1836
+ */
1837
+ declare abstract class GroupedQueryBase {
1838
+ protected readonly executeRecords: () => readonly unknown[];
1839
+ protected readonly upstreams: readonly AggregationUpstream[];
1840
+ /**
1841
+ * Optional dict label resolver attached by the query builder when
1842
+ * the grouping field is a dictKey. Variadic groupings always pass
1843
+ * `undefined` — `<field>Label` projection has no meaningful shape
1844
+ * for composite keys.
1845
+ */
1846
+ protected readonly dictLabelResolver?: ((key: string, locale: string, fallback?: string | readonly string[]) => Promise<string | undefined>) | undefined;
1847
+ /**
1848
+ * Money field descriptors for the backing collection — used to
1849
+ * rewrite `sum`/`min`/`max` over money fields into exact BigInt
1850
+ * reducers when `.aggregate(spec)` is terminated.
1851
+ */
1852
+ protected readonly moneyFields?: Record<string, MoneyDescriptor> | undefined;
1853
+ /**
1854
+ * Field set this grouped query buckets on. Stored in declaration
1855
+ * order — the same order is preserved on every result row by
1856
+ * `groupAndReduce`. For the single-field constructor, this is
1857
+ * `[field]`.
1858
+ */
1859
+ protected readonly fields: readonly string[];
1860
+ constructor(executeRecords: () => readonly unknown[], fieldOrFields: string | readonly string[], upstreams: readonly AggregationUpstream[],
1861
+ /**
1862
+ * Optional dict label resolver attached by the query builder when
1863
+ * the grouping field is a dictKey. Variadic groupings always pass
1864
+ * `undefined` — `<field>Label` projection has no meaningful shape
1865
+ * for composite keys.
1866
+ */
1867
+ dictLabelResolver?: ((key: string, locale: string, fallback?: string | readonly string[]) => Promise<string | undefined>) | undefined,
1868
+ /**
1869
+ * Money field descriptors for the backing collection — used to
1870
+ * rewrite `sum`/`min`/`max` over money fields into exact BigInt
1871
+ * reducers when `.aggregate(spec)` is terminated.
1872
+ */
1873
+ moneyFields?: Record<string, MoneyDescriptor> | undefined);
1874
+ /** Apply money-aware reducer rewriting when money fields are declared. */
1875
+ protected wrapSpec<Spec extends AggregateSpec>(spec: Spec): Spec;
1876
+ }
1877
+ /**
1878
+ * Chainable wrapper returned by `Query.groupBy(field)`. Terminates
1879
+ * with `.aggregate(spec)` which returns a `GroupedAggregation`.
1880
+ *
1881
+ * Kept minimal — the only operation on a grouped query is
1882
+ * aggregation. Ordering, limiting, and further filtering belong on
1883
+ * the underlying `Query` before `.groupBy()` is called; applying
1884
+ * them post-group would be a different operation (`having` /
1885
+ * `groupOrderBy`), out of scope for.
1886
+ */
1887
+ declare class GroupedQuery<T, F extends string> extends GroupedQueryBase {
1888
+ /**
1889
+ * Build a grouped aggregation. Returns a `GroupedAggregation`
1890
+ * with `.run()`, `.runAsync()`, and `.live()` terminals — same shape
1891
+ * as the non-grouped `.aggregate()` wrapper, just with an array
1892
+ * result (one row per bucket) instead of a single reduced object.
1893
+ */
1894
+ aggregate<Spec extends AggregateSpec>(spec: Spec): GroupedAggregation<GroupedRow<F, AggregateResult<Spec>>>;
1895
+ }
1896
+ /**
1897
+ * Variadic-keyed sibling of `GroupedQuery<T, F>`. Constructed by the
1898
+ * multi-arg `Query.groupBy(...fields)` overload. The runtime shape is
1899
+ * identical — only the type-level result-row narrowing differs.
1900
+ */
1901
+ declare class GroupedQueryN<T, F extends readonly string[]> extends GroupedQueryBase {
1902
+ aggregate<Spec extends AggregateSpec>(spec: Spec): GroupedAggregation<GroupedRowN<F, AggregateResult<Spec>>>;
1903
+ }
1904
+ /**
1905
+ * Execute the group-and-reduce pipeline. Pure function over a
1906
+ * record array and a spec — shared by `GroupedAggregation.run()`
1907
+ * and the live-mode refresh path. Exported for tests and for any
1908
+ * future `scan().groupBy().aggregate()` reuse.
1909
+ *
1910
+ * Enforces the cardinality cap incrementally during the partition
1911
+ * loop, so a runaway grouping throws at the moment the 100_001st
1912
+ * bucket would be created — the consumer doesn't have to wait for
1913
+ * the full partition to materialize before the error fires.
1914
+ */
1915
+ declare function groupAndReduce<R>(records: readonly unknown[], fieldOrFields: string | readonly string[], spec: AggregateSpec): R[];
1916
+ /**
1917
+ * Grouped aggregation wrapper — the `.groupBy(field).aggregate(spec)`
1918
+ * terminal. Shape mirrors `Aggregation<R>` from aggregate.ts: two
1919
+ * terminals (`.run()` and `.live()`), spec bound at construction
1920
+ * time, upstreams collected for live mode.
1921
+ *
1922
+ * The generic `R` is the per-row result shape (i.e. a single
1923
+ * grouped row), and the terminals return `R[]` — one row per
1924
+ * bucket.
1925
+ */
1926
+ declare class GroupedAggregation<R> {
1927
+ private readonly executeRecords;
1928
+ private readonly spec;
1929
+ private readonly upstreams;
1930
+ /**
1931
+ * Optional dict label resolver for `<field>Label` projection
1932
+ *. Present when the grouping field is a dictKey.
1933
+ */
1934
+ private readonly dictLabelResolver?;
1935
+ private readonly fields;
1936
+ constructor(executeRecords: () => readonly unknown[], fields: string | readonly string[], spec: AggregateSpec, upstreams: readonly AggregationUpstream[],
1937
+ /**
1938
+ * Optional dict label resolver for `<field>Label` projection
1939
+ *. Present when the grouping field is a dictKey.
1940
+ */
1941
+ dictLabelResolver?: ((key: string, locale: string, fallback?: string | readonly string[]) => Promise<string | undefined>) | undefined);
1942
+ /** Execute the query, group, reduce, and return an array of rows. */
1943
+ run(): R[];
1944
+ /**
1945
+ * Execute the query, group, reduce, and resolve `<field>Label` for
1946
+ * each result row when the grouping field is a `dictKey` and a
1947
+ * `locale` is provided. Returns `R[]` synchronously when
1948
+ * no locale is specified (identical to `.run()`).
1949
+ *
1950
+ * The `<field>Label` field is appended to each row. Rows whose group
1951
+ * key has no dictionary entry get `<field>Label: undefined`.
1952
+ *
1953
+ * Dict-label resolution is single-field only — multi-key groupings
1954
+ * do not produce a `<field>Label`. The resolver is only attached
1955
+ * by the builder when `fields.length === 1`.
1956
+ */
1957
+ runAsync(opts?: {
1958
+ locale?: string;
1959
+ fallback?: string | readonly string[];
1960
+ }): Promise<R[]>;
1961
+ /**
1962
+ * Build a reactive `LiveAggregation<R[]>` that re-runs the full
1963
+ * group-and-reduce pipeline whenever any upstream source notifies
1964
+ * of a change. Same error-isolation and idempotent-stop contract
1965
+ * as `Aggregation.live()` — the implementation delegates to the
1966
+ * same `LiveAggregationImpl` class by threading a fresh
1967
+ * recompute closure through the existing constructor.
1968
+ *
1969
+ * uses naive full re-run on every change. Incremental
1970
+ * per-bucket maintenance (apply `step` on inserted records,
1971
+ * `remove` on deleted records, route by bucket key) is a future
1972
+ * optimization — the reducer protocol admits it, but wiring
1973
+ * delta-aware source subscriptions is a separate PR.
1974
+ *
1975
+ * Always call `live.stop()` when finished.
1976
+ */
1977
+ live(): LiveAggregation<R[]>;
1978
+ }
1979
+
1980
+ /**
1981
+ * Strategy seam between the core Query / ScanBuilder chain and the
1982
+ * optional aggregate / groupBy subsystem. Core imports
1983
+ * `AggregateStrategy` as a TYPE-ONLY symbol and `NO_AGGREGATE` as a
1984
+ * tiny runtime stub.
1985
+ *
1986
+ * The heavy machinery — `Aggregation`, `GroupedQuery`, the
1987
+ * reducer-step logic — is only reachable from `withAggregate()` in
1988
+ * `./active.ts`, which is only exported through the
1989
+ * `@noy-db/hub/aggregate` subpath. Consumers that don't import the
1990
+ * subpath ship none of the ~886 LOC.
1991
+ *
1992
+ * @internal
1993
+ */
1994
+
1995
+ /**
1996
+ * Seam interface. `@internal` — will promote to public only when the
1997
+ * aggregate subsystem is extracted into its own package.
1998
+ *
1999
+ * @internal
2000
+ */
2001
+ interface AggregateStrategy {
2002
+ /**
2003
+ * Build an `Aggregation<R>` for `Query.aggregate(spec)`. `executeRecords`
2004
+ * is a closure that produces the matching record set when the
2005
+ * aggregation runs. NO_AGGREGATE throws; the active strategy
2006
+ * constructs a real `Aggregation`.
2007
+ */
2008
+ aggregate<Spec extends AggregateSpec>(executeRecords: () => readonly unknown[], spec: Spec, upstreams: readonly AggregationUpstream[]): Aggregation<AggregateResult<Spec>>;
2009
+ /**
2010
+ * Build a `GroupedQuery<T, F>` for `Query.groupBy(field)`. Same
2011
+ * closure / upstream inputs as `aggregate` plus the group key field.
2012
+ */
2013
+ groupBy<T, F extends string>(executeRecords: () => readonly unknown[], field: F, upstreams: readonly AggregationUpstream[], dictLabelResolver?: (key: string, locale: string, fallback?: string | readonly string[]) => Promise<string | undefined>, moneyFields?: Record<string, MoneyDescriptor>): GroupedQuery<T, F>;
2014
+ /**
2015
+ * Variadic-keyed sibling — builds a `GroupedQueryN<T, F>` for
2016
+ * `Query.groupBy(...fields)`. No dictLabelResolver — `<field>Label`
2017
+ * projection only applies to single-field groupings, which dispatch
2018
+ * through `groupBy` above.
2019
+ */
2020
+ groupByN<T, F extends readonly string[]>(executeRecords: () => readonly unknown[], fields: F, upstreams: readonly AggregationUpstream[], moneyFields?: Record<string, MoneyDescriptor>): GroupedQueryN<T, F>;
2021
+ /**
2022
+ * Terminal streaming aggregator for `ScanBuilder.aggregate(spec)`.
2023
+ * Takes an async iterable of decrypted records + the spec and
2024
+ * returns the reduced result.
2025
+ */
2026
+ scanAggregate<Spec extends AggregateSpec>(iter: AsyncIterable<unknown>, spec: Spec): Promise<AggregateResult<Spec>>;
2027
+ }
2028
+
2029
+ export { BundleSealMismatchError as $, type AggregateStrategy as A, AmendmentForbiddenError as B, RecordLockedError as C, DictKeyInUseError as D, SnapshotNotFoundError as E, FieldFrozenError as F, GROUPBY_MAX_CARDINALITY as G, DerivationCapExceededError as H, InvariantError as I, DerivationCycleError as J, DerivationDepthError as K, LocaleNotSpecifiedError as L, MissingTranslationError as M, DerivationOutputShapeError as N, DerivationOutputUnknownError as O, OverlayBaseIsVirtualError as P, OverlayCollectionUnavailableError as Q, ReservedCollectionNameError as R, ScriptViolationError as S, TranslatorNotConfiguredError as T, OverlayIdMismatchError as U, OverlayNameCollisionError as V, AttestationError as W, AdoptionStateError as X, BackupCorruptedError as Y, BackupLedgerError as Z, BundleIntegrityError as _, DictKeyMissingError as a, ValidationError as a$, BundleVersionConflictError as a0, PartitionExtractionError as a1, TransferSealError as a2, MaterializedViewConfigError as a3, MaterializedViewCycleError as a4, MaterializedViewSourceUnknownError as a5, MaterializedViewTooLargeError as a6, NoydbError as a7, AlreadyElevatedError as a8, ConflictError as a9, NetworkError as aA, NoAccessError as aB, NonAdditiveSchemaChangeError as aC, NotFoundError as aD, PathEscapeError as aE, PeriodClosedError as aF, PermissionDeniedError as aG, PrivilegeEscalationError as aH, QuiesceTimeoutError as aI, ReadOnlyAtInstantError as aJ, ReadOnlyError as aK, ReadOnlyFrameError as aL, type RoundingMode as aM, SchemaFenceError as aN, SchemaLockedError as aO, SchemaUpdateError as aP, SchemaValidationError as aQ, SequenceContentionError as aR, SequenceOfflineError as aS, ShardProvisioningError as aT, StoreCapabilityError as aU, TamperedError as aV, TierDemoteDeniedError as aW, TierNotGrantedError as aX, UniqueConstraintError as aY, UnknownShardError as aZ, UnsupportedIndexOptionError as a_, CrossJoinSourceUnknownError as aa, CrossJoinTooLargeError as ab, DanglingReferenceError as ac, DecryptionError as ad, DelegationTargetMissingError as ae, DirectoryDisabledError as af, ElevationExpiredError as ag, ExportCapabilityError as ah, FilenameSanitizationError as ai, GroupCardinalityError as aj, ImportCapabilityError as ak, IndexRequiredError as al, IndexWriteFailureError as am, InvalidKeyError as an, JoinTooLargeError as ao, KeyringCorruptError as ap, KeyringExpiredError as aq, LedgerContentionError as ar, MigrationRequiredError as as, MoneyCurrencyError as at, type MoneyDescriptor as au, type MoneyOptions as av, type MoneyOptionsFixed as aw, type MoneyOptionsMulti as ax, MoneyPrecisionError as ay, MoneyUnsupportedError as az, SessionExpiredError as b, VaultTemplateNotFoundError as b0, isMoneyDescriptor as b1, money as b2, SessionNotFoundError as c, SessionPolicyError as d, type AggregateResult as e, type AggregateSpec as f, Aggregation as g, type AggregationUpstream as h, GROUPBY_WARN_CARDINALITY as i, GroupedAggregation as j, GroupedQuery as k, GroupedQueryN as l, type GroupedRow as m, type GroupedRowN as n, type LiveAggregation as o, type Reducer as p, type ReducerOptions as q, avg as r, buildLiveAggregation as s, count as t, groupAndReduce as u, max as v, min as w, reduceRecords as x, resetGroupByWarnings as y, sum as z };