@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
@@ -31,7 +31,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
31
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
32
 
33
33
  // src/errors.ts
34
- var NoydbError, DecryptionError, TamperedError, InvalidKeyError, KeyringCorruptError, NoAccessError, ReadOnlyError, PermissionDeniedError, ExportCapabilityError, KeyringExpiredError, ImportCapabilityError, StoreCapabilityError, PrivilegeEscalationError, FieldFrozenError, InvariantError, AmendmentForbiddenError, TierNotGrantedError, ElevationExpiredError, AlreadyElevatedError, TierDemoteDeniedError, DelegationTargetMissingError, ConflictError, LedgerContentionError, BundleVersionConflictError, ValidationError, SchemaValidationError, SchemaUpdateError, SchemaFenceError, MigrationRequiredError, QuiesceTimeoutError, GroupCardinalityError, IndexRequiredError, UniqueConstraintError, UnsupportedIndexOptionError, IndexWriteFailureError, BundleIntegrityError, BundleSealMismatchError, ReservedCollectionNameError, LocaleNotSpecifiedError, TranslatorNotConfiguredError, BackupLedgerError, BackupCorruptedError, PartitionExtractionError, TransferSealError, AdoptionStateError, AttestationError, JoinTooLargeError, CrossJoinTooLargeError, CrossJoinSourceUnknownError, DanglingReferenceError, DerivationCycleError, DerivationOutputShapeError, DerivationCapExceededError, MaterializedViewCycleError, MaterializedViewSourceUnknownError, MaterializedViewTooLargeError, OverlayBaseIsVirtualError, OverlayCollectionUnavailableError, OverlayNameCollisionError, OverlayIdMismatchError;
34
+ var NoydbError, DecryptionError, TamperedError, InvalidKeyError, KeyringCorruptError, NoAccessError, ReadOnlyError, PermissionDeniedError, ExportCapabilityError, KeyringExpiredError, ImportCapabilityError, StoreCapabilityError, PrivilegeEscalationError, FieldFrozenError, InvariantError, AmendmentForbiddenError, TierNotGrantedError, ElevationExpiredError, AlreadyElevatedError, TierDemoteDeniedError, DelegationTargetMissingError, ConflictError, LedgerContentionError, SequenceContentionError, SequenceOfflineError, BundleVersionConflictError, ValidationError, SchemaValidationError, SchemaUpdateError, SchemaFenceError, MigrationRequiredError, QuiesceTimeoutError, GroupCardinalityError, IndexRequiredError, UniqueConstraintError, UnsupportedIndexOptionError, IndexWriteFailureError, BundleIntegrityError, BundleSealMismatchError, ReservedCollectionNameError, LocaleNotSpecifiedError, TranslatorNotConfiguredError, BackupLedgerError, BackupCorruptedError, PartitionExtractionError, TransferSealError, AdoptionStateError, AttestationError, JoinTooLargeError, CrossJoinTooLargeError, CrossJoinSourceUnknownError, DanglingReferenceError, DerivationCycleError, DerivationOutputShapeError, DerivationCapExceededError, MaterializedViewCycleError, MaterializedViewSourceUnknownError, MaterializedViewTooLargeError, OverlayBaseIsVirtualError, OverlayCollectionUnavailableError, OverlayNameCollisionError, OverlayIdMismatchError, UnknownShardError, ShardProvisioningError, VaultTemplateNotFoundError;
35
35
  var init_errors = __esm({
36
36
  "src/errors.ts"() {
37
37
  "use strict";
@@ -266,6 +266,28 @@ var init_errors = __esm({
266
266
  this.attempts = attempts;
267
267
  }
268
268
  };
269
+ SequenceContentionError = class extends NoydbError {
270
+ sequence;
271
+ attempts;
272
+ constructor(sequence, attempts) {
273
+ super(
274
+ "SEQUENCE_CONTENTION",
275
+ `vault.sequence("${sequence}").next(): failed to allocate after ${attempts} optimistic-CAS retries`
276
+ );
277
+ this.name = "SequenceContentionError";
278
+ this.sequence = sequence;
279
+ this.attempts = attempts;
280
+ }
281
+ };
282
+ SequenceOfflineError = class extends NoydbError {
283
+ constructor() {
284
+ super(
285
+ "SEQUENCE_OFFLINE",
286
+ "vault.sequence().next() requires an online CAS-capable store (capabilities.casAtomic). Gap-free numbering cannot be serialized offline."
287
+ );
288
+ this.name = "SequenceOfflineError";
289
+ }
290
+ };
269
291
  BundleVersionConflictError = class extends NoydbError {
270
292
  /** The bundle handle of the newer remote version that rejected the push. */
271
293
  remoteVersion;
@@ -679,6 +701,39 @@ Resolutions:
679
701
  this.expected = expected;
680
702
  }
681
703
  };
704
+ UnknownShardError = class extends NoydbError {
705
+ partitionKey;
706
+ constructor(partitionKey, groupName) {
707
+ super(
708
+ "SHARD_UNKNOWN",
709
+ `No shard for partition key "${partitionKey}" in vault group "${groupName}" and autoCreate is disabled. Call group.createShard(${JSON.stringify(partitionKey)}) first, or enable sharding.autoCreate.`
710
+ );
711
+ this.name = "UnknownShardError";
712
+ this.partitionKey = partitionKey;
713
+ }
714
+ };
715
+ ShardProvisioningError = class extends NoydbError {
716
+ vaultId;
717
+ constructor(vaultId, partitionKey) {
718
+ super(
719
+ "SHARD_PROVISIONING",
720
+ `Registry has a row for partition "${partitionKey}" (vault "${vaultId}") but that vault is not provisioned in the store. Refusing to recreate it \u2014 the registry and store have diverged. Investigate before retrying.`
721
+ );
722
+ this.name = "ShardProvisioningError";
723
+ this.vaultId = vaultId;
724
+ }
725
+ };
726
+ VaultTemplateNotFoundError = class extends NoydbError {
727
+ templateName;
728
+ constructor(templateName) {
729
+ super(
730
+ "VAULT_TEMPLATE_NOT_FOUND",
731
+ `No vault template registered under "${templateName}". Register it with db.withVaultTemplate(${JSON.stringify(templateName)}, { version, configure }) before opening the vault group.`
732
+ );
733
+ this.name = "VaultTemplateNotFoundError";
734
+ this.templateName = templateName;
735
+ }
736
+ };
682
737
  }
683
738
  });
684
739
 
@@ -3603,6 +3658,328 @@ var init_core = __esm({
3603
3658
  }
3604
3659
  });
3605
3660
 
3661
+ // src/money/fixed-point.ts
3662
+ function expandExponent(s) {
3663
+ const m = /^([+-]?)(\d+)(?:\.(\d+))?[eE]([+-]?\d+)$/.exec(s);
3664
+ if (!m) return s;
3665
+ const sign = m[1] === "-" ? "-" : "";
3666
+ const intp = m[2];
3667
+ const frac = m[3] ?? "";
3668
+ const exp = Number(m[4]);
3669
+ const digits = intp + frac;
3670
+ const pointPos = intp.length + exp;
3671
+ let body;
3672
+ if (pointPos <= 0) {
3673
+ body = "0." + "0".repeat(-pointPos) + digits;
3674
+ } else if (pointPos >= digits.length) {
3675
+ body = digits + "0".repeat(pointPos - digits.length);
3676
+ } else {
3677
+ body = digits.slice(0, pointPos) + "." + digits.slice(pointPos);
3678
+ }
3679
+ return sign + body;
3680
+ }
3681
+ function toCanonicalDecimalString(input) {
3682
+ let s;
3683
+ if (typeof input === "number") {
3684
+ if (!Number.isFinite(input)) return null;
3685
+ s = String(input);
3686
+ } else {
3687
+ s = input.trim();
3688
+ }
3689
+ s = expandExponent(s);
3690
+ if (s.startsWith("+")) s = s.slice(1);
3691
+ if (!/^-?(\d+(\.\d*)?|\.\d+)$/.test(s)) return null;
3692
+ return s;
3693
+ }
3694
+ function shouldRoundUp(negative, lastKeptDigit, firstDiscarded, hasMoreNonZeroAfterFirst, mode) {
3695
+ switch (mode) {
3696
+ case "up":
3697
+ return true;
3698
+ case "down":
3699
+ return false;
3700
+ case "ceil":
3701
+ return !negative;
3702
+ case "floor":
3703
+ return negative;
3704
+ case "half-up":
3705
+ return firstDiscarded >= 5;
3706
+ case "half-down":
3707
+ return firstDiscarded > 5 || firstDiscarded === 5 && hasMoreNonZeroAfterFirst;
3708
+ case "half-even":
3709
+ if (firstDiscarded > 5) return true;
3710
+ if (firstDiscarded < 5) return false;
3711
+ return hasMoreNonZeroAfterFirst || lastKeptDigit % 2 === 1;
3712
+ }
3713
+ }
3714
+ function parseToScaledInt(input, scale, rounding) {
3715
+ const canonical = toCanonicalDecimalString(input);
3716
+ if (canonical === null) return { ok: false, reason: "nonfinite" };
3717
+ const negative = canonical.startsWith("-");
3718
+ const unsigned = negative ? canonical.slice(1) : canonical;
3719
+ const dot = unsigned.indexOf(".");
3720
+ const intPart = dot === -1 ? unsigned : unsigned.slice(0, dot);
3721
+ const fracPart = dot === -1 ? "" : unsigned.slice(dot + 1);
3722
+ const intDigits = intPart === "" ? "0" : intPart;
3723
+ if (fracPart.length <= scale) {
3724
+ const keep2 = fracPart.padEnd(scale, "0");
3725
+ const magnitude2 = BigInt(intDigits + keep2);
3726
+ return { ok: true, value: negative && magnitude2 !== 0n ? -magnitude2 : magnitude2 };
3727
+ }
3728
+ const keep = fracPart.slice(0, scale);
3729
+ const tail = fracPart.slice(scale);
3730
+ const magnitudeDigits = intDigits + keep;
3731
+ let magnitude = BigInt(magnitudeDigits);
3732
+ if (/^0+$/.test(tail)) {
3733
+ return { ok: true, value: negative && magnitude !== 0n ? -magnitude : magnitude };
3734
+ }
3735
+ if (rounding === void 0) return { ok: false, reason: "precision" };
3736
+ const lastKeptDigit = Number(magnitudeDigits[magnitudeDigits.length - 1]);
3737
+ const firstDiscarded = Number(tail[0]);
3738
+ const hasMoreNonZeroAfterFirst = /[1-9]/.test(tail.slice(1));
3739
+ if (shouldRoundUp(negative, lastKeptDigit, firstDiscarded, hasMoreNonZeroAfterFirst, rounding)) {
3740
+ magnitude += 1n;
3741
+ }
3742
+ return { ok: true, value: negative && magnitude !== 0n ? -magnitude : magnitude };
3743
+ }
3744
+ function formatScaledInt(value, scale) {
3745
+ const negative = value < 0n;
3746
+ const abs = (negative ? -value : value).toString();
3747
+ if (scale === 0) return (negative ? "-" : "") + abs;
3748
+ const padded = abs.padStart(scale + 1, "0");
3749
+ const cut = padded.length - scale;
3750
+ const intPart = padded.slice(0, cut);
3751
+ const fracPart = padded.slice(cut);
3752
+ return (negative ? "-" : "") + intPart + "." + fracPart;
3753
+ }
3754
+ var init_fixed_point = __esm({
3755
+ "src/money/fixed-point.ts"() {
3756
+ "use strict";
3757
+ }
3758
+ });
3759
+
3760
+ // src/money/iso4217.ts
3761
+ function scaleForCurrency(code) {
3762
+ const v = MINOR_UNITS[code];
3763
+ return v === void 0 ? null : v;
3764
+ }
3765
+ var MINOR_UNITS;
3766
+ var init_iso4217 = __esm({
3767
+ "src/money/iso4217.ts"() {
3768
+ "use strict";
3769
+ MINOR_UNITS = {
3770
+ // 2-decimal majors
3771
+ EUR: 2,
3772
+ USD: 2,
3773
+ GBP: 2,
3774
+ CHF: 2,
3775
+ CAD: 2,
3776
+ AUD: 2,
3777
+ NZD: 2,
3778
+ SGD: 2,
3779
+ HKD: 2,
3780
+ CNY: 2,
3781
+ INR: 2,
3782
+ BRL: 2,
3783
+ MXN: 2,
3784
+ ZAR: 2,
3785
+ RUB: 2,
3786
+ TRY: 2,
3787
+ PLN: 2,
3788
+ SEK: 2,
3789
+ NOK: 2,
3790
+ DKK: 2,
3791
+ CZK: 2,
3792
+ HUF: 2,
3793
+ RON: 2,
3794
+ ILS: 2,
3795
+ THB: 2,
3796
+ PHP: 2,
3797
+ MYR: 2,
3798
+ IDR: 2,
3799
+ AED: 2,
3800
+ SAR: 2,
3801
+ QAR: 2,
3802
+ EGP: 2,
3803
+ // 0-decimal
3804
+ JPY: 0,
3805
+ KRW: 0,
3806
+ ISK: 0,
3807
+ CLP: 0,
3808
+ VND: 0,
3809
+ XOF: 0,
3810
+ XAF: 0,
3811
+ PYG: 0,
3812
+ // 3-decimal
3813
+ BHD: 3,
3814
+ KWD: 3,
3815
+ OMR: 3,
3816
+ TND: 3,
3817
+ JOD: 3,
3818
+ IQD: 3,
3819
+ LYD: 3
3820
+ };
3821
+ }
3822
+ });
3823
+
3824
+ // src/money/descriptor.ts
3825
+ var MoneyPrecisionError, MoneyUnsupportedError;
3826
+ var init_descriptor = __esm({
3827
+ "src/money/descriptor.ts"() {
3828
+ "use strict";
3829
+ init_errors();
3830
+ MoneyPrecisionError = class extends NoydbError {
3831
+ constructor(field, value, scale) {
3832
+ super(
3833
+ "MONEY_PRECISION",
3834
+ `money: value ${JSON.stringify(value)} for field "${field}" exceeds scale ${scale} and no rounding mode is configured`
3835
+ );
3836
+ this.field = field;
3837
+ this.value = value;
3838
+ this.scale = scale;
3839
+ this.name = "MoneyPrecisionError";
3840
+ }
3841
+ field;
3842
+ value;
3843
+ scale;
3844
+ };
3845
+ MoneyUnsupportedError = class extends NoydbError {
3846
+ constructor(field, message) {
3847
+ super(
3848
+ "MONEY_UNSUPPORTED",
3849
+ message ?? `money: operation is not supported on field "${field}" \u2014 use sum() and count() and divide at the boundary`
3850
+ );
3851
+ this.field = field;
3852
+ this.name = "MoneyUnsupportedError";
3853
+ }
3854
+ field;
3855
+ };
3856
+ }
3857
+ });
3858
+
3859
+ // src/money/normalize.ts
3860
+ function isMoneyValueObject(v) {
3861
+ return typeof v === "object" && v !== null && "currency" in v;
3862
+ }
3863
+ function quantizeAmount(field, input, scale, rounding) {
3864
+ const r = parseToScaledInt(input, scale, rounding);
3865
+ if (!r.ok) {
3866
+ if (r.reason === "precision") throw new MoneyPrecisionError(field, input, scale);
3867
+ throw new TypeError(`money: field "${field}" value ${JSON.stringify(input)} is not a finite decimal`);
3868
+ }
3869
+ return r.value.toString();
3870
+ }
3871
+ function quantizeMoneyFields(record, moneyFields) {
3872
+ const out = { ...record };
3873
+ for (const [field, desc] of Object.entries(moneyFields)) {
3874
+ const raw = out[field];
3875
+ if (raw === null || raw === void 0) continue;
3876
+ if (desc.mode === "fixed") {
3877
+ const currency2 = desc.fixedCurrency;
3878
+ out[field] = quantizeAmount(field, raw, desc.scaleFor(currency2), desc.rounding);
3879
+ continue;
3880
+ }
3881
+ let amount;
3882
+ let currency;
3883
+ if (isMoneyValueObject(raw)) {
3884
+ currency = String(raw.currency);
3885
+ amount = raw.amount;
3886
+ } else {
3887
+ const sole = desc.soleCurrency();
3888
+ if (sole === void 0) {
3889
+ throw new TypeError(
3890
+ `money: field "${field}" is multi-currency \u2014 write { amount, currency }, not a bare amount`
3891
+ );
3892
+ }
3893
+ currency = sole;
3894
+ amount = raw;
3895
+ }
3896
+ const scale = desc.scaleFor(currency);
3897
+ out[field] = { amount: quantizeAmount(field, amount, scale, desc.rounding), currency };
3898
+ }
3899
+ return out;
3900
+ }
3901
+ function formatCurrency(decimal, currency, scale, locale) {
3902
+ const fmt = new Intl.NumberFormat(locale, {
3903
+ style: "currency",
3904
+ currency,
3905
+ minimumFractionDigits: scale,
3906
+ maximumFractionDigits: scale
3907
+ });
3908
+ return fmt.format(decimal);
3909
+ }
3910
+ function decodeMoneyFields(record, moneyFields, locale) {
3911
+ const out = { ...record };
3912
+ const format = locale !== "raw";
3913
+ const fmtLocale = typeof locale === "string" && locale !== "raw" ? locale : "en-US";
3914
+ for (const [field, desc] of Object.entries(moneyFields)) {
3915
+ const stored = out[field];
3916
+ if (stored === null || stored === void 0) continue;
3917
+ let currency;
3918
+ let scaledIntString;
3919
+ if (desc.mode === "fixed") {
3920
+ if (typeof stored !== "string" && typeof stored !== "number") continue;
3921
+ currency = desc.fixedCurrency;
3922
+ scaledIntString = String(stored);
3923
+ } else {
3924
+ if (!isMoneyValueObject(stored)) continue;
3925
+ const amount = stored.amount;
3926
+ if (typeof stored.currency !== "string" || typeof amount !== "string" && typeof amount !== "number") continue;
3927
+ currency = stored.currency;
3928
+ scaledIntString = String(amount);
3929
+ }
3930
+ const scale = desc.scaleFor(currency);
3931
+ const decimal = formatScaledInt(BigInt(scaledIntString), scale);
3932
+ out[field] = desc.mode === "fixed" ? decimal : { amount: decimal, currency };
3933
+ if (format) {
3934
+ out[`${field}Formatted`] = formatCurrency(decimal, currency, scale, fmtLocale);
3935
+ out[`${field}Number`] = Number(decimal);
3936
+ }
3937
+ }
3938
+ return out;
3939
+ }
3940
+ var init_normalize = __esm({
3941
+ "src/money/normalize.ts"() {
3942
+ "use strict";
3943
+ init_fixed_point();
3944
+ init_descriptor();
3945
+ }
3946
+ });
3947
+
3948
+ // src/computed/index.ts
3949
+ function evalComputedFields(record, computed, id) {
3950
+ const out = { ...record };
3951
+ for (const [field, fn] of Object.entries(computed)) {
3952
+ try {
3953
+ out[field] = fn(out);
3954
+ } catch (cause) {
3955
+ throw new ComputedFieldError(field, id, cause);
3956
+ }
3957
+ }
3958
+ return out;
3959
+ }
3960
+ var ComputedFieldError;
3961
+ var init_computed = __esm({
3962
+ "src/computed/index.ts"() {
3963
+ "use strict";
3964
+ init_errors();
3965
+ ComputedFieldError = class extends NoydbError {
3966
+ constructor(field, id, cause) {
3967
+ super(
3968
+ "COMPUTED_FIELD",
3969
+ `computed field "${field}" threw for record "${id}": ` + (cause instanceof Error ? cause.message : String(cause))
3970
+ );
3971
+ this.field = field;
3972
+ this.id = id;
3973
+ this.cause = cause;
3974
+ this.name = "ComputedFieldError";
3975
+ }
3976
+ field;
3977
+ id;
3978
+ cause;
3979
+ };
3980
+ }
3981
+ });
3982
+
3606
3983
  // src/i18n/strategy.ts
3607
3984
  function notEnabled(op) {
3608
3985
  return new Error(
@@ -4087,6 +4464,189 @@ var init_strategy4 = __esm({
4087
4464
  }
4088
4465
  });
4089
4466
 
4467
+ // src/money/money-reducer.ts
4468
+ function toScaledInt(v) {
4469
+ if (typeof v === "string" || typeof v === "number" || typeof v === "bigint") {
4470
+ try {
4471
+ return BigInt(v);
4472
+ } catch {
4473
+ return null;
4474
+ }
4475
+ }
4476
+ return null;
4477
+ }
4478
+ function readMoney(record, field, desc) {
4479
+ const raw = readPath(record, field);
4480
+ if (raw === null || raw === void 0) return null;
4481
+ if (desc.mode === "fixed") {
4482
+ const value2 = toScaledInt(raw);
4483
+ return value2 === null ? null : { currency: desc.fixedCurrency, value: value2 };
4484
+ }
4485
+ if (typeof raw !== "object") return null;
4486
+ const o = raw;
4487
+ if (typeof o.currency !== "string") return null;
4488
+ const value = toScaledInt(o.amount);
4489
+ return value === null ? null : { currency: o.currency, value };
4490
+ }
4491
+ function targetScaleFor(desc, currency) {
4492
+ if (desc.allows(currency)) return desc.scaleFor(currency);
4493
+ const s = scaleForCurrency(currency);
4494
+ if (s === null) {
4495
+ throw new Error(`money: cannot determine scale for conversion target "${currency}"`);
4496
+ }
4497
+ return s;
4498
+ }
4499
+ function parseRate(rate) {
4500
+ const s = String(rate).trim();
4501
+ const neg = s.startsWith("-");
4502
+ const body = neg ? s.slice(1) : s;
4503
+ const dot = body.indexOf(".");
4504
+ const intPart = dot === -1 ? body : body.slice(0, dot);
4505
+ const fracPart = dot === -1 ? "" : body.slice(dot + 1);
4506
+ const int = BigInt((intPart === "" ? "0" : intPart) + fracPart);
4507
+ return { int: neg ? -int : int, scale: fracPart.length };
4508
+ }
4509
+ function divRoundHalfEven(n, d) {
4510
+ const q = n / d;
4511
+ const r = n % d;
4512
+ const twiceR = (r < 0n ? -r : r) * 2n;
4513
+ if (twiceR < d) return q;
4514
+ if (twiceR > d) return q + (n < 0n ? -1n : 1n);
4515
+ return q % 2n === 0n ? q : q + (n < 0n ? -1n : 1n);
4516
+ }
4517
+ function convertScaled(value, srcScale, rate, targetScale) {
4518
+ const { int: rateInt, scale: rateScale } = parseRate(rate);
4519
+ const product = value * rateInt;
4520
+ const curScale = srcScale + rateScale;
4521
+ if (curScale === targetScale) return product;
4522
+ if (curScale < targetScale) return product * 10n ** BigInt(targetScale - curScale);
4523
+ return divRoundHalfEven(product, 10n ** BigInt(curScale - targetScale));
4524
+ }
4525
+ function finalizeSum(state, desc, convertTo, fx) {
4526
+ if (convertTo !== void 0) {
4527
+ if (fx === void 0) {
4528
+ throw new Error(`money: sum convertTo "${convertTo}" requires an fx rate map`);
4529
+ }
4530
+ const targetScale = targetScaleFor(desc, convertTo);
4531
+ let total = 0n;
4532
+ for (const [cur, v] of state) {
4533
+ if (cur === convertTo) {
4534
+ total += convertScaled(v, desc.scaleFor(cur), 1, targetScale);
4535
+ continue;
4536
+ }
4537
+ const rate = fx[`${cur}->${convertTo}`];
4538
+ if (rate === void 0) {
4539
+ throw new Error(`money: no fx rate for "${cur}->${convertTo}"`);
4540
+ }
4541
+ total += convertScaled(v, desc.scaleFor(cur), rate, targetScale);
4542
+ }
4543
+ return formatScaledInt(total, targetScale);
4544
+ }
4545
+ if (desc.mode === "fixed") {
4546
+ const cur = desc.fixedCurrency;
4547
+ return formatScaledInt(state.get(cur) ?? 0n, desc.scaleFor(cur));
4548
+ }
4549
+ const out = {};
4550
+ for (const [cur, v] of state) out[cur] = formatScaledInt(v, desc.scaleFor(cur));
4551
+ return out;
4552
+ }
4553
+ function moneySumReducer(field, desc, convertTo, fx) {
4554
+ return {
4555
+ op: "sum",
4556
+ field,
4557
+ init: () => /* @__PURE__ */ new Map(),
4558
+ step: (state, record) => {
4559
+ const m = readMoney(record, field, desc);
4560
+ if (m) state.set(m.currency, (state.get(m.currency) ?? 0n) + m.value);
4561
+ return state;
4562
+ },
4563
+ remove: (state, record) => {
4564
+ const m = readMoney(record, field, desc);
4565
+ if (m) state.set(m.currency, (state.get(m.currency) ?? 0n) - m.value);
4566
+ return state;
4567
+ },
4568
+ finalize: (state) => finalizeSum(state, desc, convertTo, fx)
4569
+ };
4570
+ }
4571
+ function extremum(values, op) {
4572
+ let out = values[0];
4573
+ for (let i = 1; i < values.length; i++) {
4574
+ const v = values[i];
4575
+ if (op === "min" ? v < out : v > out) out = v;
4576
+ }
4577
+ return out;
4578
+ }
4579
+ function moneyMinMaxReducer(op, field, desc) {
4580
+ return {
4581
+ op,
4582
+ field,
4583
+ init: () => /* @__PURE__ */ new Map(),
4584
+ step: (state, record) => {
4585
+ const m = readMoney(record, field, desc);
4586
+ if (m) {
4587
+ const arr = state.get(m.currency);
4588
+ if (arr) arr.push(m.value);
4589
+ else state.set(m.currency, [m.value]);
4590
+ }
4591
+ return state;
4592
+ },
4593
+ remove: (state, record) => {
4594
+ const m = readMoney(record, field, desc);
4595
+ if (m) {
4596
+ const arr = state.get(m.currency);
4597
+ if (arr) {
4598
+ const idx = arr.indexOf(m.value);
4599
+ if (idx >= 0) arr.splice(idx, 1);
4600
+ }
4601
+ }
4602
+ return state;
4603
+ },
4604
+ finalize: (state) => {
4605
+ if (desc.mode === "fixed") {
4606
+ const cur = desc.fixedCurrency;
4607
+ const arr = state.get(cur);
4608
+ if (!arr || arr.length === 0) return null;
4609
+ return formatScaledInt(extremum(arr, op), desc.scaleFor(cur));
4610
+ }
4611
+ const out = {};
4612
+ for (const [cur, arr] of state) {
4613
+ if (arr.length > 0) out[cur] = formatScaledInt(extremum(arr, op), desc.scaleFor(cur));
4614
+ }
4615
+ return out;
4616
+ }
4617
+ };
4618
+ }
4619
+ function wrapMoneyReducers(spec, moneyFields) {
4620
+ let changed = false;
4621
+ const out = {};
4622
+ for (const [key, reducer] of Object.entries(spec)) {
4623
+ const field = reducer.field;
4624
+ const desc = field ? moneyFields[field] : void 0;
4625
+ if (desc && reducer.op === "avg") {
4626
+ throw new MoneyUnsupportedError(
4627
+ field,
4628
+ `avg() is not supported on money field "${field}" in v1 \u2014 use sum() and count() and divide at the boundary.`
4629
+ );
4630
+ }
4631
+ if (desc && (reducer.op === "sum" || reducer.op === "min" || reducer.op === "max")) {
4632
+ changed = true;
4633
+ out[key] = reducer.op === "sum" ? moneySumReducer(field, desc, reducer.convertTo, reducer.fx) : moneyMinMaxReducer(reducer.op, field, desc);
4634
+ } else {
4635
+ out[key] = reducer;
4636
+ }
4637
+ }
4638
+ return changed ? out : spec;
4639
+ }
4640
+ var init_money_reducer = __esm({
4641
+ "src/money/money-reducer.ts"() {
4642
+ "use strict";
4643
+ init_predicate();
4644
+ init_fixed_point();
4645
+ init_iso4217();
4646
+ init_descriptor();
4647
+ }
4648
+ });
4649
+
4090
4650
  // src/query/builder.ts
4091
4651
  function executePlanWithSource(source, plan, joinContext) {
4092
4652
  const hasCrossJoins = plan.clauses.some((c) => c.type === "crossJoin");
@@ -4363,6 +4923,7 @@ var init_builder = __esm({
4363
4923
  init_errors();
4364
4924
  init_live();
4365
4925
  init_strategy4();
4926
+ init_money_reducer();
4366
4927
  EMPTY_PLAN = {
4367
4928
  clauses: [],
4368
4929
  orderBy: [],
@@ -4808,6 +5369,10 @@ var init_builder = __esm({
4808
5369
  * partition boundaries without an API break.
4809
5370
  */
4810
5371
  aggregate(spec) {
5372
+ const moneyFields = this.source.moneyFields;
5373
+ if (moneyFields) {
5374
+ spec = wrapMoneyReducers(spec, moneyFields);
5375
+ }
4811
5376
  const source = this.source;
4812
5377
  const clauses = this.plan.clauses;
4813
5378
  const joinCtx = this.joinContext;
@@ -4855,13 +5420,15 @@ var init_builder = __esm({
4855
5420
  executeRecords,
4856
5421
  field,
4857
5422
  upstreams,
4858
- dictLabelResolver
5423
+ dictLabelResolver,
5424
+ this.source.moneyFields
4859
5425
  );
4860
5426
  }
4861
5427
  return this.aggregateStrategy.groupByN(
4862
5428
  executeRecords,
4863
5429
  fields,
4864
- upstreams
5430
+ upstreams,
5431
+ this.source.moneyFields
4865
5432
  );
4866
5433
  }
4867
5434
  /**
@@ -4982,6 +5549,29 @@ var init_builder = __esm({
4982
5549
  }
4983
5550
  });
4984
5551
 
5552
+ // src/aggregate/aggregation.ts
5553
+ function reduceRecords(records, spec) {
5554
+ const state = {};
5555
+ for (const key of Object.keys(spec)) {
5556
+ state[key] = spec[key].init();
5557
+ }
5558
+ for (const record of records) {
5559
+ for (const key of Object.keys(spec)) {
5560
+ state[key] = spec[key].step(state[key], record);
5561
+ }
5562
+ }
5563
+ const result = {};
5564
+ for (const key of Object.keys(spec)) {
5565
+ result[key] = spec[key].finalize(state[key]);
5566
+ }
5567
+ return result;
5568
+ }
5569
+ var init_aggregation = __esm({
5570
+ "src/aggregate/aggregation.ts"() {
5571
+ "use strict";
5572
+ }
5573
+ });
5574
+
4985
5575
  // src/aggregate/canonical-key.ts
4986
5576
  function canonicalGroupKey(fields, row) {
4987
5577
  const sorted = [...fields].sort();
@@ -7017,6 +7607,8 @@ var init_collection = __esm({
7017
7607
  init_types();
7018
7608
  init_strategy();
7019
7609
  init_core();
7610
+ init_normalize();
7611
+ init_computed();
7020
7612
  init_strategy2();
7021
7613
  init_policy();
7022
7614
  init_crypto();
@@ -7185,6 +7777,18 @@ var init_collection = __esm({
7185
7777
  * fields when a locale is requested.
7186
7778
  */
7187
7779
  dictKeyFields;
7780
+ /**
7781
+ * Money field descriptors keyed by field path. Declared via the
7782
+ * `moneyFields` collection option: `put()` quantizes to a scaled-int
7783
+ * string, `get()`/`list()` decode back. Mutable so {@link _applyMoneyFields}
7784
+ * can attach descriptors to a collection MV-analysis pre-created.
7785
+ */
7786
+ moneyFields;
7787
+ /**
7788
+ * Computed scalar fields, evaluated first on every `put()`. Mutable for
7789
+ * the same MV-pre-creation reconcile as {@link moneyFields}.
7790
+ */
7791
+ computed;
7188
7792
  /**
7189
7793
  * Async callback provided by the Vault that resolves a dict key
7190
7794
  * to its label for a given locale. Used by the locale-read path for
@@ -7326,6 +7930,8 @@ var init_collection = __esm({
7326
7930
  this.joinResolver = opts.joinResolver;
7327
7931
  this.i18nFields = opts.i18nFields;
7328
7932
  this.dictKeyFields = opts.dictKeyFields;
7933
+ this.moneyFields = opts.moneyFields;
7934
+ this.computed = opts.computed;
7329
7935
  this.dictLabelResolver = opts.dictLabelResolver;
7330
7936
  this.i18nPutValidator = opts.i18nPutValidator;
7331
7937
  this.autoTranslateHook = opts.autoTranslateHook;
@@ -7450,6 +8056,19 @@ var init_collection = __esm({
7450
8056
  getSchema() {
7451
8057
  return this.schema;
7452
8058
  }
8059
+ /**
8060
+ * @internal — attach money descriptors post-construction. MV dependency
8061
+ * analysis auto-creates a source collection (without options) during
8062
+ * `openVault`, before the user's `collection(name, { moneyFields })`
8063
+ * declaration; this reconciles that ordering. First-wins. Not public.
8064
+ */
8065
+ _applyMoneyFields(moneyFields) {
8066
+ if (this.moneyFields === void 0) this.moneyFields = moneyFields;
8067
+ }
8068
+ /** @internal — attach computed fields post-construction. See {@link _applyMoneyFields}. */
8069
+ _applyComputed(computed) {
8070
+ if (this.computed === void 0) this.computed = computed;
8071
+ }
7453
8072
  /**
7454
8073
  * Get a single record by ID.
7455
8074
  *
@@ -7621,7 +8240,7 @@ var init_collection = __esm({
7621
8240
  existingRecord = null;
7622
8241
  }
7623
8242
  }
7624
- await this.subsystemBus.dispatchGate("beforePut", {
8243
+ const gateEvent = {
7625
8244
  op: existingEnv ? "update" : "create",
7626
8245
  vault: this.vault,
7627
8246
  collection: this.name,
@@ -7631,12 +8250,20 @@ var init_collection = __esm({
7631
8250
  existingVersion: existingEnv?._v ?? 0,
7632
8251
  existingTs: existingEnv?._ts,
7633
8252
  userId: this.keyring.userId,
7634
- role: this.keyring.role
7635
- });
8253
+ role: this.keyring.role,
8254
+ ...this.computed !== void 0 ? { computedFieldNames: new Set(Object.keys(this.computed)) } : {}
8255
+ };
8256
+ await this.subsystemBus.dispatchGate("beforePut", gateEvent);
8257
+ }
8258
+ if (this.computed !== void 0) {
8259
+ record = evalComputedFields(record, this.computed, id);
7636
8260
  }
7637
8261
  if (this.schema !== void 0) {
7638
8262
  record = await validateSchemaInput(this.schema, record, `put(${id})`);
7639
8263
  }
8264
+ if (this.moneyFields) {
8265
+ record = quantizeMoneyFields(record, this.moneyFields);
8266
+ }
7640
8267
  if (this.i18nFields) {
7641
8268
  const obj = record;
7642
8269
  for (const [field, descriptor] of Object.entries(this.i18nFields)) {
@@ -8458,7 +9085,8 @@ var init_collection = __esm({
8458
9085
  // fields. The Query builder consults these when present and falls
8459
9086
  // back to a linear scan otherwise.
8460
9087
  getIndexes: () => this.getIndexes(),
8461
- lookupById: (id) => this.cache.get(id)?.record
9088
+ lookupById: (id) => this.cache.get(id)?.record,
9089
+ ...this.moneyFields ? { moneyFields: this.moneyFields } : {}
8462
9090
  };
8463
9091
  const resolver = this.joinResolver;
8464
9092
  const leftCollection = this.name;
@@ -9140,10 +9768,14 @@ var init_collection = __esm({
9140
9768
  async applyLocaleToRecord(record, localeOpts) {
9141
9769
  const hasI18n = this.i18nFields && Object.keys(this.i18nFields).length > 0;
9142
9770
  const hasDict = this.dictKeyFields && Object.keys(this.dictKeyFields).length > 0;
9143
- if (!hasI18n && !hasDict) return record;
9771
+ const hasMoney = this.moneyFields && Object.keys(this.moneyFields).length > 0;
9772
+ if (!hasI18n && !hasDict && !hasMoney) return record;
9144
9773
  const locale = localeOpts?.locale ?? this.defaultLocale;
9145
- if (!locale) return record;
9146
9774
  let result = record;
9775
+ if (hasMoney && this.moneyFields) {
9776
+ result = decodeMoneyFields(result, this.moneyFields, typeof locale === "string" ? locale : void 0);
9777
+ }
9778
+ if (!locale) return result;
9147
9779
  if (hasI18n && this.i18nFields) {
9148
9780
  result = this.i18nStrategy.applyI18nLocale(result, this.i18nFields, locale, localeOpts?.fallback);
9149
9781
  }
@@ -9982,6 +10614,182 @@ var init_virtual_collection = __esm({
9982
10614
  }
9983
10615
  });
9984
10616
 
10617
+ // src/archive/engine.ts
10618
+ function isHeld(policy, record) {
10619
+ if (!policy.legalHold) return false;
10620
+ try {
10621
+ return policy.legalHold(record);
10622
+ } catch {
10623
+ return true;
10624
+ }
10625
+ }
10626
+ async function runArchive(ctx, options = {}) {
10627
+ const maxArchives = options.maxArchives ?? Infinity;
10628
+ const dryRun = options.dryRun === true;
10629
+ let archived = 0;
10630
+ let held = 0;
10631
+ let scanned = 0;
10632
+ const byCollection = {};
10633
+ outer: for (const collection of ctx.collectionsWithPolicy()) {
10634
+ const policy = ctx.getPolicy(collection);
10635
+ if (!policy) continue;
10636
+ byCollection[collection] = { archived: 0, held: 0 };
10637
+ for (const id of await ctx.listRecordIds(collection)) {
10638
+ if (archived >= maxArchives) break outer;
10639
+ const record = await ctx.getRecord(collection, id).catch(() => null);
10640
+ if (record === null) continue;
10641
+ scanned += 1;
10642
+ let eligible = false;
10643
+ try {
10644
+ eligible = policy.archiveWhen(record);
10645
+ } catch {
10646
+ eligible = false;
10647
+ }
10648
+ if (!eligible) continue;
10649
+ if (isHeld(policy, record)) {
10650
+ held += 1;
10651
+ byCollection[collection].held += 1;
10652
+ continue;
10653
+ }
10654
+ if (!dryRun) {
10655
+ const env = await ctx.getEnvelope(collection, id);
10656
+ if (!env) continue;
10657
+ await ctx.archiveStore.put(ctx.vaultId, collection, id, env);
10658
+ await ctx.removeFromPrimary(collection, id);
10659
+ }
10660
+ archived += 1;
10661
+ byCollection[collection].archived += 1;
10662
+ }
10663
+ }
10664
+ return { archived, held, scanned, byCollection };
10665
+ }
10666
+ async function runRestore(ctx, collection, id) {
10667
+ const env = await ctx.archiveStore.get(ctx.vaultId, collection, id);
10668
+ if (!env) return false;
10669
+ await ctx.restoreToPrimary(collection, id, env);
10670
+ await ctx.archiveStore.delete(ctx.vaultId, collection, id);
10671
+ return true;
10672
+ }
10673
+ async function runListArchived(ctx, collection) {
10674
+ const collections = collection ? [collection] : ctx.collectionsWithPolicy();
10675
+ const out = [];
10676
+ for (const c of collections) {
10677
+ const ids = await ctx.archiveStore.list(ctx.vaultId, c);
10678
+ for (const id of ids) out.push({ collection: c, id });
10679
+ }
10680
+ return out;
10681
+ }
10682
+ var init_engine = __esm({
10683
+ "src/archive/engine.ts"() {
10684
+ "use strict";
10685
+ }
10686
+ });
10687
+
10688
+ // src/archive/index.ts
10689
+ var init_archive = __esm({
10690
+ "src/archive/index.ts"() {
10691
+ "use strict";
10692
+ init_engine();
10693
+ }
10694
+ });
10695
+
10696
+ // src/sequence/index.ts
10697
+ async function sleepBackoff2(attempt) {
10698
+ const ceil = Math.min(2 ** attempt, 32);
10699
+ const ms = Math.floor(Math.random() * ceil);
10700
+ await new Promise((r) => setTimeout(r, ms));
10701
+ }
10702
+ var SEQUENCE_COLLECTION, MAX_NEXT_ATTEMPTS, SequenceStore;
10703
+ var init_sequence = __esm({
10704
+ "src/sequence/index.ts"() {
10705
+ "use strict";
10706
+ init_types();
10707
+ init_crypto();
10708
+ init_errors();
10709
+ SEQUENCE_COLLECTION = "_sequences";
10710
+ MAX_NEXT_ATTEMPTS = 16;
10711
+ SequenceStore = class {
10712
+ adapter;
10713
+ vault;
10714
+ encrypted;
10715
+ getDEK;
10716
+ actor;
10717
+ /**
10718
+ * Memoized DEK promise. The `_sequences` collection DEK is created on
10719
+ * first access; without sharing one promise, a burst of concurrent
10720
+ * `next()` calls would each trigger DEK creation and diverge (one
10721
+ * writer's ciphertext unreadable by another). One shared promise → one
10722
+ * DEK.
10723
+ */
10724
+ dekPromise = null;
10725
+ constructor(opts) {
10726
+ this.adapter = opts.adapter;
10727
+ this.vault = opts.vault;
10728
+ this.encrypted = opts.encrypted;
10729
+ this.getDEK = opts.getDEK;
10730
+ this.actor = opts.actor;
10731
+ }
10732
+ /** A handle bound to one sequence name. */
10733
+ handle(name) {
10734
+ return {
10735
+ next: () => this.next(name),
10736
+ peek: () => this.peek(name)
10737
+ };
10738
+ }
10739
+ assertOnline() {
10740
+ if (this.adapter.capabilities?.casAtomic !== true) {
10741
+ throw new SequenceOfflineError();
10742
+ }
10743
+ }
10744
+ dek() {
10745
+ if (!this.dekPromise) this.dekPromise = this.getDEK(SEQUENCE_COLLECTION);
10746
+ return this.dekPromise;
10747
+ }
10748
+ async read(name) {
10749
+ const env = await this.adapter.get(this.vault, SEQUENCE_COLLECTION, name);
10750
+ if (!env) return { env: null, value: 0 };
10751
+ const json = this.encrypted ? await decrypt(env._iv, env._data, await this.dek()) : env._data;
10752
+ const state = JSON.parse(json);
10753
+ return { env, value: state.value };
10754
+ }
10755
+ async encryptState(state, version) {
10756
+ const json = JSON.stringify(state);
10757
+ if (!this.encrypted) {
10758
+ return { _noydb: NOYDB_FORMAT_VERSION, _v: version, _ts: (/* @__PURE__ */ new Date()).toISOString(), _iv: "", _data: json, _by: this.actor };
10759
+ }
10760
+ const { iv, data } = await encrypt(json, await this.dek());
10761
+ return { _noydb: NOYDB_FORMAT_VERSION, _v: version, _ts: (/* @__PURE__ */ new Date()).toISOString(), _iv: iv, _data: data, _by: this.actor };
10762
+ }
10763
+ async peek(name) {
10764
+ return (await this.read(name)).value;
10765
+ }
10766
+ async next(name) {
10767
+ this.assertOnline();
10768
+ let lastConflict;
10769
+ for (let attempt = 0; attempt < MAX_NEXT_ATTEMPTS; attempt++) {
10770
+ const { env, value } = await this.read(name);
10771
+ const nextValue = value + 1;
10772
+ const expectedVersion = env?._v ?? 0;
10773
+ const envelope = await this.encryptState({ value: nextValue }, expectedVersion + 1);
10774
+ try {
10775
+ await this.adapter.put(this.vault, SEQUENCE_COLLECTION, name, envelope, expectedVersion);
10776
+ return nextValue;
10777
+ } catch (err) {
10778
+ if (err instanceof ConflictError) {
10779
+ lastConflict = err;
10780
+ if (attempt < MAX_NEXT_ATTEMPTS - 1) await sleepBackoff2(attempt);
10781
+ continue;
10782
+ }
10783
+ throw err;
10784
+ }
10785
+ }
10786
+ void lastConflict;
10787
+ throw new SequenceContentionError(name, MAX_NEXT_ATTEMPTS);
10788
+ }
10789
+ };
10790
+ }
10791
+ });
10792
+
9985
10793
  // src/shadow/strategy.ts
9986
10794
  var NOT_ENABLED3, NO_SHADOW;
9987
10795
  var init_strategy7 = __esm({
@@ -10274,6 +11082,7 @@ async function runCompaction(ctx, options = {}) {
10274
11082
  let evicted = 0;
10275
11083
  let records = 0;
10276
11084
  let auditEntries = 0;
11085
+ let held = 0;
10277
11086
  let collectionsWithPolicy = 0;
10278
11087
  outer: for (const collectionName of allCollections) {
10279
11088
  if (collectionName.startsWith("_")) continue;
@@ -10297,6 +11106,10 @@ async function runCompaction(ctx, options = {}) {
10297
11106
  if (!policy) continue;
10298
11107
  const reason = evaluatePolicy(policy, record, slot, now);
10299
11108
  if (!reason) continue;
11109
+ if (isHeld2(policy, record, now)) {
11110
+ held += 1;
11111
+ continue;
11112
+ }
10300
11113
  if (!dryRun) {
10301
11114
  await ctx.deleteSlot(collectionName, recordId2, slot.name);
10302
11115
  await writeAuditEntry(ctx, {
@@ -10321,9 +11134,32 @@ async function runCompaction(ctx, options = {}) {
10321
11134
  records,
10322
11135
  collections: collectionsWithPolicy,
10323
11136
  auditEntries,
11137
+ held,
10324
11138
  byCollection
10325
11139
  };
10326
11140
  }
11141
+ function isHeld2(policy, record, now) {
11142
+ if (policy.legalHold) {
11143
+ try {
11144
+ if (policy.legalHold(record)) return true;
11145
+ } catch {
11146
+ return true;
11147
+ }
11148
+ }
11149
+ if (policy.retainUntil) {
11150
+ try {
11151
+ const until = policy.retainUntil(record);
11152
+ if (until !== null && until !== void 0) {
11153
+ const t = until instanceof Date ? until.getTime() : typeof until === "number" ? until : Date.parse(String(until));
11154
+ if (!Number.isFinite(t)) return true;
11155
+ if (t > now.getTime()) return true;
11156
+ }
11157
+ } catch {
11158
+ return true;
11159
+ }
11160
+ }
11161
+ return false;
11162
+ }
10327
11163
  function evaluatePolicy(policy, record, slot, now) {
10328
11164
  let ttlTriggered = false;
10329
11165
  let predicateTriggered = false;
@@ -12081,6 +12917,8 @@ var init_vault = __esm({
12081
12917
  init_keyring();
12082
12918
  init_errors();
12083
12919
  init_errors();
12920
+ init_archive();
12921
+ init_sequence();
12084
12922
  init_constants();
12085
12923
  init_entry();
12086
12924
  init_strategy3();
@@ -12139,6 +12977,10 @@ var init_vault = __esm({
12139
12977
  * call throws with a pointer at `@noy-db/hub/blobs`.
12140
12978
  */
12141
12979
  blobStrategy;
12980
+ /** Cold-storage archival strategy (the archive target store). */
12981
+ archiveStrategy;
12982
+ /** Per-collection record archival policies. Indexed by collection name. */
12983
+ archiveRegistry = /* @__PURE__ */ new Map();
12142
12984
  indexStrategy;
12143
12985
  aggregateStrategy;
12144
12986
  crdtStrategy;
@@ -12242,6 +13084,8 @@ var init_vault = __esm({
12242
13084
  * docstring.
12243
13085
  */
12244
13086
  ledgerStore = null;
13087
+ /** Lazily-built atomic-sequence store. See {@link sequence}. */
13088
+ sequenceStore = null;
12245
13089
  /**
12246
13090
  * Background writes for persisted-schema envelopes (#schema-dump v0
12247
13091
  * slice 1). One promise per `collection({ persistJsonSchema: true })`
@@ -12343,6 +13187,7 @@ var init_vault = __esm({
12343
13187
  this.onRegisterConflictResolver = opts.onRegisterConflictResolver;
12344
13188
  this.syncAdapter = opts.syncAdapter;
12345
13189
  this.blobStrategy = opts.blobStrategy;
13190
+ this.archiveStrategy = opts.archiveStrategy;
12346
13191
  this.indexStrategy = opts.indexStrategy;
12347
13192
  this.aggregateStrategy = opts.aggregateStrategy;
12348
13193
  this.crdtStrategy = opts.crdtStrategy;
@@ -12405,8 +13250,9 @@ var init_vault = __esm({
12405
13250
  *. `put()` validates keys against the declared set; reads
12406
13251
  * with `{ locale }` add `<field>Label` virtual fields.
12407
13252
  *
12408
- * Throws `ReservedCollectionNameError` for names starting with `_dict_`.
12409
- * Use `vault.dictionary(name)` to access dictionary collections.
13253
+ * Throws `ReservedCollectionNameError` for names starting with `_dict_` or
13254
+ * equal to `_sequences`. Use `vault.dictionary(name)` for dict collections
13255
+ * and `vault.sequence(name)` for sequence counters.
12410
13256
  *
12411
13257
  * Lazy mode + indexes is rejected at construction time — see the
12412
13258
  * Collection constructor for the rationale.
@@ -12425,7 +13271,16 @@ var init_vault = __esm({
12425
13271
  if (isDictCollectionName(collectionName)) {
12426
13272
  throw new ReservedCollectionNameError(collectionName);
12427
13273
  }
13274
+ if (collectionName === SEQUENCE_COLLECTION) {
13275
+ throw new ReservedCollectionNameError(collectionName);
13276
+ }
12428
13277
  let coll = this.collectionCache.get(collectionName);
13278
+ if (coll && options?.moneyFields) {
13279
+ coll._applyMoneyFields(options.moneyFields);
13280
+ }
13281
+ if (coll && options?.computed) {
13282
+ coll._applyComputed(options.computed);
13283
+ }
12429
13284
  if (!coll) {
12430
13285
  if (options?.refs) {
12431
13286
  this.refRegistry.register(collectionName, options.refs);
@@ -12436,6 +13291,9 @@ var init_vault = __esm({
12436
13291
  if (options?.blobFields) {
12437
13292
  this.blobFieldsRegistry.set(collectionName, options.blobFields);
12438
13293
  }
13294
+ if (options?.archive) {
13295
+ this.archiveRegistry.set(collectionName, options.archive);
13296
+ }
12439
13297
  if (options?.attestation !== void 0) {
12440
13298
  this.attestationRegistry.set(collectionName, options.attestation);
12441
13299
  }
@@ -12551,6 +13409,8 @@ var init_vault = __esm({
12551
13409
  collOpts.onCrossTierAccess = (event) => this.emitCrossTier(event);
12552
13410
  if (this.syncAdapter !== void 0) collOpts.syncAdapter = this.syncAdapter;
12553
13411
  if (options?.i18nFields !== void 0) collOpts.i18nFields = options.i18nFields;
13412
+ if (options?.moneyFields !== void 0) collOpts.moneyFields = options.moneyFields;
13413
+ if (options?.computed !== void 0) collOpts.computed = options.computed;
12554
13414
  if (options?.dictKeyFields !== void 0) {
12555
13415
  collOpts.dictLabelResolver = async (dictName, key, locale, fallback) => {
12556
13416
  const handle = this.dictionary(dictName);
@@ -12970,6 +13830,33 @@ var init_vault = __esm({
12970
13830
  * await vault.compact({ maxEvictions: 1000 }) // cap batch
12971
13831
  * ```
12972
13832
  */
13833
+ /**
13834
+ * Atomic, gap-free numbering. `vault.sequence('invoice-2026').next()`
13835
+ * returns 1, 2, 3, … with no gaps or duplicates under concurrency, via
13836
+ * an optimistic-CAS counter at `_sequences/<name>`. Each name is an
13837
+ * independent sequence.
13838
+ *
13839
+ * **Online-only:** `next()` throws `SequenceOfflineError` unless the
13840
+ * store advertises `capabilities.casAtomic` — gap-free numbering cannot
13841
+ * be serialized by an offline / non-CAS writer.
13842
+ *
13843
+ * ```ts
13844
+ * const n = await vault.sequence('invoice-2026').next() // 1, then 2, …
13845
+ * const cur = await vault.sequence('invoice-2026').peek() // current value, no allocation
13846
+ * ```
13847
+ */
13848
+ sequence(name) {
13849
+ if (!this.sequenceStore) {
13850
+ this.sequenceStore = new SequenceStore({
13851
+ adapter: this.adapter,
13852
+ vault: this.name,
13853
+ encrypted: this.encrypted,
13854
+ getDEK: this.getDEK,
13855
+ actor: this.keyring.userId
13856
+ });
13857
+ }
13858
+ return this.sequenceStore.handle(name);
13859
+ }
12973
13860
  async compact(options = {}) {
12974
13861
  return runCompaction({
12975
13862
  adapter: this.adapter,
@@ -12994,6 +13881,48 @@ var init_vault = __esm({
12994
13881
  }
12995
13882
  }, options);
12996
13883
  }
13884
+ /**
13885
+ * Sweep records eligible by their collection's `archive` policy into the
13886
+ * cold archive store. Relocation is envelope-level (no re-encryption) and
13887
+ * bypasses guards + materialized-view dispatch, so issued/immutable
13888
+ * records over a sealed period can be archived without recomputing
13889
+ * finalized aggregates. A `legalHold` predicate blocks archival.
13890
+ * Requires `archiveStrategy: withArchive({ store })` in `createNoydb`.
13891
+ */
13892
+ async archive(options = {}) {
13893
+ return runArchive(this._archiveContext(), options);
13894
+ }
13895
+ /** Relocate one archived record back to the primary store. Returns false if it was not archived. */
13896
+ async restore(collection, id) {
13897
+ return runRestore(this._archiveContext(), collection, id);
13898
+ }
13899
+ /** List archived record ids for a collection (or all collections with an archive policy). */
13900
+ async listArchived(collection) {
13901
+ return runListArchived(this._archiveContext(), collection);
13902
+ }
13903
+ _archiveContext() {
13904
+ const strategy = this.archiveStrategy;
13905
+ if (!strategy) {
13906
+ throw new Error(
13907
+ "vault.archive/restore/listArchived require `archiveStrategy: withArchive({ store })` in createNoydb"
13908
+ );
13909
+ }
13910
+ const archiveStore = strategy.store;
13911
+ return {
13912
+ vaultId: this.name,
13913
+ archiveStore,
13914
+ collectionsWithPolicy: () => [...this.archiveRegistry.keys()],
13915
+ getPolicy: (c) => this.archiveRegistry.get(c) ?? null,
13916
+ listRecordIds: (c) => this.adapter.list(this.name, c),
13917
+ getRecord: async (c, id) => await this.collection(c).get(id, { locale: "raw" }),
13918
+ getEnvelope: (c, id) => this.adapter.get(this.name, c, id),
13919
+ removeFromPrimary: (c, id) => this.collection(c)._internalDelete(id),
13920
+ restoreToPrimary: async (c, id, env) => {
13921
+ await this.adapter.put(this.name, c, id, env);
13922
+ await this.collection(c)._invalidateCacheEntry(id);
13923
+ }
13924
+ };
13925
+ }
12997
13926
  exportBlobs(options = {}) {
12998
13927
  this.assertCanExport("plaintext", "blob");
12999
13928
  return createExportBlobsHandle(
@@ -14255,7 +15184,7 @@ var init_vault = __esm({
14255
15184
  }
14256
15185
  }
14257
15186
  const internalSnapshot = {};
14258
- for (const internalName of [LEDGER_COLLECTION, LEDGER_DELTAS_COLLECTION, SCHEMAS_COLLECTION]) {
15187
+ for (const internalName of [LEDGER_COLLECTION, LEDGER_DELTAS_COLLECTION, SCHEMAS_COLLECTION, SEQUENCE_COLLECTION]) {
14259
15188
  const ids = await this.adapter.list(this.name, internalName);
14260
15189
  if (ids.length === 0) continue;
14261
15190
  const records = {};
@@ -15870,7 +16799,7 @@ function deny(gate, reason, required) {
15870
16799
  return new PolicyDeniedError(gate, reason, required);
15871
16800
  }
15872
16801
  var DEFAULT_FRESHNESS_MS;
15873
- var init_engine = __esm({
16802
+ var init_engine2 = __esm({
15874
16803
  "src/policy/engine.ts"() {
15875
16804
  "use strict";
15876
16805
  init_errors2();
@@ -15883,7 +16812,7 @@ var init_policy3 = __esm({
15883
16812
  "src/policy/index.ts"() {
15884
16813
  "use strict";
15885
16814
  init_presets();
15886
- init_engine();
16815
+ init_engine2();
15887
16816
  init_storage5();
15888
16817
  }
15889
16818
  });
@@ -15927,14 +16856,21 @@ var init_executor3 = __esm({
15927
16856
  * Compare existing vs incoming for each `frozenFields.fields` entry
15928
16857
  * when `frozenFields.when(existing)` is true. Throws
15929
16858
  * `FieldFrozenError` listing every changed frozen field.
16859
+ *
16860
+ * @param skipFields — field names that are schema-owned computed fields.
16861
+ * These are excluded from the comparison because `incoming` carries the
16862
+ * raw user input (computed fields not yet evaluated), so comparing
16863
+ * `existing[field]` vs `incoming[field]` would always look like a
16864
+ * change even when the computed result is unchanged.
15930
16865
  */
15931
- async checkFrozenFields(guard, id, existing, incoming) {
16866
+ async checkFrozenFields(guard, id, existing, incoming, skipFields) {
15932
16867
  const ff = guard.frozenFields;
15933
16868
  if (!ff) return;
15934
16869
  if (existing === null) return;
15935
16870
  if (!ff.when(existing)) return;
15936
16871
  const changed = [];
15937
16872
  for (const f of ff.fields) {
16873
+ if (skipFields?.has(String(f))) continue;
15938
16874
  if (existing[f] !== incoming[f]) {
15939
16875
  if (!deepEqual(existing[f], incoming[f])) changed.push(String(f));
15940
16876
  }
@@ -15963,6 +16899,476 @@ var init_executor3 = __esm({
15963
16899
  }
15964
16900
  });
15965
16901
 
16902
+ // src/federation/classify-skip.ts
16903
+ function classifyShardSkip(err) {
16904
+ return err instanceof NoAccessError ? "no-grant" : "error";
16905
+ }
16906
+ var init_classify_skip = __esm({
16907
+ "src/federation/classify-skip.ts"() {
16908
+ "use strict";
16909
+ init_errors();
16910
+ }
16911
+ });
16912
+
16913
+ // src/federation/cross-vault-live.ts
16914
+ var CrossVaultLive;
16915
+ var init_cross_vault_live = __esm({
16916
+ "src/federation/cross-vault-live.ts"() {
16917
+ "use strict";
16918
+ CrossVaultLive = class {
16919
+ snapshot;
16920
+ error = null;
16921
+ ready;
16922
+ subs = /* @__PURE__ */ new Set();
16923
+ unsubChange;
16924
+ opts;
16925
+ stopped = false;
16926
+ computing = false;
16927
+ dirty = false;
16928
+ scheduled = false;
16929
+ timer = null;
16930
+ resolveReady;
16931
+ settledOnce = false;
16932
+ constructor(opts) {
16933
+ this.opts = opts;
16934
+ this.snapshot = opts.initialSnapshot;
16935
+ this.ready = new Promise((res) => {
16936
+ this.resolveReady = res;
16937
+ });
16938
+ this.unsubChange = opts.subscribeToChanges((e) => {
16939
+ if (this.stopped || !opts.isRelevant(e)) return;
16940
+ this.schedule();
16941
+ });
16942
+ this.schedule();
16943
+ }
16944
+ subscribe(cb) {
16945
+ if (this.stopped) return () => {
16946
+ };
16947
+ this.subs.add(cb);
16948
+ return () => this.subs.delete(cb);
16949
+ }
16950
+ stop() {
16951
+ if (this.stopped) return;
16952
+ this.stopped = true;
16953
+ this.unsubChange();
16954
+ if (this.timer !== null) clearTimeout(this.timer);
16955
+ this.subs.clear();
16956
+ if (!this.settledOnce) this.resolveReady();
16957
+ }
16958
+ schedule() {
16959
+ if (this.stopped) return;
16960
+ if (this.computing) {
16961
+ this.dirty = true;
16962
+ return;
16963
+ }
16964
+ if (this.scheduled) return;
16965
+ this.scheduled = true;
16966
+ const run = () => {
16967
+ this.scheduled = false;
16968
+ void this.runCompute();
16969
+ };
16970
+ const ms = this.opts.debounceMs ?? 0;
16971
+ if (ms > 0) this.timer = setTimeout(run, ms);
16972
+ else queueMicrotask(run);
16973
+ }
16974
+ async runCompute() {
16975
+ if (this.stopped) return;
16976
+ this.computing = true;
16977
+ this.dirty = false;
16978
+ try {
16979
+ const next = await this.opts.compute();
16980
+ if (this.stopped) return;
16981
+ this.snapshot = next;
16982
+ this.error = null;
16983
+ } catch (err) {
16984
+ if (this.stopped) return;
16985
+ this.error = err instanceof Error ? err : new Error(String(err));
16986
+ } finally {
16987
+ this.computing = false;
16988
+ if (!this.stopped) {
16989
+ if (!this.settledOnce) {
16990
+ this.settledOnce = true;
16991
+ this.resolveReady();
16992
+ }
16993
+ for (const cb of this.subs) cb();
16994
+ if (this.dirty) this.schedule();
16995
+ }
16996
+ }
16997
+ }
16998
+ };
16999
+ }
17000
+ });
17001
+
17002
+ // src/federation/aggregate-across.ts
17003
+ var CrossVaultAggregation, CrossVaultGroupedAggregation;
17004
+ var init_aggregate_across = __esm({
17005
+ "src/federation/aggregate-across.ts"() {
17006
+ "use strict";
17007
+ init_aggregation();
17008
+ init_groupby();
17009
+ init_cross_vault_live();
17010
+ CrossVaultAggregation = class {
17011
+ constructor(src, spec, bind) {
17012
+ this.src = src;
17013
+ this.spec = spec;
17014
+ this.bind = bind;
17015
+ }
17016
+ src;
17017
+ spec;
17018
+ bind;
17019
+ async run(options = {}) {
17020
+ const { records, skippedVaults } = await this.src.fanoutRecords(options);
17021
+ return { result: reduceRecords(records, this.spec), skippedVaults };
17022
+ }
17023
+ live(options = {}) {
17024
+ if (!this.bind) throw new Error("CrossVaultAggregation: live() requires a LiveBinding \u2014 use ShardedQuery.aggregate()");
17025
+ const spec = this.spec;
17026
+ const src = this.src;
17027
+ const core = new CrossVaultLive({
17028
+ subscribeToChanges: this.bind.subscribeToChanges,
17029
+ isRelevant: this.bind.isRelevant,
17030
+ compute: async () => {
17031
+ const { records, skippedVaults } = await src.fanoutRecords(options);
17032
+ return { value: reduceRecords(records, spec), skipped: skippedVaults };
17033
+ },
17034
+ initialSnapshot: { value: void 0, skipped: [] },
17035
+ ...options.debounceMs !== void 0 ? { debounceMs: options.debounceMs } : {}
17036
+ });
17037
+ return {
17038
+ get value() {
17039
+ return core.snapshot.value;
17040
+ },
17041
+ get skippedVaults() {
17042
+ return core.snapshot.skipped;
17043
+ },
17044
+ get error() {
17045
+ return core.error;
17046
+ },
17047
+ ready: core.ready,
17048
+ subscribe: (cb) => core.subscribe(cb),
17049
+ stop: () => core.stop()
17050
+ };
17051
+ }
17052
+ };
17053
+ CrossVaultGroupedAggregation = class {
17054
+ constructor(src, field, spec, bind) {
17055
+ this.src = src;
17056
+ this.field = field;
17057
+ this.spec = spec;
17058
+ this.bind = bind;
17059
+ }
17060
+ src;
17061
+ field;
17062
+ spec;
17063
+ bind;
17064
+ async run(options = {}) {
17065
+ const { records, skippedVaults } = await this.src.fanoutRecords(options);
17066
+ return {
17067
+ results: groupAndReduce(records, this.field, this.spec),
17068
+ skippedVaults
17069
+ };
17070
+ }
17071
+ live(options = {}) {
17072
+ if (!this.bind) throw new Error("CrossVaultGroupedAggregation: live() requires a LiveBinding \u2014 use ShardedQuery.groupBy().aggregate()");
17073
+ const field = this.field;
17074
+ const spec = this.spec;
17075
+ const src = this.src;
17076
+ const core = new CrossVaultLive({
17077
+ subscribeToChanges: this.bind.subscribeToChanges,
17078
+ isRelevant: this.bind.isRelevant,
17079
+ compute: async () => {
17080
+ const { records, skippedVaults } = await src.fanoutRecords(options);
17081
+ return {
17082
+ records: groupAndReduce(records, field, spec),
17083
+ skipped: skippedVaults
17084
+ };
17085
+ },
17086
+ initialSnapshot: { records: [], skipped: [] },
17087
+ ...options.debounceMs !== void 0 ? { debounceMs: options.debounceMs } : {}
17088
+ });
17089
+ return {
17090
+ get value() {
17091
+ return core.snapshot.records;
17092
+ },
17093
+ get skippedVaults() {
17094
+ return core.snapshot.skipped;
17095
+ },
17096
+ get error() {
17097
+ return core.error;
17098
+ },
17099
+ ready: core.ready,
17100
+ subscribe: (cb) => core.subscribe(cb),
17101
+ stop: () => core.stop()
17102
+ };
17103
+ }
17104
+ };
17105
+ }
17106
+ });
17107
+
17108
+ // src/federation/vault-group.ts
17109
+ var vault_group_exports = {};
17110
+ __export(vault_group_exports, {
17111
+ ShardedCollection: () => ShardedCollection,
17112
+ ShardedGroupedQuery: () => ShardedGroupedQuery,
17113
+ ShardedQuery: () => ShardedQuery,
17114
+ VaultGroup: () => VaultGroup
17115
+ });
17116
+ function assertSafePartitionKey(partitionKey) {
17117
+ if (partitionKey.length === 0) {
17118
+ throw new ValidationError("partitionKey must be a non-empty string");
17119
+ }
17120
+ if (!SAFE_PARTITION_KEY.test(partitionKey)) {
17121
+ throw new ValidationError(
17122
+ `partitionKey "${partitionKey}" contains characters outside [A-Za-z0-9._-]. Map your records to a store-safe key in sharding.keyOf.`
17123
+ );
17124
+ }
17125
+ if (partitionKey.includes(SHARD_SEPARATOR)) {
17126
+ throw new ValidationError(
17127
+ `partitionKey "${partitionKey}" must not contain "--" \u2014 it is reserved as the shard vault-id separator and would risk shard-id collisions.`
17128
+ );
17129
+ }
17130
+ }
17131
+ var SHARD_SEPARATOR, SAFE_PARTITION_KEY, VaultGroup, ShardedCollection, ShardedQuery, ShardedGroupedQuery;
17132
+ var init_vault_group = __esm({
17133
+ "src/federation/vault-group.ts"() {
17134
+ "use strict";
17135
+ init_errors();
17136
+ init_classify_skip();
17137
+ init_cross_vault_live();
17138
+ init_aggregate_across();
17139
+ SHARD_SEPARATOR = "--";
17140
+ SAFE_PARTITION_KEY = /^[A-Za-z0-9._-]+$/;
17141
+ VaultGroup = class {
17142
+ constructor(db, name, registry, sharding, template) {
17143
+ this.db = db;
17144
+ this.name = name;
17145
+ this.registry = registry;
17146
+ this.sharding = sharding;
17147
+ this.template = template;
17148
+ if (name.includes(SHARD_SEPARATOR)) {
17149
+ throw new ValidationError(
17150
+ `VaultGroup name "${name}" must not contain "--" (reserved shard vault-id separator).`
17151
+ );
17152
+ }
17153
+ }
17154
+ db;
17155
+ name;
17156
+ registry;
17157
+ sharding;
17158
+ template;
17159
+ /** Deterministic vault name for a partition key, namespaced by the group. */
17160
+ shardVaultId(partitionKey) {
17161
+ assertSafePartitionKey(partitionKey);
17162
+ return `${this.name}${SHARD_SEPARATOR}${partitionKey}`;
17163
+ }
17164
+ /** All registry rows (hydrates the registry collection first). */
17165
+ async allRows() {
17166
+ await this.registry.list();
17167
+ return this.registry.query().toArray();
17168
+ }
17169
+ /** Open an existing shard and apply the template. */
17170
+ async openShard(partitionKey) {
17171
+ const vault = await this.db.openVault(this.shardVaultId(partitionKey), { create: false });
17172
+ this.template.configure(vault);
17173
+ return vault;
17174
+ }
17175
+ /**
17176
+ * Idempotently provision a shard for `partitionKey`. Returns the
17177
+ * configured vault handle.
17178
+ *
17179
+ * - row + vault present → no-op, return handle
17180
+ * - row present, vault gone → ShardProvisioningError
17181
+ * - row absent (vault present or not) → open-or-create, configure, write row
17182
+ */
17183
+ async createShard(partitionKey) {
17184
+ const vaultId = this.shardVaultId(partitionKey);
17185
+ const row = await this.registry.get(partitionKey);
17186
+ const provisioned = await this.db._shardVaultProvisioned(vaultId);
17187
+ if (row && !provisioned) throw new ShardProvisioningError(vaultId, partitionKey);
17188
+ if (row && provisioned) return this.openShard(partitionKey);
17189
+ const vault = await this.db.openVault(vaultId);
17190
+ this.template.configure(vault);
17191
+ await this.registry.put(partitionKey, {
17192
+ vaultId,
17193
+ partitionKey,
17194
+ templateName: this.sharding.vaultTemplate,
17195
+ schemaVersion: this.template.version,
17196
+ createdAt: Date.now()
17197
+ });
17198
+ return vault;
17199
+ }
17200
+ /**
17201
+ * Drill down to a single shard's full Collection API. Throws if the shard is unknown.
17202
+ * Also throws ShardProvisioningError if the registry row exists but the vault has been deleted
17203
+ * (registry/store divergence).
17204
+ */
17205
+ async shard(partitionKey) {
17206
+ const vaultId = this.shardVaultId(partitionKey);
17207
+ const row = await this.registry.get(partitionKey);
17208
+ if (!row) throw new UnknownShardError(partitionKey, this.name);
17209
+ const provisioned = await this.db._shardVaultProvisioned(vaultId);
17210
+ if (!provisioned) throw new ShardProvisioningError(vaultId, partitionKey);
17211
+ return this.openShard(partitionKey);
17212
+ }
17213
+ /** A sharded view over one logical collection across all shards. */
17214
+ collection(collectionName) {
17215
+ return new ShardedCollection(this, collectionName);
17216
+ }
17217
+ /** @internal — eligible (openable-candidate) rows + drift/divergence skips. */
17218
+ async resolveEligible(options = {}) {
17219
+ const rows = await this.allRows();
17220
+ const skipped = [];
17221
+ const versionOk = [];
17222
+ for (const row of rows) {
17223
+ if (options.minVersion !== void 0 && row.schemaVersion < options.minVersion) {
17224
+ skipped.push({ vaultId: row.vaultId, reason: "schema-drift" });
17225
+ } else versionOk.push(row);
17226
+ }
17227
+ const provisioned = await Promise.all(versionOk.map((r) => this.db._shardVaultProvisioned(r.vaultId)));
17228
+ const eligible = [];
17229
+ versionOk.forEach((row, i) => {
17230
+ if (provisioned[i]) eligible.push(row);
17231
+ else skipped.push({ vaultId: row.vaultId, reason: "error", error: new ShardProvisioningError(row.vaultId, row.partitionKey) });
17232
+ });
17233
+ return { eligible, skipped };
17234
+ }
17235
+ };
17236
+ ShardedCollection = class {
17237
+ constructor(group, collectionName) {
17238
+ this.group = group;
17239
+ this.collectionName = collectionName;
17240
+ }
17241
+ group;
17242
+ collectionName;
17243
+ /** Route a write to the shard owning `keyOf(record)`. */
17244
+ async put(id, record) {
17245
+ const key = this.group.sharding.keyOf(record);
17246
+ const row = await this.group.registry.get(key);
17247
+ let vault;
17248
+ if (!row) {
17249
+ if (this.group.sharding.autoCreate === false) {
17250
+ throw new UnknownShardError(key, this.group.name);
17251
+ }
17252
+ vault = await this.group.createShard(key);
17253
+ } else {
17254
+ vault = await this.group.openShard(key);
17255
+ }
17256
+ await vault.collection(this.collectionName).put(id, record);
17257
+ }
17258
+ /** Begin a cross-shard fan-out query. */
17259
+ query() {
17260
+ return new ShardedQuery(this.group, this.collectionName, []);
17261
+ }
17262
+ };
17263
+ ShardedQuery = class _ShardedQuery {
17264
+ constructor(group, collectionName, clauses) {
17265
+ this.group = group;
17266
+ this.collectionName = collectionName;
17267
+ this.clauses = clauses;
17268
+ }
17269
+ group;
17270
+ collectionName;
17271
+ clauses;
17272
+ where(field, op, value) {
17273
+ return new _ShardedQuery(this.group, this.collectionName, [
17274
+ ...this.clauses,
17275
+ { field, op, value }
17276
+ ]);
17277
+ }
17278
+ /** @internal — fan out the where-filtered records across eligible shards. */
17279
+ async fanoutRecords(options = {}) {
17280
+ const { eligible, skipped } = await this.group.resolveEligible(options);
17281
+ const across = await this.group.db.queryAcross(
17282
+ eligible.map((r) => r.vaultId),
17283
+ async (vault) => {
17284
+ this.group.template.configure(vault);
17285
+ const coll = vault.collection(this.collectionName);
17286
+ await coll.list();
17287
+ let q = coll.query();
17288
+ for (const c of this.clauses) q = q.where(c.field, c.op, c.value);
17289
+ return q.toArray();
17290
+ },
17291
+ { concurrency: options.concurrency ?? 1, create: false }
17292
+ );
17293
+ const results = [];
17294
+ for (const r of across) {
17295
+ if (r.error) skipped.push({ vaultId: r.vault, reason: classifyShardSkip(r.error), error: r.error });
17296
+ else for (const item of r.result) results.push(item);
17297
+ }
17298
+ return { records: results, skippedVaults: skipped };
17299
+ }
17300
+ /** Fan out across eligible shards and merge results. */
17301
+ async toArray(options = {}) {
17302
+ const { records, skippedVaults } = await this.fanoutRecords(options);
17303
+ return { results: records, skippedVaults };
17304
+ }
17305
+ /** @internal — build the change-subscription + relevance binding for this query's group+collection. */
17306
+ liveBinding() {
17307
+ const group = this.group;
17308
+ const collectionName = this.collectionName;
17309
+ return {
17310
+ subscribeToChanges: (h) => {
17311
+ group.db.on("change", h);
17312
+ return () => group.db.off("change", h);
17313
+ },
17314
+ isRelevant: (e) => e.collection === collectionName && e.vault.startsWith(`${group.name}--`)
17315
+ };
17316
+ }
17317
+ /** Returns a reactive cross-shard live query — a facade over CrossVaultLive. */
17318
+ live(options = {}) {
17319
+ const bind = this.liveBinding();
17320
+ const core = new CrossVaultLive({
17321
+ ...bind,
17322
+ compute: async () => {
17323
+ const { records, skippedVaults } = await this.fanoutRecords(options);
17324
+ return { records, skipped: skippedVaults };
17325
+ },
17326
+ initialSnapshot: { records: [], skipped: [] },
17327
+ ...options.debounceMs !== void 0 ? { debounceMs: options.debounceMs } : {}
17328
+ });
17329
+ return {
17330
+ get value() {
17331
+ return core.snapshot.records;
17332
+ },
17333
+ get skippedVaults() {
17334
+ return core.snapshot.skipped;
17335
+ },
17336
+ get error() {
17337
+ return core.error;
17338
+ },
17339
+ ready: core.ready,
17340
+ subscribe: (cb) => core.subscribe(cb),
17341
+ stop: () => core.stop()
17342
+ };
17343
+ }
17344
+ /** One-shot distributed aggregate — central reduce over all shard records. */
17345
+ aggregate(spec) {
17346
+ return new CrossVaultAggregation(this, spec, this.liveBinding());
17347
+ }
17348
+ /** Begin a grouped cross-shard aggregate. */
17349
+ groupBy(field) {
17350
+ return new ShardedGroupedQuery(this, field);
17351
+ }
17352
+ };
17353
+ ShardedGroupedQuery = class {
17354
+ constructor(query, field) {
17355
+ this.query = query;
17356
+ this.field = field;
17357
+ }
17358
+ query;
17359
+ field;
17360
+ aggregate(spec) {
17361
+ return new CrossVaultGroupedAggregation(
17362
+ { fanoutRecords: (o) => this.query.fanoutRecords(o) },
17363
+ this.field,
17364
+ spec,
17365
+ this.query.liveBinding()
17366
+ );
17367
+ }
17368
+ };
17369
+ }
17370
+ });
17371
+
15966
17372
  // src/noydb.ts
15967
17373
  var noydb_exports = {};
15968
17374
  __export(noydb_exports, {
@@ -16101,6 +17507,7 @@ var init_noydb = __esm({
16101
17507
  writeRelay;
16102
17508
  /** Per-vault policy enforcers. */
16103
17509
  policyEnforcers = /* @__PURE__ */ new Map();
17510
+ vaultTemplates = /* @__PURE__ */ new Map();
16104
17511
  txStrategy;
16105
17512
  sessionStrategy;
16106
17513
  syncStrategy;
@@ -16170,7 +17577,7 @@ var init_noydb = __esm({
16170
17577
  await registry.runChecks(e.collection, incoming, ctx);
16171
17578
  const { GuardExecutor: GuardExecutor2 } = await Promise.resolve().then(() => (init_executor3(), executor_exports3));
16172
17579
  for (const g of guards) {
16173
- await GuardExecutor2.checkFrozenFields(g, e.docId, existing, incoming);
17580
+ await GuardExecutor2.checkFrozenFields(g, e.docId, existing, incoming, e.computedFieldNames);
16174
17581
  }
16175
17582
  });
16176
17583
  this.subsystemBus.registerGate("beforeDelete", async (e) => {
@@ -16349,6 +17756,7 @@ var init_noydb = __esm({
16349
17756
  syncAdapter: targets.length > 0 ? targets[0].store : void 0,
16350
17757
  historyConfig: this.options.history,
16351
17758
  ...this.options.blobStrategy !== void 0 ? { blobStrategy: this.options.blobStrategy } : {},
17759
+ ...this.options.archiveStrategy !== void 0 ? { archiveStrategy: this.options.archiveStrategy } : {},
16352
17760
  ...this.options.indexStrategy !== void 0 ? { indexStrategy: this.options.indexStrategy } : {},
16353
17761
  ...this.options.aggregateStrategy !== void 0 ? { aggregateStrategy: this.options.aggregateStrategy } : {},
16354
17762
  ...this.options.crdtStrategy !== void 0 ? { crdtStrategy: this.options.crdtStrategy } : {},
@@ -16402,6 +17810,7 @@ var init_noydb = __esm({
16402
17810
  emitter: this.emitter,
16403
17811
  historyConfig: this.options.history,
16404
17812
  ...this.options.blobStrategy !== void 0 ? { blobStrategy: this.options.blobStrategy } : {},
17813
+ ...this.options.archiveStrategy !== void 0 ? { archiveStrategy: this.options.archiveStrategy } : {},
16405
17814
  ...this.options.indexStrategy !== void 0 ? { indexStrategy: this.options.indexStrategy } : {},
16406
17815
  ...this.options.aggregateStrategy !== void 0 ? { aggregateStrategy: this.options.aggregateStrategy } : {},
16407
17816
  ...this.options.crdtStrategy !== void 0 ? { crdtStrategy: this.options.crdtStrategy } : {},
@@ -16430,6 +17839,7 @@ var init_noydb = __esm({
16430
17839
  encrypted: true,
16431
17840
  historyConfig: this.options.history,
16432
17841
  ...this.options.blobStrategy !== void 0 ? { blobStrategy: this.options.blobStrategy } : {},
17842
+ ...this.options.archiveStrategy !== void 0 ? { archiveStrategy: this.options.archiveStrategy } : {},
16433
17843
  ...this.options.indexStrategy !== void 0 ? { indexStrategy: this.options.indexStrategy } : {},
16434
17844
  ...this.options.aggregateStrategy !== void 0 ? { aggregateStrategy: this.options.aggregateStrategy } : {},
16435
17845
  ...this.options.crdtStrategy !== void 0 ? { crdtStrategy: this.options.crdtStrategy } : {},
@@ -16744,6 +18154,32 @@ var init_noydb = __esm({
16744
18154
  }
16745
18155
  return results;
16746
18156
  }
18157
+ /**
18158
+ * Register a shard schema blueprint. `createShard` / `openVaultGroup`
18159
+ * stamp shards from the named template. See the MVF design spec.
18160
+ */
18161
+ withVaultTemplate(name, template) {
18162
+ this.vaultTemplates.set(name, template);
18163
+ }
18164
+ /**
18165
+ * Open a VaultGroup — transparent routing over per-partition shard
18166
+ * vaults, with shard discovery backed by the supplied `vault-registry`
18167
+ * collection.
18168
+ */
18169
+ async openVaultGroup(name, opts) {
18170
+ if (this.closed) throw new ValidationError("Instance is closed");
18171
+ const template = this.vaultTemplates.get(opts.sharding.vaultTemplate);
18172
+ if (!template) throw new VaultTemplateNotFoundError(opts.sharding.vaultTemplate);
18173
+ const { VaultGroup: VaultGroup2 } = await Promise.resolve().then(() => (init_vault_group(), vault_group_exports));
18174
+ return new VaultGroup2(this, name, opts.registry, opts.sharding, template);
18175
+ }
18176
+ /**
18177
+ * @internal — true when an encrypted shard vault is provisioned
18178
+ * (its keyring exists in the store).
18179
+ */
18180
+ async _shardVaultProvisioned(vaultId) {
18181
+ return (await this.options.store.list(vaultId, "_keyring")).length > 0;
18182
+ }
16747
18183
  /**
16748
18184
  * Change the current user's passphrase for a vault.
16749
18185
  *