@noy-db/hub 0.2.0-pre.9 → 0.3.0-pre.1

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 (541) hide show
  1. package/README.md +129 -3
  2. package/dist/adapter/index.d.ts +5 -0
  3. package/dist/adapter/index.js +15 -0
  4. package/dist/aggregate/index.d.ts +6 -2
  5. package/dist/aggregate/index.js +24 -16
  6. package/dist/aggregate/index.js.map +1 -1
  7. package/dist/api-RW3KP7WU.js +14 -0
  8. package/dist/as/index.d.ts +7 -0
  9. package/dist/as/index.js +24 -0
  10. package/dist/at/index.d.ts +5 -0
  11. package/dist/at/index.js +1 -0
  12. package/dist/attestation/index.d.ts +15 -47
  13. package/dist/attestation/index.js +54 -10
  14. package/dist/attestation/index.js.map +1 -1
  15. package/dist/backup-XV3IOEGB.js +217 -0
  16. package/dist/backup-XV3IOEGB.js.map +1 -0
  17. package/dist/blobs/index.d.ts +6 -8
  18. package/dist/blobs/index.js +19 -12
  19. package/dist/blobs/index.js.map +1 -1
  20. package/dist/bundle/index.d.ts +16 -70
  21. package/dist/bundle/index.js +39 -476
  22. package/dist/bundle/index.js.map +1 -1
  23. package/dist/{ulid-CJ8RzRrm.d.ts → bundle-CH-H06dp.d.ts} +31 -86
  24. package/dist/by/index.d.ts +1 -0
  25. package/dist/by/index.js +11 -0
  26. package/dist/cargo/index.d.ts +9 -0
  27. package/dist/cargo/index.js +89 -0
  28. package/dist/chunk-26LGBE4T.js +42 -0
  29. package/dist/chunk-26LGBE4T.js.map +1 -0
  30. package/dist/chunk-2P2HZEXU.js +233 -0
  31. package/dist/chunk-2P2HZEXU.js.map +1 -0
  32. package/dist/{chunk-K3DK3NU5.js → chunk-3YFXJ3ZP.js} +20 -5
  33. package/dist/chunk-3YFXJ3ZP.js.map +1 -0
  34. package/dist/chunk-4Q6HSHHL.js +90 -0
  35. package/dist/chunk-4Q6HSHHL.js.map +1 -0
  36. package/dist/chunk-5LUY7UTV.js +380 -0
  37. package/dist/chunk-5LUY7UTV.js.map +1 -0
  38. package/dist/chunk-5N6CZTCY.js +367 -0
  39. package/dist/chunk-5N6CZTCY.js.map +1 -0
  40. package/dist/chunk-5O3AOPDT.js +992 -0
  41. package/dist/chunk-5O3AOPDT.js.map +1 -0
  42. package/dist/chunk-5R3ERCDH.js +239 -0
  43. package/dist/chunk-5R3ERCDH.js.map +1 -0
  44. package/dist/{chunk-6CME4UEK.js → chunk-5R5JW2JT.js} +7000 -4827
  45. package/dist/chunk-5R5JW2JT.js.map +1 -0
  46. package/dist/chunk-5TDJ56JE.js +32 -0
  47. package/dist/chunk-5TDJ56JE.js.map +1 -0
  48. package/dist/{chunk-T7JEBOGN.js → chunk-62QYRORB.js} +18 -11
  49. package/dist/chunk-62QYRORB.js.map +1 -0
  50. package/dist/{chunk-J66GRPNH.js → chunk-6S7T6WC4.js} +2 -2
  51. package/dist/chunk-6S7T6WC4.js.map +1 -0
  52. package/dist/chunk-76722EBH.js +451 -0
  53. package/dist/chunk-76722EBH.js.map +1 -0
  54. package/dist/{chunk-Z6FNBOTC.js → chunk-AIWULCUO.js} +13 -17
  55. package/dist/chunk-AIWULCUO.js.map +1 -0
  56. package/dist/{chunk-O3VZPBZG.js → chunk-AQTBSL7R.js} +47 -11
  57. package/dist/chunk-AQTBSL7R.js.map +1 -0
  58. package/dist/chunk-AURFOK3D.js +35 -0
  59. package/dist/chunk-AURFOK3D.js.map +1 -0
  60. package/dist/{chunk-53XBRIRT.js → chunk-AXRXJTE2.js} +9 -9
  61. package/dist/chunk-AXRXJTE2.js.map +1 -0
  62. package/dist/chunk-AZAOEIKW.js +155 -0
  63. package/dist/chunk-AZAOEIKW.js.map +1 -0
  64. package/dist/{chunk-HNRHLRDC.js → chunk-BG3SPSR4.js} +3 -3
  65. package/dist/chunk-BG3SPSR4.js.map +1 -0
  66. package/dist/chunk-BGIZAFY7.js +1 -0
  67. package/dist/chunk-CHFZDSE4.js +1 -0
  68. package/dist/{chunk-DJHHA6XH.js → chunk-CMGR4ZEW.js} +50 -20
  69. package/dist/chunk-CMGR4ZEW.js.map +1 -0
  70. package/dist/chunk-CWPPNPOH.js +23 -0
  71. package/dist/chunk-CWPPNPOH.js.map +1 -0
  72. package/dist/{chunk-QODLLGQ7.js → chunk-DFEMTNPJ.js} +371 -38
  73. package/dist/chunk-DFEMTNPJ.js.map +1 -0
  74. package/dist/{chunk-ZYWZWG6G.js → chunk-DGDI2D4M.js} +10 -10
  75. package/dist/chunk-DGDI2D4M.js.map +1 -0
  76. package/dist/{chunk-SYMWGEET.js → chunk-EIZUR2XW.js} +3 -3
  77. package/dist/chunk-EIZUR2XW.js.map +1 -0
  78. package/dist/{chunk-BVRYKATC.js → chunk-FISN7WE4.js} +36 -33
  79. package/dist/chunk-FISN7WE4.js.map +1 -0
  80. package/dist/chunk-GHVIKOHT.js +1 -0
  81. package/dist/chunk-GYGWYIOZ.js +200 -0
  82. package/dist/chunk-GYGWYIOZ.js.map +1 -0
  83. package/dist/chunk-HCIPRAGS.js +45 -0
  84. package/dist/chunk-HCIPRAGS.js.map +1 -0
  85. package/dist/{chunk-PX35GA7L.js → chunk-I2NOIW44.js} +10 -10
  86. package/dist/chunk-I2NOIW44.js.map +1 -0
  87. package/dist/{chunk-OIF6LZUR.js → chunk-I3TIKTJO.js} +3 -3
  88. package/dist/chunk-I3TIKTJO.js.map +1 -0
  89. package/dist/chunk-I7FD46FF.js +9 -0
  90. package/dist/chunk-I7FD46FF.js.map +1 -0
  91. package/dist/chunk-IAGBDSCS.js +40 -0
  92. package/dist/chunk-IAGBDSCS.js.map +1 -0
  93. package/dist/{chunk-JWRVQKRZ.js → chunk-IELYAOGG.js} +6 -18
  94. package/dist/chunk-IELYAOGG.js.map +1 -0
  95. package/dist/chunk-IGUYVGGI.js +205 -0
  96. package/dist/chunk-IGUYVGGI.js.map +1 -0
  97. package/dist/{chunk-U26HQ6KJ.js → chunk-IO6GRPT6.js} +4 -4
  98. package/dist/chunk-IO6GRPT6.js.map +1 -0
  99. package/dist/chunk-IPB7FTQX.js +273 -0
  100. package/dist/chunk-IPB7FTQX.js.map +1 -0
  101. package/dist/chunk-ITNUCOXM.js +148 -0
  102. package/dist/chunk-ITNUCOXM.js.map +1 -0
  103. package/dist/{chunk-WPLVTJ5D.js → chunk-IUEN57TV.js} +10 -10
  104. package/dist/chunk-IUEN57TV.js.map +1 -0
  105. package/dist/{chunk-DL3HWOQ5.js → chunk-JNUWZ6D3.js} +9 -9
  106. package/dist/chunk-JNUWZ6D3.js.map +1 -0
  107. package/dist/chunk-K2WCO3NX.js +1 -0
  108. package/dist/chunk-KVOXU4T5.js +30 -0
  109. package/dist/chunk-KVOXU4T5.js.map +1 -0
  110. package/dist/chunk-KXGNJJXB.js +135 -0
  111. package/dist/chunk-KXGNJJXB.js.map +1 -0
  112. package/dist/chunk-LB7FD65R.js +163 -0
  113. package/dist/chunk-LB7FD65R.js.map +1 -0
  114. package/dist/{chunk-22DWZL57.js → chunk-LFLXAY2W.js} +43 -218
  115. package/dist/chunk-LFLXAY2W.js.map +1 -0
  116. package/dist/chunk-LMTH2RM6.js +129 -0
  117. package/dist/chunk-LMTH2RM6.js.map +1 -0
  118. package/dist/{aggregate/index.cjs → chunk-LV7M27WM.js} +390 -219
  119. package/dist/chunk-LV7M27WM.js.map +1 -0
  120. package/dist/{chunk-PE2FR4J3.js → chunk-LXQT4WMP.js} +16 -18
  121. package/dist/chunk-LXQT4WMP.js.map +1 -0
  122. package/dist/chunk-M2YKN37S.js +524 -0
  123. package/dist/chunk-M2YKN37S.js.map +1 -0
  124. package/dist/chunk-M6OST55S.js +14 -0
  125. package/dist/chunk-M6OST55S.js.map +1 -0
  126. package/dist/{chunk-F3GDRNUT.js → chunk-MD3Y6J3L.js} +35 -69
  127. package/dist/chunk-MD3Y6J3L.js.map +1 -0
  128. package/dist/{chunk-XJFLDA7A.js → chunk-MTMJVJ5W.js} +8 -7
  129. package/dist/chunk-MTMJVJ5W.js.map +1 -0
  130. package/dist/{chunk-DFMLEQZB.js → chunk-NF5JWERG.js} +5 -10
  131. package/dist/chunk-NF5JWERG.js.map +1 -0
  132. package/dist/{chunk-DO7C2TOG.js → chunk-PKHL44ER.js} +3 -3
  133. package/dist/{chunk-DO7C2TOG.js.map → chunk-PKHL44ER.js.map} +1 -1
  134. package/dist/chunk-PSMV73A5.js +117 -0
  135. package/dist/chunk-PSMV73A5.js.map +1 -0
  136. package/dist/chunk-PY4KJPYU.js +9 -0
  137. package/dist/chunk-PY4KJPYU.js.map +1 -0
  138. package/dist/chunk-PZ5AY32C.js +10 -0
  139. package/dist/{chunk-DE6GKS6G.js → chunk-Q7SS3IME.js} +50 -9
  140. package/dist/chunk-Q7SS3IME.js.map +1 -0
  141. package/dist/chunk-QHJW5EXU.js +54 -0
  142. package/dist/chunk-QHJW5EXU.js.map +1 -0
  143. package/dist/{chunk-NONAAENK.js → chunk-RUEKROOS.js} +11 -4
  144. package/dist/chunk-RUEKROOS.js.map +1 -0
  145. package/dist/chunk-RUIMKQTA.js +23 -0
  146. package/dist/chunk-RUIMKQTA.js.map +1 -0
  147. package/dist/{chunk-TFBP23BX.js → chunk-SKF73JOP.js} +66 -7
  148. package/dist/chunk-SKF73JOP.js.map +1 -0
  149. package/dist/chunk-SM3AVUHC.js +42 -0
  150. package/dist/chunk-SM3AVUHC.js.map +1 -0
  151. package/dist/{chunk-ML236QKC.js → chunk-SMXWYP24.js} +5 -5
  152. package/dist/chunk-SMXWYP24.js.map +1 -0
  153. package/dist/chunk-SRB2XEWB.js +148 -0
  154. package/dist/chunk-SRB2XEWB.js.map +1 -0
  155. package/dist/chunk-SVLR4POP.js +64 -0
  156. package/dist/chunk-SVLR4POP.js.map +1 -0
  157. package/dist/chunk-TA66UMI4.js +123 -0
  158. package/dist/chunk-TA66UMI4.js.map +1 -0
  159. package/dist/chunk-TEILUWOI.js +664 -0
  160. package/dist/chunk-TEILUWOI.js.map +1 -0
  161. package/dist/chunk-TJYQIGAP.js +82 -0
  162. package/dist/chunk-TJYQIGAP.js.map +1 -0
  163. package/dist/{chunk-H2X3ISXG.js → chunk-UAG5KWVA.js} +7 -7
  164. package/dist/chunk-UAG5KWVA.js.map +1 -0
  165. package/dist/chunk-UDRIWL7A.js +382 -0
  166. package/dist/chunk-UDRIWL7A.js.map +1 -0
  167. package/dist/{chunk-2GLDA55J.js → chunk-UIU2THRG.js} +498 -133
  168. package/dist/chunk-UIU2THRG.js.map +1 -0
  169. package/dist/{chunk-3YPCK6JX.js → chunk-UPJNJGGA.js} +165 -423
  170. package/dist/chunk-UPJNJGGA.js.map +1 -0
  171. package/dist/chunk-UV5MFVO3.js +21 -0
  172. package/dist/chunk-UV5MFVO3.js.map +1 -0
  173. package/dist/{chunk-2WUSG3IT.js → chunk-V7RWQRG7.js} +5 -5
  174. package/dist/chunk-V7RWQRG7.js.map +1 -0
  175. package/dist/{chunk-VTKGMEPP.js → chunk-VCTFO5CO.js} +13 -3
  176. package/dist/chunk-VCTFO5CO.js.map +1 -0
  177. package/dist/{chunk-5T22KDPN.js → chunk-VFQGRQIH.js} +8 -8
  178. package/dist/chunk-VFQGRQIH.js.map +1 -0
  179. package/dist/{chunk-2QR2PQTT.js → chunk-VQNJ7UZL.js} +5 -3
  180. package/dist/chunk-VQNJ7UZL.js.map +1 -0
  181. package/dist/{chunk-DONMZAD2.js → chunk-WWGT2MDV.js} +43 -165
  182. package/dist/chunk-WWGT2MDV.js.map +1 -0
  183. package/dist/{chunk-EMIGCR7X.js → chunk-WXSYDNBT.js} +2 -2
  184. package/dist/chunk-WXSYDNBT.js.map +1 -0
  185. package/dist/chunk-WYSO2NIH.js +30 -0
  186. package/dist/chunk-WYSO2NIH.js.map +1 -0
  187. package/dist/chunk-XXYIOFUB.js +164 -0
  188. package/dist/chunk-XXYIOFUB.js.map +1 -0
  189. package/dist/{chunk-3BFJOWSU.js → chunk-Y22T3KQE.js} +35 -7
  190. package/dist/chunk-Y22T3KQE.js.map +1 -0
  191. package/dist/{chunk-A3JMGXPG.js → chunk-YMUGBZN2.js} +2 -2
  192. package/dist/chunk-YMUGBZN2.js.map +1 -0
  193. package/dist/{chunk-I5FOWO4J.js → chunk-ZCGAHGUS.js} +52 -73
  194. package/dist/chunk-ZCGAHGUS.js.map +1 -0
  195. package/dist/{chunk-FZU343FL.js → chunk-ZJADGNYF.js} +2 -2
  196. package/dist/chunk-ZJADGNYF.js.map +1 -0
  197. package/dist/{chunk-B6PB7JLN.js → chunk-ZYUC53LT.js} +427 -6
  198. package/dist/chunk-ZYUC53LT.js.map +1 -0
  199. package/dist/collection-facade-GQAOGJP2.js +33 -0
  200. package/dist/consent/index.d.ts +5 -7
  201. package/dist/consent/index.js +7 -5
  202. package/dist/consent/index.js.map +1 -1
  203. package/dist/crdt/index.d.ts +6 -2
  204. package/dist/crdt/index.js +3 -2
  205. package/dist/crdt/index.js.map +1 -1
  206. package/dist/decrypt-partition-IHtxEnTi.d.ts +21 -0
  207. package/dist/delegation-UL5HKLER.js +19 -0
  208. package/dist/derivations/index.d.ts +7 -9
  209. package/dist/derivations/index.js +11 -6
  210. package/dist/describe/index.d.ts +1 -0
  211. package/dist/describe/index.js +1 -0
  212. package/dist/describe-aBkJR2sd.d.ts +131 -0
  213. package/dist/{dev-unlock-B4kDxep_.d.ts → dev-unlock-C9Ro3v_O.d.ts} +1 -1
  214. package/dist/discriminant-BN9REW3o.d.ts +60 -0
  215. package/dist/enclave-UL5LW66V.js +88 -0
  216. package/dist/executor-2FWQRLMG.js +15 -0
  217. package/dist/executor-QZ7BXICW.js +9 -0
  218. package/dist/executor-Z5ZLJVTV.js +9 -0
  219. package/dist/export-accessible-KRV5W4GH.js +17 -0
  220. package/dist/extract-partition-GLKBOXFQ.js +30 -0
  221. package/dist/{fanout-sidecar-OKPMMPLG.js → fanout-sidecar-GF3DJ6KR.js} +34 -14
  222. package/dist/fanout-sidecar-GF3DJ6KR.js.map +1 -0
  223. package/dist/forget/index.d.ts +36 -0
  224. package/dist/forget/index.js +19 -0
  225. package/dist/forget/index.js.map +1 -0
  226. package/dist/guards/index.d.ts +13 -9
  227. package/dist/guards/index.js +12 -5
  228. package/dist/{hash-DdpVypUp.d.cts → hash-Cp5uwiox.d.ts} +5 -1
  229. package/dist/history/index.d.ts +6 -8
  230. package/dist/history/index.js +19 -12
  231. package/dist/history/index.js.map +1 -1
  232. package/dist/i18n/index.d.ts +5 -7
  233. package/dist/i18n/index.js +104 -15
  234. package/dist/i18n/index.js.map +1 -1
  235. package/dist/in/index.d.ts +5 -0
  236. package/dist/in/index.js +1 -0
  237. package/dist/in/index.js.map +1 -0
  238. package/dist/index-B9QdHytu.d.ts +123 -0
  239. package/dist/index-BF9_96A5.d.ts +123 -0
  240. package/dist/{types-Df28QFKb.d.ts → index-BzUo1B6n.d.ts} +16270 -8358
  241. package/dist/index.d.ts +1088 -450
  242. package/dist/index.js +1165 -293
  243. package/dist/index.js.map +1 -1
  244. package/dist/indexing/index.d.ts +6 -3
  245. package/dist/indexing/index.js +6 -5
  246. package/dist/indexing/index.js.map +1 -1
  247. package/dist/issue-Y6UVIR43.js +13 -0
  248. package/dist/issue-Y6UVIR43.js.map +1 -0
  249. package/dist/kernel/index.d.ts +32 -0
  250. package/dist/kernel/index.js +53 -0
  251. package/dist/kernel/index.js.map +1 -0
  252. package/dist/{ledger-TMRZYNVJ.js → ledger-RYI35CDS.js} +12 -9
  253. package/dist/ledger-RYI35CDS.js.map +1 -0
  254. package/dist/liberate-CRPZEV7O.js +18 -0
  255. package/dist/liberate-CRPZEV7O.js.map +1 -0
  256. package/dist/materialized-views/index.d.ts +6 -19
  257. package/dist/materialized-views/index.js +16 -12
  258. package/dist/mime-magic-CGhw37_E.d.ts +103 -0
  259. package/dist/noydb-367AM4HT.js +50 -0
  260. package/dist/noydb-367AM4HT.js.map +1 -0
  261. package/dist/on/index.d.ts +5 -0
  262. package/dist/on/index.js +11 -0
  263. package/dist/on/index.js.map +1 -0
  264. package/dist/overlay-views/index.d.ts +27 -11
  265. package/dist/overlay-views/index.js +7 -6
  266. package/dist/periods/index.d.ts +5 -7
  267. package/dist/periods/index.js +13 -9
  268. package/dist/pod/index.d.ts +63 -0
  269. package/dist/pod/index.js +61 -0
  270. package/dist/pod/index.js.map +1 -0
  271. package/dist/policy-IXK4FVXP.js +41 -0
  272. package/dist/policy-IXK4FVXP.js.map +1 -0
  273. package/dist/portability/index.d.ts +20 -0
  274. package/dist/portability/index.js +43 -0
  275. package/dist/portability/index.js.map +1 -0
  276. package/dist/{public-envelope-BW6OXORV.js → public-envelope-JHDQCPSX.js} +6 -5
  277. package/dist/public-envelope-JHDQCPSX.js.map +1 -0
  278. package/dist/query/index.d.ts +5 -3
  279. package/dist/query/index.js +21 -13
  280. package/dist/read-only-facade-5ADRJVTM.js +8 -0
  281. package/dist/read-only-facade-5ADRJVTM.js.map +1 -0
  282. package/dist/registry-45RJNWGU.js +9 -0
  283. package/dist/registry-45RJNWGU.js.map +1 -0
  284. package/dist/registry-5GRV5VXI.js +13 -0
  285. package/dist/registry-5GRV5VXI.js.map +1 -0
  286. package/dist/registry-VW6P6A3J.js +8 -0
  287. package/dist/registry-VW6P6A3J.js.map +1 -0
  288. package/dist/registry-WEUCHBO4.js +11 -0
  289. package/dist/registry-WEUCHBO4.js.map +1 -0
  290. package/dist/request-withdrawal-GBPH2FDY.js +25 -0
  291. package/dist/request-withdrawal-GBPH2FDY.js.map +1 -0
  292. package/dist/revoke-TUFRGI6S.js +18 -0
  293. package/dist/revoke-TUFRGI6S.js.map +1 -0
  294. package/dist/sealed-record/index.d.ts +69 -0
  295. package/dist/sealed-record/index.js +65 -0
  296. package/dist/sealed-record/index.js.map +1 -0
  297. package/dist/session/index.d.ts +6 -8
  298. package/dist/session/index.js +7 -5
  299. package/dist/session/index.js.map +1 -1
  300. package/dist/shadow/index.d.ts +5 -7
  301. package/dist/shadow/index.js +4 -3
  302. package/dist/shadow/index.js.map +1 -1
  303. package/dist/{signer-72QAUSVW.js → signer-PNKTBVF7.js} +6 -5
  304. package/dist/signer-PNKTBVF7.js.map +1 -0
  305. package/dist/snapshots/index.d.ts +6 -8
  306. package/dist/snapshots/index.js +13 -11
  307. package/dist/snapshots/index.js.map +1 -1
  308. package/dist/{stale-6ZDBTQT7.js → stale-3JWHNDIY.js} +3 -2
  309. package/dist/stale-3JWHNDIY.js.map +1 -0
  310. package/dist/store-coordination-provider-3I7XWZZK.js +142 -0
  311. package/dist/store-coordination-provider-3I7XWZZK.js.map +1 -0
  312. package/dist/subject-index-O75wKshW.d.ts +362 -0
  313. package/dist/sync/index.d.ts +4 -6
  314. package/dist/sync/index.js +7 -6
  315. package/dist/sync/index.js.map +1 -1
  316. package/dist/team/index.d.ts +5 -7
  317. package/dist/team/index.js +20 -16
  318. package/dist/tiers/index.d.ts +5 -0
  319. package/dist/tiers/index.js +33 -0
  320. package/dist/tiers/index.js.map +1 -0
  321. package/dist/to/index.d.ts +5 -0
  322. package/dist/to/index.js +17 -0
  323. package/dist/to/index.js.map +1 -0
  324. package/dist/transition-guard-C7ol6oPw.d.ts +165 -0
  325. package/dist/tx/index.d.ts +23 -9
  326. package/dist/tx/index.js +13 -8
  327. package/dist/tx/index.js.map +1 -1
  328. package/dist/ui/index.d.ts +1 -0
  329. package/dist/ui/index.js +1 -0
  330. package/dist/ui/index.js.map +1 -0
  331. package/dist/ulid-DRH25k3y.d.ts +66 -0
  332. package/dist/ulid-PTAIMDG4.js +10 -0
  333. package/dist/ulid-PTAIMDG4.js.map +1 -0
  334. package/dist/util/index.d.ts +2 -0
  335. package/dist/util/index.js +7 -2
  336. package/dist/util/index.js.map +1 -1
  337. package/dist/vault-diff-B5fYNBL7.d.ts +147 -0
  338. package/dist/with/index.d.ts +38 -0
  339. package/dist/with/index.js +25 -0
  340. package/dist/with/index.js.map +1 -0
  341. package/dist/{with-materialized-view-BLkQxoQN.d.ts → with-materialized-view-6p0Fk8bL.d.ts} +1 -1
  342. package/dist/{with-overlayed-view-CRsSEwHR.d.ts → with-overlayed-view-BJ6mXGMd.d.ts} +2 -3
  343. package/dist/with-rollup-BvQo3ROo.d.ts +47 -0
  344. package/dist/withdraw-accessible-FFS46EOD.js +22 -0
  345. package/dist/withdraw-accessible-FFS46EOD.js.map +1 -0
  346. package/dist/zod-HAJM7LMS.js +14763 -0
  347. package/dist/zod-HAJM7LMS.js.map +1 -0
  348. package/package.json +121 -201
  349. package/dist/aggregate/index.cjs.map +0 -1
  350. package/dist/aggregate/index.d.cts +0 -38
  351. package/dist/attestation/index.cjs +0 -305
  352. package/dist/attestation/index.cjs.map +0 -1
  353. package/dist/attestation/index.d.cts +0 -52
  354. package/dist/blobs/index.cjs +0 -1480
  355. package/dist/blobs/index.cjs.map +0 -1
  356. package/dist/blobs/index.d.cts +0 -46
  357. package/dist/bundle/index.cjs +0 -19264
  358. package/dist/bundle/index.cjs.map +0 -1
  359. package/dist/bundle/index.d.cts +0 -176
  360. package/dist/chunk-22DWZL57.js.map +0 -1
  361. package/dist/chunk-2GLDA55J.js.map +0 -1
  362. package/dist/chunk-2QR2PQTT.js.map +0 -1
  363. package/dist/chunk-2WUSG3IT.js.map +0 -1
  364. package/dist/chunk-3BFJOWSU.js.map +0 -1
  365. package/dist/chunk-3YPCK6JX.js.map +0 -1
  366. package/dist/chunk-53XBRIRT.js.map +0 -1
  367. package/dist/chunk-5T22KDPN.js.map +0 -1
  368. package/dist/chunk-5XHKQ56N.js +0 -340
  369. package/dist/chunk-5XHKQ56N.js.map +0 -1
  370. package/dist/chunk-6CME4UEK.js.map +0 -1
  371. package/dist/chunk-6STK5TQP.js +0 -139
  372. package/dist/chunk-6STK5TQP.js.map +0 -1
  373. package/dist/chunk-A3JMGXPG.js.map +0 -1
  374. package/dist/chunk-B6PB7JLN.js.map +0 -1
  375. package/dist/chunk-BVRYKATC.js.map +0 -1
  376. package/dist/chunk-DE6GKS6G.js.map +0 -1
  377. package/dist/chunk-DFMLEQZB.js.map +0 -1
  378. package/dist/chunk-DJHHA6XH.js.map +0 -1
  379. package/dist/chunk-DL3HWOQ5.js.map +0 -1
  380. package/dist/chunk-DONMZAD2.js.map +0 -1
  381. package/dist/chunk-EMIGCR7X.js.map +0 -1
  382. package/dist/chunk-F3GDRNUT.js.map +0 -1
  383. package/dist/chunk-FZU343FL.js.map +0 -1
  384. package/dist/chunk-H2X3ISXG.js.map +0 -1
  385. package/dist/chunk-HNRHLRDC.js.map +0 -1
  386. package/dist/chunk-I5FOWO4J.js.map +0 -1
  387. package/dist/chunk-J66GRPNH.js.map +0 -1
  388. package/dist/chunk-JWRVQKRZ.js.map +0 -1
  389. package/dist/chunk-K3DK3NU5.js.map +0 -1
  390. package/dist/chunk-ML236QKC.js.map +0 -1
  391. package/dist/chunk-NONAAENK.js.map +0 -1
  392. package/dist/chunk-O3VZPBZG.js.map +0 -1
  393. package/dist/chunk-OIF6LZUR.js.map +0 -1
  394. package/dist/chunk-OQ6PIGHA.js +0 -19
  395. package/dist/chunk-OQ6PIGHA.js.map +0 -1
  396. package/dist/chunk-PE2FR4J3.js.map +0 -1
  397. package/dist/chunk-PP6W64Y3.js +0 -275
  398. package/dist/chunk-PP6W64Y3.js.map +0 -1
  399. package/dist/chunk-PX35GA7L.js.map +0 -1
  400. package/dist/chunk-QEILDE6R.js +0 -793
  401. package/dist/chunk-QEILDE6R.js.map +0 -1
  402. package/dist/chunk-QODLLGQ7.js.map +0 -1
  403. package/dist/chunk-RAZ4OVLL.js +0 -51
  404. package/dist/chunk-RAZ4OVLL.js.map +0 -1
  405. package/dist/chunk-SYMWGEET.js.map +0 -1
  406. package/dist/chunk-T7JEBOGN.js.map +0 -1
  407. package/dist/chunk-TFBP23BX.js.map +0 -1
  408. package/dist/chunk-TV3YZ35S.js +0 -90
  409. package/dist/chunk-TV3YZ35S.js.map +0 -1
  410. package/dist/chunk-U26HQ6KJ.js.map +0 -1
  411. package/dist/chunk-UF3BUNQZ.js +0 -1
  412. package/dist/chunk-UMLVJTYV.js +0 -20
  413. package/dist/chunk-UMLVJTYV.js.map +0 -1
  414. package/dist/chunk-VTKGMEPP.js.map +0 -1
  415. package/dist/chunk-W6EQLGMB.js +0 -100
  416. package/dist/chunk-W6EQLGMB.js.map +0 -1
  417. package/dist/chunk-WIRRPTFH.js +0 -17
  418. package/dist/chunk-WIRRPTFH.js.map +0 -1
  419. package/dist/chunk-WPLVTJ5D.js.map +0 -1
  420. package/dist/chunk-XJFLDA7A.js.map +0 -1
  421. package/dist/chunk-Z6FNBOTC.js.map +0 -1
  422. package/dist/chunk-ZYWZWG6G.js.map +0 -1
  423. package/dist/consent/index.cjs +0 -204
  424. package/dist/consent/index.cjs.map +0 -1
  425. package/dist/consent/index.d.cts +0 -25
  426. package/dist/crdt/index.cjs +0 -152
  427. package/dist/crdt/index.cjs.map +0 -1
  428. package/dist/crdt/index.d.cts +0 -30
  429. package/dist/crypto-HTZ4FJOP.js +0 -44
  430. package/dist/delegation-RI54P6I5.js +0 -17
  431. package/dist/derivations/index.cjs +0 -351
  432. package/dist/derivations/index.cjs.map +0 -1
  433. package/dist/derivations/index.d.cts +0 -72
  434. package/dist/dev-unlock-BIoEFbwm.d.cts +0 -263
  435. package/dist/executor-5PNY7LGW.js +0 -8
  436. package/dist/executor-B4QIYGZX.js +0 -8
  437. package/dist/executor-BWXXDQ7K.js +0 -11
  438. package/dist/fanout-sidecar-OKPMMPLG.js.map +0 -1
  439. package/dist/guards/index.cjs +0 -322
  440. package/dist/guards/index.cjs.map +0 -1
  441. package/dist/guards/index.d.cts +0 -31
  442. package/dist/hash-HJqD14vS.d.ts +0 -63
  443. package/dist/history/index.cjs +0 -1222
  444. package/dist/history/index.cjs.map +0 -1
  445. package/dist/history/index.d.cts +0 -63
  446. package/dist/i18n/index.cjs +0 -1100
  447. package/dist/i18n/index.cjs.map +0 -1
  448. package/dist/i18n/index.d.cts +0 -39
  449. package/dist/index-4fBVt8j9.d.cts +0 -2387
  450. package/dist/index-D8I_pyJD.d.ts +0 -2387
  451. package/dist/index.cjs +0 -24487
  452. package/dist/index.cjs.map +0 -1
  453. package/dist/index.d.cts +0 -776
  454. package/dist/indexing/index.cjs +0 -742
  455. package/dist/indexing/index.cjs.map +0 -1
  456. package/dist/indexing/index.d.cts +0 -36
  457. package/dist/issue-VGDPP4B5.js +0 -12
  458. package/dist/lazy-builder-7tIpFyWN.d.ts +0 -304
  459. package/dist/lazy-builder-wY4pMCEe.d.cts +0 -304
  460. package/dist/materialized-views/index.cjs +0 -854
  461. package/dist/materialized-views/index.cjs.map +0 -1
  462. package/dist/materialized-views/index.d.cts +0 -186
  463. package/dist/mime-magic-CBBSOkjm.d.cts +0 -50
  464. package/dist/mime-magic-CBBSOkjm.d.ts +0 -50
  465. package/dist/noydb-G725ZSZG.js +0 -34
  466. package/dist/overlay-views/index.cjs +0 -359
  467. package/dist/overlay-views/index.cjs.map +0 -1
  468. package/dist/overlay-views/index.d.cts +0 -82
  469. package/dist/periods/index.cjs +0 -1041
  470. package/dist/periods/index.cjs.map +0 -1
  471. package/dist/periods/index.d.cts +0 -22
  472. package/dist/predicate-BSAGEyu5.d.cts +0 -209
  473. package/dist/predicate-BSAGEyu5.d.ts +0 -209
  474. package/dist/query/index.cjs +0 -2375
  475. package/dist/query/index.cjs.map +0 -1
  476. package/dist/query/index.d.cts +0 -3
  477. package/dist/read-only-facade-ITU6L7BL.js +0 -7
  478. package/dist/registry-3QP3YKQS.js +0 -8
  479. package/dist/registry-DKEXOJVO.js +0 -7
  480. package/dist/registry-OJIOSBV6.js +0 -10
  481. package/dist/registry-USRVT6YF.js +0 -8
  482. package/dist/revoke-JCC7N56X.js +0 -17
  483. package/dist/session/index.cjs +0 -495
  484. package/dist/session/index.cjs.map +0 -1
  485. package/dist/session/index.d.cts +0 -46
  486. package/dist/shadow/index.cjs +0 -133
  487. package/dist/shadow/index.cjs.map +0 -1
  488. package/dist/shadow/index.d.cts +0 -17
  489. package/dist/snapshots/index.cjs +0 -937
  490. package/dist/snapshots/index.cjs.map +0 -1
  491. package/dist/snapshots/index.d.cts +0 -28
  492. package/dist/store/index.cjs +0 -1083
  493. package/dist/store/index.cjs.map +0 -1
  494. package/dist/store/index.d.cts +0 -492
  495. package/dist/store/index.d.ts +0 -492
  496. package/dist/store/index.js +0 -37
  497. package/dist/strategy-BSxFXGzb.d.cts +0 -110
  498. package/dist/strategy-BSxFXGzb.d.ts +0 -110
  499. package/dist/strategy-DSTrsZ8t.d.cts +0 -601
  500. package/dist/strategy-DSTrsZ8t.d.ts +0 -601
  501. package/dist/sync/index.cjs +0 -1062
  502. package/dist/sync/index.cjs.map +0 -1
  503. package/dist/sync/index.d.cts +0 -43
  504. package/dist/team/index.cjs +0 -2798
  505. package/dist/team/index.cjs.map +0 -1
  506. package/dist/team/index.d.cts +0 -118
  507. package/dist/tx/index.cjs +0 -544
  508. package/dist/tx/index.cjs.map +0 -1
  509. package/dist/tx/index.d.cts +0 -21
  510. package/dist/types-DyXYr8rE.d.cts +0 -12818
  511. package/dist/ulid-COREQ2RQ.js +0 -9
  512. package/dist/ulid-Drr7ykr6.d.cts +0 -603
  513. package/dist/util/index.cjs +0 -230
  514. package/dist/util/index.cjs.map +0 -1
  515. package/dist/util/index.d.cts +0 -77
  516. package/dist/with-derivation-DFnFByiQ.d.ts +0 -13
  517. package/dist/with-derivation-DU3Sjazm.d.cts +0 -13
  518. package/dist/with-guard-ByyxmEe7.d.cts +0 -18
  519. package/dist/with-guard-qube6BMI.d.ts +0 -18
  520. package/dist/with-materialized-view-BmEToIR1.d.cts +0 -27
  521. package/dist/with-overlayed-view-BMsQQbWm.d.cts +0 -13
  522. /package/dist/{store → adapter}/index.js.map +0 -0
  523. /package/dist/{chunk-UF3BUNQZ.js.map → api-RW3KP7WU.js.map} +0 -0
  524. /package/dist/{crypto-HTZ4FJOP.js.map → as/index.js.map} +0 -0
  525. /package/dist/{delegation-RI54P6I5.js.map → at/index.js.map} +0 -0
  526. /package/dist/{executor-5PNY7LGW.js.map → by/index.js.map} +0 -0
  527. /package/dist/{executor-B4QIYGZX.js.map → cargo/index.js.map} +0 -0
  528. /package/dist/{executor-BWXXDQ7K.js.map → chunk-BGIZAFY7.js.map} +0 -0
  529. /package/dist/{issue-VGDPP4B5.js.map → chunk-CHFZDSE4.js.map} +0 -0
  530. /package/dist/{ledger-TMRZYNVJ.js.map → chunk-GHVIKOHT.js.map} +0 -0
  531. /package/dist/{noydb-G725ZSZG.js.map → chunk-K2WCO3NX.js.map} +0 -0
  532. /package/dist/{public-envelope-BW6OXORV.js.map → chunk-PZ5AY32C.js.map} +0 -0
  533. /package/dist/{read-only-facade-ITU6L7BL.js.map → collection-facade-GQAOGJP2.js.map} +0 -0
  534. /package/dist/{registry-3QP3YKQS.js.map → delegation-UL5HKLER.js.map} +0 -0
  535. /package/dist/{registry-DKEXOJVO.js.map → describe/index.js.map} +0 -0
  536. /package/dist/{registry-OJIOSBV6.js.map → enclave-UL5LW66V.js.map} +0 -0
  537. /package/dist/{registry-USRVT6YF.js.map → executor-2FWQRLMG.js.map} +0 -0
  538. /package/dist/{revoke-JCC7N56X.js.map → executor-QZ7BXICW.js.map} +0 -0
  539. /package/dist/{signer-72QAUSVW.js.map → executor-Z5ZLJVTV.js.map} +0 -0
  540. /package/dist/{stale-6ZDBTQT7.js.map → export-accessible-KRV5W4GH.js.map} +0 -0
  541. /package/dist/{ulid-COREQ2RQ.js.map → extract-partition-GLKBOXFQ.js.map} +0 -0
@@ -1,2387 +0,0 @@
1
- import { C as CollectionIndexes, a as Clause, O as Operator } from './predicate-BSAGEyu5.js';
2
- import { A as AggregateStrategy, b as AggregateSpec, c as Aggregation, a as AggregateResult, g as GroupedQuery, h as GroupedQueryN } from './strategy-DSTrsZ8t.js';
3
-
4
- /**
5
- * All NOYDB error classes — a single import surface for `catch` blocks and
6
- * `instanceof` checks.
7
- *
8
- * ## Class hierarchy
9
- *
10
- * ```
11
- * Error
12
- * └─ NoydbError (code: string)
13
- * ├─ Crypto errors
14
- * │ ├─ DecryptionError — AES-GCM tag failure
15
- * │ ├─ TamperedError — ciphertext modified after write
16
- * │ └─ InvalidKeyError — wrong passphrase / corrupt keyring
17
- * ├─ Access errors
18
- * │ ├─ NoAccessError — no DEK for this collection
19
- * │ ├─ ReadOnlyError — ro permission, write attempted
20
- * │ ├─ PermissionDeniedError — role too low for operation
21
- * │ ├─ PrivilegeEscalationError — grant wider than grantor holds
22
- * │ └─ StoreCapabilityError — optional store method missing
23
- * ├─ Sync errors
24
- * │ ├─ ConflictError — optimistic-lock version mismatch
25
- * │ ├─ BundleVersionConflictError — bundle push rejected by remote
26
- * │ └─ NetworkError — push/pull network failure
27
- * ├─ Data errors
28
- * │ ├─ NotFoundError — get(id) on missing record
29
- * │ ├─ ValidationError — application-level guard failed
30
- * │ └─ SchemaValidationError — Standard Schema v1 rejection
31
- * ├─ Query errors
32
- * │ ├─ JoinTooLargeError — join row ceiling exceeded
33
- * │ ├─ CrossJoinTooLargeError — cross-join row ceiling exceeded
34
- * │ ├─ CrossJoinSourceUnknownError — target collection not in vault
35
- * │ ├─ DanglingReferenceError — strict ref() points at nothing
36
- * │ ├─ GroupCardinalityError — groupBy bucket cap exceeded
37
- * │ ├─ IndexRequiredError — lazy-mode query touches unindexed field
38
- * │ └─ IndexWriteFailureError — index side-car put/delete failed post-main
39
- * ├─ i18n / Dictionary errors
40
- * │ ├─ ReservedCollectionNameError
41
- * │ ├─ DictKeyMissingError
42
- * │ ├─ DictKeyInUseError
43
- * │ ├─ MissingTranslationError
44
- * │ ├─ LocaleNotSpecifiedError
45
- * │ └─ TranslatorNotConfiguredError
46
- * ├─ Backup errors
47
- * │ ├─ BackupLedgerError — hash-chain verification failed
48
- * │ └─ BackupCorruptedError — envelope hash mismatch in dump
49
- * ├─ Bundle errors
50
- * │ └─ BundleIntegrityError — .noydb body sha256 mismatch
51
- * ├─ Session errors
52
- * │ ├─ SessionExpiredError
53
- * │ ├─ SessionNotFoundError
54
- * │ └─ SessionPolicyError
55
- * └─ Snapshot errors
56
- * └─ SnapshotNotFoundError — snapshot key absent from snapshot store
57
- * ```
58
- *
59
- * ## Catching all NOYDB errors
60
- *
61
- * ```ts
62
- * import { NoydbError, InvalidKeyError, ConflictError } from '@noy-db/hub'
63
- *
64
- * try {
65
- * await vault.unlock(passphrase)
66
- * } catch (e) {
67
- * if (e instanceof InvalidKeyError) { showBadPassphraseUI(); return }
68
- * if (e instanceof NoydbError) { logToSentry(e.code, e); return }
69
- * throw e // unexpected — re-throw
70
- * }
71
- * ```
72
- *
73
- * @module
74
- */
75
- /**
76
- * Base class for all NOYDB errors.
77
- *
78
- * Every error thrown by `@noy-db/hub` extends this class, so consumers can
79
- * catch all NOYDB errors in a single `catch (e) { if (e instanceof NoydbError) ... }`
80
- * block. The `code` field is a machine-readable string (e.g. `'DECRYPTION_FAILED'`)
81
- * suitable for `switch` statements and logging pipelines.
82
- */
83
- declare class NoydbError extends Error {
84
- /** Machine-readable error code. Stable across library versions. */
85
- readonly code: string;
86
- constructor(code: string, message: string);
87
- }
88
- /**
89
- * Thrown when AES-GCM decryption fails.
90
- *
91
- * The most common cause is a wrong passphrase or a corrupted ciphertext.
92
- * A `DecryptionError` at the wrong passphrase level is caught internally
93
- * and re-thrown as `InvalidKeyError` — so in practice this surfaces for
94
- * per-record corruption rather than authentication failures.
95
- */
96
- declare class DecryptionError extends NoydbError {
97
- constructor(message?: string);
98
- }
99
- /**
100
- * Thrown when GCM tag verification fails, indicating the ciphertext was
101
- * modified after encryption.
102
- *
103
- * AES-256-GCM is authenticated encryption — the tag over the ciphertext
104
- * is checked on every decrypt. If any byte was flipped (accidental
105
- * corruption or deliberate tampering), decryption throws this error.
106
- * Treat it as a security alert: the stored bytes are not what NOYDB wrote.
107
- */
108
- declare class TamperedError extends NoydbError {
109
- constructor(message?: string);
110
- }
111
- /**
112
- * Thrown when key unwrapping fails, typically because the passphrase is wrong
113
- * or the keyring file is corrupted.
114
- *
115
- * NOYDB uses AES-KW (RFC 3394) to wrap DEKs with the KEK. If AES-KW
116
- * unwrapping fails, it means either the KEK was derived from the wrong
117
- * passphrase (PBKDF2 with 600K iterations) or the keyring bytes are
118
- * corrupted. This is the error shown to the user on a failed unlock attempt.
119
- */
120
- declare class InvalidKeyError extends NoydbError {
121
- constructor(message?: string);
122
- }
123
- /**
124
- * Thrown when a keyring's wrapped-DEK set unwraps partially — at least
125
- * one DEK succeeds (proving the KEK is correct) but at least one fails.
126
- * The passphrase is right; the failed entries are corrupted.
127
- *
128
- * This is distinct from {@link InvalidKeyError} so that
129
- * `NoydbOptions.onInvalidKey: 'reset'` does NOT fire — resetting on
130
- * partial corruption would destroy the still-valid DEKs and the data
131
- * they protect, which is silent data loss in response to a feature
132
- * designed for stale-credential recovery.
133
- */
134
- declare class KeyringCorruptError extends NoydbError {
135
- readonly failedCollections: readonly string[];
136
- readonly intactCount: number;
137
- constructor(opts: {
138
- failedCollections: readonly string[];
139
- intactCount: number;
140
- message?: string;
141
- });
142
- }
143
- /**
144
- * Thrown when the authenticated user does not have a DEK for the requested
145
- * collection — i.e. the collection is not in their keyring at all.
146
- *
147
- * This is the "no key for this door" error. It is different from
148
- * `ReadOnlyError` (user has a key but it only grants ro) and from
149
- * `PermissionDeniedError` (user's role doesn't allow the operation).
150
- */
151
- declare class NoAccessError extends NoydbError {
152
- constructor(message?: string);
153
- }
154
- /**
155
- * Thrown when a user with read-only (`ro`) permission attempts a write
156
- * operation (`put` or `delete`) on a collection.
157
- *
158
- * The user has a DEK for the collection (they can decrypt and read), but
159
- * their keyring grants only `ro`. To fix: re-grant the user with `rw`
160
- * permission, or do not attempt writes as a viewer/client role.
161
- */
162
- declare class ReadOnlyError extends NoydbError {
163
- constructor(message?: string);
164
- }
165
- /**
166
- * Thrown when a write is attempted against a historical view produced
167
- * by `vault.at(timestamp)`. Time-machine views are read-only by
168
- * contract — mutating the past would require either the shadow-vault
169
- * mechanism or a ledger-history rewrite (which breaks
170
- * the tamper-evidence guarantee).
171
- *
172
- * Distinct from {@link ReadOnlyError} (keyring-level) and
173
- * {@link PermissionDeniedError} (role-level): this error is about the
174
- * *view* being historical, independent of the caller's permissions.
175
- */
176
- declare class ReadOnlyAtInstantError extends NoydbError {
177
- constructor(operation: string, timestamp: string);
178
- }
179
- /**
180
- * Thrown when a write is attempted against a shadow-vault frame
181
- * produced by `vault.frame()`. Frames are read-only by contract —
182
- * the use case is screen-sharing / demos / compliance review where
183
- * the operator wants to prevent accidental edits.
184
- *
185
- * Behavioural enforcement only — the underlying keyring still holds
186
- * write-capable DEKs. See {@link VaultFrame} for the full caveat.
187
- */
188
- declare class ReadOnlyFrameError extends NoydbError {
189
- constructor(operation: string);
190
- }
191
- /**
192
- * Thrown when the authenticated user's role does not permit the requested
193
- * operation — e.g. a `viewer` calling `grantAccess()`, or an `operator`
194
- * calling `rotateKeys()`.
195
- *
196
- * This is a role-level check (what the user's role allows), distinct from
197
- * `NoAccessError` (collection not in keyring) and `ReadOnlyError` (in
198
- * keyring, but write not allowed).
199
- */
200
- declare class PermissionDeniedError extends NoydbError {
201
- constructor(message?: string);
202
- }
203
- /**
204
- * Thrown when an `@noy-db/as-*` export is attempted without the
205
- * required capability bit on the invoking keyring.
206
- *
207
- * Two sub-cases discriminated by the `tier` field:
208
- *
209
- * - `tier: 'plaintext'` — a plaintext-tier export (`as-xlsx`,
210
- * `as-csv`, `as-blob`, `as-zip`, …) was attempted but the
211
- * keyring's `exportCapability.plaintext` does not include the
212
- * requested `format` (nor the `'*'` wildcard). Default for every
213
- * role is `plaintext: []` — the owner must positively grant.
214
- * - `tier: 'bundle'` — an encrypted `as-noydb` bundle export was
215
- * attempted but the keyring's `exportCapability.bundle` is
216
- * `false`. Default for `owner`/`admin` is `true`; for
217
- * `operator`/`viewer`/`client` it is `false`.
218
- *
219
- * Distinct from `PermissionDeniedError` (role-level check) and
220
- * `NoAccessError` (collection not readable). Surfaces separately so
221
- * UI layers can show a "request the export capability from your
222
- * admin" flow rather than a generic permission error.
223
- */
224
- declare class ExportCapabilityError extends NoydbError {
225
- readonly tier: 'plaintext' | 'bundle';
226
- readonly format?: string;
227
- readonly userId: string;
228
- constructor(opts: {
229
- tier: 'plaintext' | 'bundle';
230
- userId: string;
231
- format?: string;
232
- message?: string;
233
- });
234
- }
235
- /**
236
- * Thrown when a keyring file's `expires_at` cutoff has passed.
237
- * Surfaced by `loadKeyring` before any DEK unwrap is attempted —
238
- * past the cutoff the slot refuses to open even with the right
239
- * passphrase. Distinct from PBKDF2 / unwrap errors so consumer code
240
- * can show a precise "this bundle slot has expired" message instead
241
- * of the generic decryption-failure UX.
242
- *
243
- * Used predominantly on `BundleRecipient` slots produced by
244
- * `writeNoydbBundle({ recipients: [...] })` to time-box audit access.
245
- */
246
- declare class KeyringExpiredError extends NoydbError {
247
- readonly userId: string;
248
- readonly expiresAt: string;
249
- constructor(opts: {
250
- userId: string;
251
- expiresAt: string;
252
- });
253
- }
254
- /**
255
- * Thrown when an `@noy-db/as-*` import is attempted but the invoking
256
- * keyring lacks the required import-capability bit.
257
- *
258
- * - `tier: 'plaintext'` — a plaintext-tier import (`as-csv`, `as-json`,
259
- * `as-ndjson`, `as-zip`, …) was attempted but the keyring's
260
- * `importCapability.plaintext` does not include the requested
261
- * `format` (nor the `'*'` wildcard).
262
- * - `tier: 'bundle'` — a `.noydb` bundle import was attempted but the
263
- * keyring's `importCapability.bundle` is not `true`.
264
- *
265
- * Default for every role on every dimension is closed — owners and
266
- * admins must positively grant the capability. Distinct from
267
- * `PermissionDeniedError` and `NoAccessError` so UI layers can show a
268
- * specific "request the import capability" flow.
269
- */
270
- declare class ImportCapabilityError extends NoydbError {
271
- readonly tier: 'plaintext' | 'bundle';
272
- readonly format?: string;
273
- readonly userId: string;
274
- constructor(opts: {
275
- tier: 'plaintext' | 'bundle';
276
- userId: string;
277
- format?: string;
278
- message?: string;
279
- });
280
- }
281
- /**
282
- * Thrown when a grant would give the grantee a permission the grantor
283
- * does not themselves hold — the "admin cannot grant what admin cannot
284
- * do" rule from the admin-delegation work.
285
- *
286
- * Distinct from `PermissionDeniedError` so callers can tell the two
287
- * cases apart in logs and tests:
288
- *
289
- * - `PermissionDeniedError` — "you are not allowed to perform this
290
- * operation at all" (wrong role).
291
- * - `PrivilegeEscalationError` — "you are allowed to grant, but not
292
- * with these specific permissions" (widening attempt).
293
- *
294
- * Under the admin model the grantee of an admin-grants-admin call
295
- * inherits the caller's entire DEK set by construction, so this error
296
- * is structurally unreachable in typical flows. The check and error
297
- * class exist so that future per-collection admin scoping cannot
298
- * accidentally bypass the subset rule — the guard is already wired in.
299
- *
300
- * `offendingCollection` carries the first collection name that failed
301
- * the subset check, to make the violation actionable in error output.
302
- */
303
- /**
304
- * Thrown when a caller invokes an API that requires an optional
305
- * store capability the active store does not implement.
306
- *
307
- * Today the only call site is `Noydb.listAccessibleVaults()`,
308
- * which depends on the optional `NoydbStore.listVaults()`
309
- * method. The error message names the missing method and the calling
310
- * API so consumers know exactly which combination is unsupported,
311
- * and the `capability` field is machine-readable so library code can
312
- * pattern-match in catch blocks (e.g. fall back to a candidate-list
313
- * shape).
314
- *
315
- * The class lives in `errors.ts` rather than as a generic
316
- * `ValidationError` because the diagnostic shape is different: a
317
- * `ValidationError` says "the inputs you passed are wrong"; this
318
- * error says "the inputs are fine, but the store you wired up
319
- * doesn't support what you're asking for." Different fix, different
320
- * documentation.
321
- */
322
- declare class StoreCapabilityError extends NoydbError {
323
- /** The store method/capability that was missing. */
324
- readonly capability: string;
325
- constructor(capability: string, callerApi: string, storeName?: string);
326
- }
327
- declare class PrivilegeEscalationError extends NoydbError {
328
- readonly offendingCollection: string;
329
- constructor(offendingCollection: string, message?: string);
330
- }
331
- /**
332
- * Thrown by `Collection.put` / `.delete` when the target record's
333
- * envelope `_ts` falls within a closed accounting period.
334
- *
335
- * Distinct from `ReadOnlyError` (keyring-level), `ReadOnlyAtInstantError`
336
- * (historical view), and `ReadOnlyFrameError` (shadow vault): this
337
- * error is about the STORED RECORD being sealed by an operator call
338
- * to `vault.closePeriod()`, independent of caller permissions or
339
- * view type. The `periodName` and `endDate` fields name the sealing
340
- * period so audit UIs can surface a "this record is locked in
341
- * FY2026-Q1 (closed 2026-03-31)" message without parsing the error
342
- * string.
343
- *
344
- * To apply a correction after close, book a compensating entry in a
345
- * new period rather than unlocking the old one. Re-opening a closed
346
- * period is deliberately unsupported.
347
- */
348
- declare class PeriodClosedError extends NoydbError {
349
- readonly periodName: string;
350
- readonly endDate: string;
351
- readonly recordTs: string;
352
- constructor(periodName: string, endDate: string, recordTs: string);
353
- }
354
- /**
355
- * Thrown when a `put()` or `delete()` is rejected by a guard's `check`
356
- * function. The `reason` is the message the guard supplied — typically a
357
- * short business description (e.g. "invoice is issued"). The full
358
- * collection + id are surfaced so audit UIs can link back to the record.
359
- */
360
- declare class RecordLockedError extends NoydbError {
361
- readonly collection: string;
362
- readonly id: string;
363
- readonly reason: string;
364
- constructor(collection: string, id: string, reason: string);
365
- }
366
- /**
367
- * Thrown when a `put()` changes one or more fields that are frozen by a
368
- * `frozenFields` guard. The `fields` list contains the specific paths
369
- * that were detected as changed.
370
- */
371
- declare class FieldFrozenError extends NoydbError {
372
- readonly collection: string;
373
- readonly id: string;
374
- readonly fields: readonly string[];
375
- constructor(collection: string, id: string, fields: readonly string[]);
376
- }
377
- /**
378
- * Thrown by an amendment invariant when the proposed change-set violates
379
- * the declared business rule (e.g. disbursement total not preserved).
380
- * Triggers a full transaction rollback via the existing revert pass.
381
- */
382
- declare class InvariantError extends NoydbError {
383
- constructor(message: string);
384
- }
385
- /**
386
- * Thrown at `withTransactions({ amendment: true })` open if the caller's
387
- * role is not in the guard's allowed amendment roles. Fail-fast: thrown
388
- * before any writes are attempted.
389
- */
390
- declare class AmendmentForbiddenError extends NoydbError {
391
- readonly userId: string;
392
- readonly role: string;
393
- constructor(userId: string, role: string);
394
- }
395
- /**
396
- * Thrown by `listUsersWithEnvelopes` when the vault's user directory
397
- * has been disabled (via `db.setDirectoryEnabled(vault, false)`) and
398
- * the caller's role is neither `owner` nor `admin`. Owner/admin can
399
- * still enumerate users — the toggle is a UX privacy switch, not a
400
- * security boundary.
401
- *
402
- * Honest caveat: this is a UX flag, not a privacy guarantee. The
403
- * envelope ciphertext is still in the store, the keyring file is
404
- * still listed at `_keyring/*`, and anyone with direct store read
405
- * access can count keyrings without going through the hub. See
406
- * `docs/subsystems/user-envelope.md` → "Directory visibility".
407
- */
408
- declare class DirectoryDisabledError extends NoydbError {
409
- readonly vault: string;
410
- constructor(vault: string);
411
- }
412
- /**
413
- * Thrown when a user tries to act at a tier they are not cleared for.
414
- *
415
- * This is the umbrella error for tier write refusals:
416
- * - `put({ tier: N })` when the user's keyring lacks tier-N DEK.
417
- * - `elevate(id, N)` when the caller cannot reach tier N.
418
- *
419
- * Distinct from `TierAccessDeniedError` which covers *read* refusals on
420
- * the invisibility/ghost path.
421
- */
422
- declare class TierNotGrantedError extends NoydbError {
423
- readonly tier: number;
424
- readonly collection: string;
425
- constructor(collection: string, tier: number);
426
- }
427
- /**
428
- * Thrown when an elevated-handle operation runs after the elevation's
429
- * TTL expired. Reads continue at the original tier; only writes
430
- * through the scoped handle flip to throwing once expired.
431
- */
432
- declare class ElevationExpiredError extends NoydbError {
433
- readonly tier: number;
434
- readonly expiresAt: number;
435
- constructor(opts: {
436
- tier: number;
437
- expiresAt: number;
438
- });
439
- }
440
- /**
441
- * Thrown by `vault.elevate(...)` when an elevation is already active
442
- * on the vault. Adopters must `release()` the existing handle before
443
- * starting a new elevation.
444
- */
445
- declare class AlreadyElevatedError extends NoydbError {
446
- readonly activeTier: number;
447
- constructor(activeTier: number);
448
- }
449
- /**
450
- * Thrown when `demote()` is called by someone who is not the original
451
- * elevator and not an owner.
452
- */
453
- declare class TierDemoteDeniedError extends NoydbError {
454
- constructor(id: string, tier: number);
455
- }
456
- /**
457
- * Thrown when `db.delegate()` is called against a user that has no
458
- * keyring in the target vault — the delegation token cannot be
459
- * constructed without the target user's KEK wrap.
460
- */
461
- declare class DelegationTargetMissingError extends NoydbError {
462
- readonly toUser: string;
463
- constructor(toUser: string);
464
- }
465
- /**
466
- * Thrown when a `put()` detects an optimistic concurrency conflict.
467
- *
468
- * NOYDB uses version numbers (`_v`) for optimistic locking. If a `put()`
469
- * is called with `expectedVersion: N` but the stored record is at version
470
- * `M ≠ N`, the write is rejected and the caller must re-read, re-apply their
471
- * change, and retry. The `version` field carries the actual stored version
472
- * so callers can decide whether to retry or surface the conflict to the user.
473
- */
474
- declare class ConflictError extends NoydbError {
475
- /** The actual stored version at the time of conflict. */
476
- readonly version: number;
477
- constructor(version: number, message?: string);
478
- }
479
- /**
480
- * Thrown by `LedgerStore.append()` after exhausting its CAS retry
481
- * budget under multi-writer contention. Two browser tabs, a
482
- * web app + an offline mobile peer, or a server worker pool all
483
- * producing ledger entries against the same vault can race on the
484
- * "read head, write head+1" cycle; the optimistic-CAS retry loop
485
- * resolves the race for `casAtomic: true` stores, but pathological
486
- * contention (or a buggy peer) can still exhaust the budget. When
487
- * that happens, the chain is intact — the failed writer simply
488
- * couldn't claim a slot. Caller's choice whether to retry, queue,
489
- * or surface the failure to the user.
490
- */
491
- declare class LedgerContentionError extends NoydbError {
492
- readonly attempts: number;
493
- constructor(attempts: number);
494
- }
495
- /**
496
- * Thrown when a bundle push is rejected because the remote has been updated
497
- * since the local bundle was last pulled.
498
- *
499
- * Unlike `ConflictError` (per-record), this is a whole-bundle conflict —
500
- * the remote's bundle handle has changed. The caller must pull the new
501
- * bundle, merge, and re-push. `remoteVersion` is the handle of the newer
502
- * remote bundle for use in diagnostics.
503
- */
504
- declare class BundleVersionConflictError extends NoydbError {
505
- /** The bundle handle of the newer remote version that rejected the push. */
506
- readonly remoteVersion: string;
507
- constructor(remoteVersion: string, message?: string);
508
- }
509
- /**
510
- * Thrown when a sync operation (push or pull) fails due to a network error.
511
- *
512
- * NOYDB's offline-first design means network errors are expected during sync.
513
- * Callers should catch `NetworkError`, surface connectivity status in the UI,
514
- * and rely on the `SyncScheduler` to retry when connectivity is restored.
515
- */
516
- declare class NetworkError extends NoydbError {
517
- constructor(message?: string);
518
- }
519
- /**
520
- * Thrown when `collection.get(id)` is called with an ID that does not exist.
521
- *
522
- * NOYDB collections are memory-first, so this error is synchronous and cheap —
523
- * it does not make a network round-trip. Callers that expect the record to be
524
- * absent should use `collection.getOrNull(id)` instead.
525
- */
526
- declare class NotFoundError extends NoydbError {
527
- constructor(message?: string);
528
- }
529
- /**
530
- * Thrown when application-level validation fails before encryption.
531
- *
532
- * Distinct from `SchemaValidationError` (Standard Schema v1 validator)
533
- * and `MissingTranslationError` (i18nText). `ValidationError` is the
534
- * general-purpose validation base — use it for custom guards in `put()`
535
- * hooks or store middleware.
536
- */
537
- declare class ValidationError extends NoydbError {
538
- constructor(message?: string);
539
- }
540
- /**
541
- * Thrown when a Standard Schema v1 validator rejects a record on
542
- * `put()` (input validation) or on read (output validation). Carries
543
- * the raw issue list so callers can render field-level errors.
544
- *
545
- * `direction` distinguishes the two cases:
546
- * - `'input'`: the user passed bad data into `put()`. This is a
547
- * normal error case that application code should handle — typically
548
- * by showing validation messages in the UI.
549
- * - `'output'`: stored data does not match the current schema. This
550
- * indicates a schema drift (the schema was changed without
551
- * migrating the existing records) and should be treated as a bug
552
- * — the application should not swallow it silently.
553
- *
554
- * The `issues` type is deliberately `readonly unknown[]` on this class
555
- * so that `errors.ts` doesn't need to import from `schema.ts` (and
556
- * create a dependency cycle). Callers who know they're holding a
557
- * `SchemaValidationError` can cast to the more precise
558
- * `readonly StandardSchemaV1Issue[]` from `schema.ts`.
559
- */
560
- declare class SchemaValidationError extends NoydbError {
561
- readonly issues: readonly unknown[];
562
- readonly direction: 'input' | 'output';
563
- constructor(message: string, issues: readonly unknown[], direction: 'input' | 'output');
564
- }
565
- /** Base for schema-evolution strategy rejections. */
566
- declare class SchemaUpdateError extends NoydbError {
567
- constructor(code: string, message: string);
568
- }
569
- /** A non-additive schema change was rejected by the `additiveOnly()` strategy. */
570
- declare class NonAdditiveSchemaChangeError extends SchemaUpdateError {
571
- constructor(message: string);
572
- }
573
- /** A schema change was rejected by the `lockSchema()` strategy. */
574
- declare class SchemaLockedError extends SchemaUpdateError {
575
- constructor(message: string);
576
- }
577
- /** Write attempted while a schema cutover fence is up (draining/migrating, or this collection has a pending cutover). */
578
- declare class SchemaFenceError extends SchemaUpdateError {
579
- constructor(message: string);
580
- }
581
- /** Write attempted by a client whose generation snapshot is behind the live fence — reload required. */
582
- declare class MigrationRequiredError extends SchemaUpdateError {
583
- constructor(message: string);
584
- }
585
- /** A coordinated cutover timed out waiting for active clients to quiesce. */
586
- declare class QuiesceTimeoutError extends SchemaUpdateError {
587
- constructor(message: string);
588
- }
589
- /**
590
- * Thrown when `.groupBy().aggregate()` produces more than the hard
591
- * cardinality cap (default 100_000 groups)..
592
- *
593
- * The cap exists because `.groupBy()` materializes one bucket per
594
- * distinct key value in memory, and runaway cardinality — a groupBy
595
- * on a high-uniqueness field like `id` or `createdAt` — is almost
596
- * always a query mistake rather than legitimate use. A hard error is
597
- * better than silent OOM: the consumer sees an actionable message
598
- * naming the field and the observed cardinality, with guidance to
599
- * either narrow the query with `.where()` or accept the ceiling
600
- * override.
601
- *
602
- * A separate one-shot warning fires at 10% of the cap (10_000
603
- * groups) so consumers get a heads-up before the hard error — same
604
- * pattern as `JoinTooLargeError` and the `.join()` row ceiling.
605
- *
606
- * **Not overridable in.** The 100k cap is a fixed constant so
607
- * the failure mode is consistent across the codebase; a
608
- * `{ maxGroups }` override can be added later without a break if a
609
- * real consumer asks.
610
- */
611
- declare class GroupCardinalityError extends NoydbError {
612
- /** The field being grouped on. */
613
- readonly field: string;
614
- /** Observed number of distinct groups at the moment the cap tripped. */
615
- readonly cardinality: number;
616
- /** The cap that was exceeded. */
617
- readonly maxGroups: number;
618
- constructor(field: string, cardinality: number, maxGroups: number);
619
- }
620
- /**
621
- * Thrown in lazy mode when a `.query()` / `.where()` / `.orderBy()` clause
622
- * references a field that does not have a declared index.
623
- *
624
- * Lazy-mode queries only work when every touched field is indexed.
625
- * This is deliberate — silent scan-fallback would hide the performance
626
- * cliff that lazy-mode indexes exist to prevent.
627
- *
628
- * Payload:
629
- * - `collection` — name of the collection queried
630
- * - `touchedFields` — every field referenced by the query (filter + order)
631
- * - `missingFields` — subset of `touchedFields` that have no declared index
632
- */
633
- declare class IndexRequiredError extends NoydbError {
634
- readonly collection: string;
635
- readonly touchedFields: readonly string[];
636
- readonly missingFields: readonly string[];
637
- constructor(args: {
638
- collection: string;
639
- touchedFields: readonly string[];
640
- missingFields: readonly string[];
641
- });
642
- }
643
- /**
644
- * Thrown (or surfaced via the `index:write-partial` event) when one or more
645
- * per-indexed-field side-car writes fail after the main record write has
646
- * already succeeded.
647
- *
648
- * Not thrown out of `.put()` / `.delete()` directly — those succeed when the
649
- * main record succeeds. Instead, `IndexWriteFailureError` instances are collected
650
- * into the session-scoped reconcile queue and emitted on the Collection
651
- * emitter as `index:write-partial`.
652
- *
653
- * Payload:
654
- * - `recordId` — the id of the main record whose side-car writes failed
655
- * - `field` — the indexed field whose side-car write failed
656
- * - `op` — `'put'` or `'delete'`, indicating which mutation was in flight
657
- * - `cause` — the underlying error from the store
658
- */
659
- declare class IndexWriteFailureError extends NoydbError {
660
- readonly recordId: string;
661
- readonly field: string;
662
- readonly op: 'put' | 'delete';
663
- readonly cause: unknown;
664
- constructor(args: {
665
- recordId: string;
666
- field: string;
667
- op: 'put' | 'delete';
668
- cause: unknown;
669
- });
670
- }
671
- /**
672
- * Thrown by `readNoydbBundle()` when the body bytes don't match
673
- * the integrity hash declared in the bundle header — i.e. someone
674
- * modified the bytes between write and read.
675
- *
676
- * Distinct from a generic `Error` (which would be thrown for
677
- * format violations like a missing magic prefix or malformed
678
- * header JSON) so consumers can pattern-match the corruption case
679
- * and handle it differently from a producer bug. A
680
- * `BundleIntegrityError` indicates "the bytes you got are not
681
- * what was written"; a plain `Error` from `parsePrefixAndHeader`
682
- * indicates "what was written wasn't a valid bundle in the first
683
- * place."
684
- *
685
- * Also thrown when decompression fails after the integrity hash
686
- * passed — that's a producer bug (the wrong algorithm byte was
687
- * written) but it surfaces with the same error class because the
688
- * end result is "the body cannot be turned back into a dump."
689
- */
690
- declare class BundleIntegrityError extends NoydbError {
691
- constructor(message: string);
692
- }
693
- /**
694
- * Thrown by `readNoydbBundle` when the bundle carries
695
- * sealed per-user passphrases but no supplied `SealingKeyProvider`
696
- * has a `.id` (= `pid`) matching the sealed entry's `pid`.
697
- *
698
- * Carries the failing pid + the user id so the recipient can
699
- * surface an actionable prompt:
700
- *
701
- * ```
702
- * BundleSealMismatchError: bundle carries sealed passphrase for user "alice"
703
- * under provider "macos-keychain:com.acme.app/alice@acme.example",
704
- * but no registered provider matches that pid.
705
- * ```
706
- *
707
- * Three resolution paths the message names (per foundation §11.9.4):
708
- *
709
- * 1. Configure a provider matching the pid and retry import.
710
- * 2. Pass `attemptUnsealAcrossProviders: true` to try each
711
- * registered provider regardless of pid.
712
- * 3. Inspect without unsealing — pass no `sealingProviders` to
713
- * receive the sealed entries unmodified for offline analysis.
714
- */
715
- declare class BundleSealMismatchError extends NoydbError {
716
- readonly userId: string;
717
- readonly pid: string;
718
- constructor(userId: string, pid: string);
719
- }
720
- /**
721
- * Thrown when `vault.collection()` is called with a name that is
722
- * reserved for NOYDB internal use (any name starting with `_dict_`).
723
- *
724
- * Dictionary collections are accessed exclusively via
725
- * `vault.dictionary(name)` — attempting to open one as a regular
726
- * collection would bypass the dictionary invariants (ACL, rename
727
- * tracking, reserved-name policy).
728
- */
729
- declare class ReservedCollectionNameError extends NoydbError {
730
- /** The rejected collection name. */
731
- readonly collectionName: string;
732
- constructor(collectionName: string);
733
- }
734
- /**
735
- * Thrown by `DictionaryHandle.get()` and `DictionaryHandle.delete()` when
736
- * the requested key does not exist in the dictionary.
737
- *
738
- * Distinct from `NotFoundError` (which is for data records) so callers
739
- * can distinguish "data record missing" from "dictionary key missing"
740
- * without inspecting error messages.
741
- */
742
- declare class DictKeyMissingError extends NoydbError {
743
- /** The dictionary name. */
744
- readonly dictionaryName: string;
745
- /** The key that was not found. */
746
- readonly key: string;
747
- constructor(dictionaryName: string, key: string);
748
- }
749
- /**
750
- * Thrown by `DictionaryHandle.delete()` in strict mode when the key to
751
- * be deleted is still referenced by one or more records.
752
- *
753
- * The caller must either rename the key first (the only sanctioned
754
- * mass-mutation path) or pass `{ mode: 'warn' }` to skip the check
755
- * (development only).
756
- */
757
- declare class DictKeyInUseError extends NoydbError {
758
- /** The dictionary name. */
759
- readonly dictionaryName: string;
760
- /** The key that is still referenced. */
761
- readonly key: string;
762
- /** Name of the first collection found to reference this key. */
763
- readonly usedBy: string;
764
- /** Number of records in `usedBy` that reference this key. */
765
- readonly count: number;
766
- constructor(dictionaryName: string, key: string, usedBy: string, count: number);
767
- }
768
- /**
769
- * Thrown by `Collection.put()` when an `i18nText` field is missing one
770
- * or more required translations.
771
- *
772
- * The `missing` array names each locale code that was absent from the
773
- * field value. The `field` property names the field so callers can
774
- * render a field-level error message without parsing the string.
775
- */
776
- declare class MissingTranslationError extends NoydbError {
777
- /** The field name whose translation(s) are missing. */
778
- readonly field: string;
779
- /** Locale codes that were required but absent. */
780
- readonly missing: readonly string[];
781
- constructor(field: string, missing: readonly string[], message?: string);
782
- }
783
- /**
784
- * Thrown when reading an `i18nText` field without specifying a locale —
785
- * either at the call site (`get(id, { locale })`) or on the vault
786
- * (`openVault(name, { locale })`).
787
- *
788
- * Also thrown when `resolveI18nText()` exhausts the fallback chain and
789
- * no translation is available for the requested locale.
790
- *
791
- * The `field` property names the field that triggered the error so the
792
- * caller can surface it in the UI.
793
- */
794
- declare class LocaleNotSpecifiedError extends NoydbError {
795
- /** The field name that required a locale. */
796
- readonly field: string;
797
- constructor(field: string, message?: string);
798
- }
799
- /**
800
- * Thrown at write time when an `i18nText` slot's value contains
801
- * characters outside the script set allowed for that locale, and the
802
- * field's `onScriptViolation` policy is `'reject'` (the default).
803
- *
804
- * Distinct from {@link MissingTranslationError} (write-shape) and
805
- * {@link LocaleNotSpecifiedError} (read-hole) so callers can tell a
806
- * wrong-script value from a missing one.
807
- */
808
- declare class ScriptViolationError extends NoydbError {
809
- /** The field whose value violated its script constraint. */
810
- readonly field: string;
811
- /** The locale slot (e.g. `'en'`) that was checked. */
812
- readonly locale: string;
813
- /** The Unicode scripts allowed for this slot. */
814
- readonly expected: readonly string[];
815
- /** A short sample of the offending characters, for diagnostics. */
816
- readonly sample: string;
817
- constructor(field: string, locale: string, expected: readonly string[], sample: string, message?: string);
818
- }
819
- /**
820
- * Thrown when a collection has an `i18nText` field with
821
- * `autoTranslate: true` but no `plaintextTranslator` was configured
822
- * on `createNoydb()`.
823
- *
824
- * The error is raised at `put()` time (not at schema construction) so
825
- * the mis-configuration is surfaced by the first write rather than
826
- * silently at startup.
827
- */
828
- declare class TranslatorNotConfiguredError extends NoydbError {
829
- /** The field that requested auto-translation. */
830
- readonly field: string;
831
- /** The collection the put was targeting. */
832
- readonly collection: string;
833
- constructor(field: string, collection: string);
834
- }
835
- /**
836
- * Thrown when `Vault.load()` finds that a backup's hash chain
837
- * doesn't verify, or that its embedded `ledgerHead.hash` doesn't
838
- * match the chain head reconstructed from the loaded entries.
839
- *
840
- * Distinct from `BackupCorruptedError` so callers can choose to
841
- * recover from one but not the other (e.g., a corrupted JSON file is
842
- * unrecoverable; a chain mismatch might mean the backup is from an
843
- * incompatible noy-db version).
844
- */
845
- declare class BackupLedgerError extends NoydbError {
846
- /** First-broken-entry index, if known. */
847
- readonly divergedAt?: number;
848
- constructor(message: string, divergedAt?: number);
849
- }
850
- /**
851
- * Thrown when `Vault.load()` finds that the backup's data
852
- * collection content doesn't match the ledger's recorded
853
- * `payloadHash`es. This is the "envelope was tampered with after
854
- * dump" detection — the chain itself can be intact, but if any
855
- * encrypted record bytes were swapped, this check catches it.
856
- */
857
- declare class BackupCorruptedError extends NoydbError {
858
- /** The (collection, id) pair whose envelope failed the hash check. */
859
- readonly collection: string;
860
- readonly id: string;
861
- constructor(collection: string, id: string, message: string);
862
- }
863
- /**
864
- * Thrown by partition-extraction primitives when the
865
- * transitive-closure walk fails — e.g. the FK graph is deeper than
866
- * `maxDepth`, signalling a runaway or unexpectedly cyclic graph.
867
- */
868
- declare class PartitionExtractionError extends NoydbError {
869
- constructor(message: string);
870
- }
871
- /**
872
- * Thrown by `adoptPartition` when the transfer seal can't be
873
- * opened — a wrong/short transfer key (AES-GCM auth-tag failure) or a
874
- * malformed sealed payload.
875
- */
876
- declare class TransferSealError extends NoydbError {
877
- constructor(message: string);
878
- }
879
- /**
880
- * Thrown when an adoption-lifecycle precondition fails — re-adopting a
881
- * partition already consumed in this store, or owner-creation on a
882
- * vault that isn't in the adopted-unowned state.
883
- */
884
- declare class AdoptionStateError extends NoydbError {
885
- constructor(message: string);
886
- }
887
- /** Document-attestation failures: undeclared field-schema, non-owner issue, missing field, signer failure. */
888
- declare class AttestationError extends NoydbError {
889
- constructor(message: string);
890
- }
891
- /**
892
- * Thrown by `resolveSession()` when the session token's `expiresAt`
893
- * timestamp is in the past. The session key is also removed from the
894
- * in-memory store when this is thrown, so retrying with the same sessionId
895
- * will produce `SessionNotFoundError`.
896
- *
897
- * Separate from `SessionNotFoundError` so callers can distinguish between
898
- * "session is gone" (key store cleared, tab reloaded) and "session is
899
- * still in the store but has exceeded its lifetime" (idle timeout, absolute
900
- * timeout, policy-driven expiry). The remediation differs: expired sessions
901
- * should prompt a fresh unlock; not-found sessions may indicate a bug or a
902
- * cross-tab scenario where the session was never established.
903
- */
904
- declare class SessionExpiredError extends NoydbError {
905
- readonly sessionId: string;
906
- constructor(sessionId: string);
907
- }
908
- /**
909
- * Thrown by `resolveSession()` when the session key cannot be found in
910
- * the module-level store. This happens when:
911
- * - The session was explicitly revoked via `revokeSession()`.
912
- * - The JS context was reloaded (tab navigation, page refresh, worker restart).
913
- * - `Noydb.close()` was called (which calls `revokeAllSessions()`).
914
- * - The sessionId is wrong or was generated by a different JS context.
915
- *
916
- * The session token (if the caller holds it) is permanently useless after
917
- * this error — the key is gone and cannot be recovered.
918
- */
919
- declare class SessionNotFoundError extends NoydbError {
920
- readonly sessionId: string;
921
- constructor(sessionId: string);
922
- }
923
- /**
924
- * Thrown when a session policy blocks an operation — for example,
925
- * `requireReAuthFor: ['export']` is set and the caller attempts to
926
- * call `exportStream()` without re-authenticating for this session.
927
- *
928
- * The `operation` field names the specific operation that was blocked
929
- * (e.g. `'export'`, `'grant'`, `'rotate'`) so the caller can surface
930
- * a targeted prompt ("Please re-enter your passphrase to export data").
931
- */
932
- declare class SessionPolicyError extends NoydbError {
933
- readonly operation: string;
934
- constructor(operation: string, message?: string);
935
- }
936
- /**
937
- * Thrown when a `.join()` would exceed its configured row ceiling on
938
- * either side. The ceiling defaults to 50,000 per side and can be
939
- * overridden via the `{ maxRows }` option on `.join()`.
940
- *
941
- * Carries both row counts so the error message can show which side
942
- * tripped the limit (e.g. "left had 60,000 rows, right had 1,200,
943
- * max was 50,000"). The `side` field is machine-readable so test
944
- * code and devtools can match on it without regex-parsing the
945
- * message.
946
- *
947
- * The row ceiling exists because joins are bounded in-memory
948
- * operations over materialized record sets. Consumers whose
949
- * collections genuinely exceed the ceiling should track
950
- * (streaming joins over `scan()`) or filter the left side further
951
- * with `where()` / `limit()` before joining.
952
- */
953
- declare class JoinTooLargeError extends NoydbError {
954
- readonly leftRows: number;
955
- readonly rightRows: number;
956
- readonly maxRows: number;
957
- readonly side: 'left' | 'right';
958
- constructor(opts: {
959
- leftRows: number;
960
- rightRows: number;
961
- maxRows: number;
962
- side: 'left' | 'right';
963
- message: string;
964
- });
965
- }
966
- /**
967
- * Thrown by `.crossJoin()` when the cumulative cartesian product (or lateral
968
- * filtered count) exceeds the configured ceiling. Check before allocating.
969
- * Mirrors the pattern of `JoinTooLargeError` and the `.join()` row ceiling.
970
- *
971
- * @see CrossJoinClause.maxRows — per-clause override
972
- * @see DEFAULT_CROSS_JOIN_MAX_ROWS — package default (50_000)
973
- */
974
- declare class CrossJoinTooLargeError extends NoydbError {
975
- readonly target: string;
976
- readonly expected: number;
977
- readonly limit: number;
978
- constructor(opts: {
979
- target: string;
980
- expected: number;
981
- limit: number;
982
- });
983
- }
984
- /**
985
- * Thrown at cross-join execution time when the target collection is not
986
- * reachable from the current vault. The left collection is included in the
987
- * message for context.
988
- */
989
- declare class CrossJoinSourceUnknownError extends NoydbError {
990
- readonly target: string;
991
- readonly leftCollection: string;
992
- constructor(target: string, leftCollection: string);
993
- }
994
- /**
995
- * Thrown by `.join()` in strict `ref()` mode when a left-side record
996
- * points at a right-side id that does not exist in the target
997
- * collection.
998
- *
999
- * Distinct from `RefIntegrityError` so test code can pattern-match
1000
- * on the *read-time* dangling case without catching *write-time*
1001
- * integrity violations. Both indicate "ref points at nothing" but
1002
- * happen at different lifecycle phases and deserve different
1003
- * remediation in documentation: a RefIntegrityError on `put()`
1004
- * means the input is invalid; a DanglingReferenceError on `.join()`
1005
- * means stored data has drifted and `vault.checkIntegrity()`
1006
- * is the right tool to find the full set of orphans.
1007
- */
1008
- declare class DanglingReferenceError extends NoydbError {
1009
- readonly field: string;
1010
- readonly target: string;
1011
- readonly refId: string;
1012
- constructor(opts: {
1013
- field: string;
1014
- target: string;
1015
- refId: string;
1016
- message: string;
1017
- });
1018
- }
1019
- /**
1020
- * Thrown by {@link sanitizeFilename} when an input filename cannot be
1021
- * made safe — NUL byte, empty after normalization, missing
1022
- * `opaqueId` for the opaque profile, `..` segment, or a `maxBytes`
1023
- * cap too small to hold a single code point.
1024
- */
1025
- declare class FilenameSanitizationError extends NoydbError {
1026
- constructor(message: string);
1027
- }
1028
- /**
1029
- * Thrown when a write target resolves OUTSIDE the requested
1030
- * directory after sanitization — the canonical Zip-Slip class. The
1031
- * sanitizer's job is to strip path-traversal segments; this error
1032
- * is the defense-in-depth fallback at the FS write site.
1033
- */
1034
- declare class PathEscapeError extends NoydbError {
1035
- readonly attempted: string;
1036
- readonly targetDir: string;
1037
- constructor(opts: {
1038
- attempted: string;
1039
- targetDir: string;
1040
- });
1041
- }
1042
- /**
1043
- * Thrown at vault open if the derivation graph contains a cycle.
1044
- * `path` is the offending chain (e.g. `['a', 'b', 'c', 'a']`).
1045
- */
1046
- declare class DerivationCycleError extends NoydbError {
1047
- readonly path: readonly string[];
1048
- constructor(path: readonly string[]);
1049
- }
1050
- /**
1051
- * Thrown when a cascade of source → output → source → … exceeds the
1052
- * configured `maxDepth` (default 5).
1053
- */
1054
- declare class DerivationDepthError extends NoydbError {
1055
- readonly limit: number;
1056
- readonly attempted: number;
1057
- constructor(limit: number, attempted: number);
1058
- }
1059
- /**
1060
- * Thrown at registration if a `withDerivation` strategy references an
1061
- * output `collection` that isn't otherwise declared (no schema, no use
1062
- * elsewhere). Surfacing this early catches typos in collection names.
1063
- */
1064
- declare class DerivationOutputUnknownError extends NoydbError {
1065
- readonly collection: string;
1066
- constructor(collection: string);
1067
- }
1068
- /**
1069
- * Thrown when the user's `derive` function returns a value that doesn't
1070
- * match the declared output spec (e.g. wrong shape, wrong key set).
1071
- */
1072
- declare class DerivationOutputShapeError extends NoydbError {
1073
- readonly outputKey: string;
1074
- constructor(outputKey: string, detail: string);
1075
- }
1076
- /**
1077
- * Thrown by array-shape derivations when the `derive` function
1078
- * returns more rows than the output's `maxFanout` cap. The cap exists
1079
- * to keep dispatch cost bounded — without it a single source-row
1080
- * update could fan out to thousands of derived rows, dominating the
1081
- * write path.
1082
- *
1083
- * Defaults to `maxFanout: 64`. Raise on the output spec for
1084
- * carry-forward expansion cases (e.g. monthly rows across multi-year
1085
- * contracts).
1086
- */
1087
- declare class DerivationCapExceededError extends NoydbError {
1088
- readonly outputKey: string;
1089
- readonly returned: number;
1090
- readonly maxFanout: number;
1091
- constructor(outputKey: string, returned: number, maxFanout: number);
1092
- }
1093
- /**
1094
- * Thrown at vault open if the materialized-view graph contains a
1095
- * cycle. `path` is the offending chain (e.g. `['a-mv', 'b-mv', 'a-mv']`).
1096
- * Detected by the same shared DFS that catches `DerivationCycleError`;
1097
- * surfaces with a distinct error type so consumers can disambiguate.
1098
- */
1099
- declare class MaterializedViewCycleError extends NoydbError {
1100
- readonly path: readonly string[];
1101
- constructor(path: readonly string[]);
1102
- }
1103
- /**
1104
- * Thrown at MV registration if the query references a source
1105
- * collection that isn't declared on the vault. Surfacing this early
1106
- * catches typos in collection names.
1107
- */
1108
- declare class MaterializedViewSourceUnknownError extends NoydbError {
1109
- readonly mvName: string;
1110
- readonly collection: string;
1111
- constructor(mvName: string, collection: string);
1112
- }
1113
- /**
1114
- * Thrown by the MV executor when a refresh produces more rows than
1115
- * the configured ceiling. Default ceiling is 100k rows; override
1116
- * per-MV via `maxRows`. Mirrors `JoinTooLargeError` /
1117
- * `GroupCardinalityError` from the query DSL — the explosion is
1118
- * detected BEFORE writes hit the store, so the source-write
1119
- * transaction can roll back cleanly via strict-mode.
1120
- */
1121
- declare class MaterializedViewTooLargeError extends NoydbError {
1122
- readonly mvName: string;
1123
- readonly expected: number;
1124
- readonly limit: number;
1125
- constructor(mvName: string, expected: number, limit: number);
1126
- }
1127
- /**
1128
- * Thrown by `withMaterializedView()` at registration time when the
1129
- * strategy is structurally malformed. Distinct from
1130
- * `MaterializedViewSourceUnknownError` (the source list is well-formed
1131
- * but names a collection the vault doesn't know) and
1132
- * `MaterializedViewCycleError` (the source graph has a cycle): this
1133
- * error fires before either check, at the moment the spec is being
1134
- * normalized.
1135
- *
1136
- * Today the trigger cases are all about the `query` / `unionSources`
1137
- * dichotomy:
1138
- * - both `query` and `unionSources` were set (mutually exclusive),
1139
- * - neither `query` nor `unionSources` was set,
1140
- * - `unionSources` has fewer than 2 arms,
1141
- * - two arms in `unionSources` reference the same `collection`.
1142
- *
1143
- * The error message is prefixed with `[noy-db] withMaterializedView:`
1144
- * so it's grep-friendly in logs and looks consistent with the existing
1145
- * `ValidationError` messages from the same factory.
1146
- */
1147
- declare class MaterializedViewConfigError extends NoydbError {
1148
- constructor(message: string);
1149
- }
1150
- /**
1151
- * Thrown at vault open when a `withOverlayedView` declaration uses
1152
- * another virtual-overlay name as its `base`. Multi-overlay stacking
1153
- * is a v2 non-goal — the shallow expansion in
1154
- * `QueryDependencyAnalyzer` would truncate at the inner overlay
1155
- * name, leaving downstream MVs silently stale.
1156
- */
1157
- declare class OverlayBaseIsVirtualError extends NoydbError {
1158
- readonly overlayName: string;
1159
- readonly base: string;
1160
- constructor(overlayName: string, base: string);
1161
- }
1162
- /**
1163
- * Thrown at vault open when a `withOverlayedView`'s `overlay`
1164
- * references an unknown collection or an MV-owned collection. The
1165
- * overlay collection is user-writable; MV-owned collections aren't.
1166
- */
1167
- declare class OverlayCollectionUnavailableError extends NoydbError {
1168
- readonly overlayName: string;
1169
- readonly overlay: string;
1170
- constructor(overlayName: string, overlay: string);
1171
- }
1172
- /**
1173
- * Thrown at vault open when a `withOverlayedView`'s virtual `name`
1174
- * collides with an MV output or a concrete source collection.
1175
- */
1176
- declare class OverlayNameCollisionError extends NoydbError {
1177
- readonly overlayName: string;
1178
- constructor(overlayName: string);
1179
- }
1180
- /**
1181
- * Thrown by the virtual overlay's `put(id, record)` when the
1182
- * consumer-supplied `id` doesn't match `rowKey(record)`. Catches
1183
- * fat-finger separator typos that would otherwise silently produce
1184
- * orphaned overlay rows. Direct writes to the underlying overlay
1185
- * collection (bypass the virtual layer) skip this validation.
1186
- */
1187
- declare class OverlayIdMismatchError extends NoydbError {
1188
- readonly actual: string;
1189
- readonly expected: string;
1190
- constructor(actual: string, expected: string);
1191
- }
1192
- /**
1193
- * Thrown when a requested snapshot version does not exist in the
1194
- * snapshot store — either it was never created, was pruned by the
1195
- * retention policy, or was deleted manually.
1196
- *
1197
- * The `version` field carries the key that was looked up so callers
1198
- * can surface an actionable "snapshot X not found" message without
1199
- * parsing the error string.
1200
- */
1201
- declare class SnapshotNotFoundError extends NoydbError {
1202
- readonly version: string;
1203
- constructor(version: string);
1204
- }
1205
-
1206
- /**
1207
- * Foreign-key references — the soft-FK mechanism.
1208
- *
1209
- * A collection declares its references as metadata at construction
1210
- * time:
1211
- *
1212
- * ```ts
1213
- * import { ref } from '@noy-db/hub'
1214
- *
1215
- * const invoices = company.collection<Invoice>('invoices', {
1216
- * refs: {
1217
- * clientId: ref('clients'), // default: strict
1218
- * categoryId: ref('categories', 'warn'),
1219
- * parentId: ref('invoices', 'cascade'), // self-reference OK
1220
- * },
1221
- * })
1222
- * ```
1223
- *
1224
- * Three modes:
1225
- *
1226
- * - **strict** — the default. `put()` rejects records whose
1227
- * reference target doesn't exist, and `delete()` of the target
1228
- * rejects if any strict-referencing records still exist.
1229
- * Matches SQL's default FK semantics.
1230
- *
1231
- * - **warn** — both operations succeed unconditionally. Broken
1232
- * references surface only through
1233
- * `vault.checkIntegrity()`, which walks every collection
1234
- * and reports orphans. Use when you want soft validation for
1235
- * imports from messy sources.
1236
- *
1237
- * - **cascade** — `put()` is same as warn. `delete()` of the
1238
- * target deletes every referencing record. Cycles are detected
1239
- * and broken via an in-progress set, so mutual cascades
1240
- * terminate instead of recursing forever.
1241
- *
1242
- * Cross-vault refs are explicitly rejected: if the target
1243
- * name contains a `/`, `ref()` throws `RefScopeError`. Cross-
1244
- * vault refs need an auth story (multi-keyring reads) that
1245
- * doesn't ship — tracked for.
1246
- */
1247
-
1248
- /** The three enforcement modes. Default for new refs is `'strict'`. */
1249
- type RefMode = 'strict' | 'warn' | 'cascade';
1250
- /**
1251
- * Descriptor returned by `ref()`. Collections accept a
1252
- * `Record<string, RefDescriptor>` in their options. The key is the
1253
- * field name on the record (top-level only — dotted paths are out of
1254
- * scope), the value describes which target collection the
1255
- * field references and under what mode.
1256
- *
1257
- * The descriptor carries only plain data so it can be serialized,
1258
- * passed around, and introspected without any class machinery.
1259
- */
1260
- interface RefDescriptor {
1261
- readonly target: string;
1262
- readonly mode: RefMode;
1263
- }
1264
- /**
1265
- * Thrown when a strict reference is violated — either `put()` with a
1266
- * missing target id, or `delete()` of a target that still has
1267
- * strict-referencing records.
1268
- *
1269
- * Carries structured detail so UI code (and a potential future
1270
- * devtools panel) can render "client X cannot be deleted because
1271
- * invoices 1, 2, and 3 reference it" instead of a bare error string.
1272
- */
1273
- declare class RefIntegrityError extends NoydbError {
1274
- readonly collection: string;
1275
- readonly id: string;
1276
- readonly field: string;
1277
- readonly refTo: string;
1278
- readonly refId: string | null;
1279
- constructor(opts: {
1280
- collection: string;
1281
- id: string;
1282
- field: string;
1283
- refTo: string;
1284
- refId: string | null;
1285
- message: string;
1286
- });
1287
- }
1288
- /**
1289
- * Thrown when `ref()` is called with a target name that looks like
1290
- * a cross-vault reference (contains a `/`). Separate error
1291
- * class because the fix is different: RefIntegrityError means "data
1292
- * is wrong"; RefScopeError means "the ref declaration is wrong".
1293
- */
1294
- declare class RefScopeError extends NoydbError {
1295
- constructor(target: string);
1296
- }
1297
- /**
1298
- * Helper constructor. Thin wrapper around the object literal so user
1299
- * code reads like `ref('clients')` instead of `{ target: 'clients',
1300
- * mode: 'strict' }` — this is the only ergonomics reason it exists.
1301
- *
1302
- * Validates the target name eagerly so a misconfigured ref declaration
1303
- * fails at collection construction time, not at the first put.
1304
- */
1305
- declare function ref(target: string, mode?: RefMode): RefDescriptor;
1306
- /**
1307
- * Per-vault registry of reference declarations.
1308
- *
1309
- * The registry is populated by `Collection` constructors (which pass
1310
- * their `refs` option through the Vault) and consulted by the
1311
- * Vault on every `put` / `delete` and by `checkIntegrity`. A
1312
- * single instance lives on the Vault for its lifetime; there's
1313
- * no global state.
1314
- *
1315
- * The data structure is two parallel maps:
1316
- *
1317
- * - `outbound`: `collection → { field → RefDescriptor }` — what
1318
- * refs does `collection` declare? Used on put to check
1319
- * strict-target-exists and on checkIntegrity to walk each
1320
- * collection's outbound refs.
1321
- *
1322
- * - `inbound`: `target → Array<{ collection, field, mode }>` —
1323
- * which collections reference `target`? Used on delete to find
1324
- * the records that might be affected by cascade / strict.
1325
- *
1326
- * The two views are kept in sync by `register()` and never mutated
1327
- * otherwise — refs can't be unregistered at runtime in.
1328
- */
1329
- declare class RefRegistry {
1330
- private readonly outbound;
1331
- private readonly inbound;
1332
- /**
1333
- * Register the refs declared by a single collection. Idempotent in
1334
- * the happy path — calling twice with the same data is a no-op.
1335
- * Calling twice with DIFFERENT data throws, because silent
1336
- * overrides would be confusing ("I changed the ref and it doesn't
1337
- * update" vs "I declared the same collection twice with different
1338
- * refs and the second call won").
1339
- */
1340
- register(collection: string, refs: Record<string, RefDescriptor>): void;
1341
- /** Get the outbound refs declared by a collection (or `{}` if none). */
1342
- getOutbound(collection: string): Record<string, RefDescriptor>;
1343
- /** Get the inbound refs that target a given collection (or `[]`). */
1344
- getInbound(target: string): ReadonlyArray<{
1345
- collection: string;
1346
- field: string;
1347
- mode: RefMode;
1348
- }>;
1349
- /**
1350
- * Iterate every (collection → refs) pair that has at least one
1351
- * declared reference. Used by `checkIntegrity` to walk the full
1352
- * universe of outbound refs without needing to track collection
1353
- * names elsewhere.
1354
- */
1355
- entries(): Array<[string, Record<string, RefDescriptor>]>;
1356
- /** Clear the registry. Test-only escape hatch; never called from production code. */
1357
- clear(): void;
1358
- }
1359
- /**
1360
- * Shape of a single violation reported by `vault.checkIntegrity()`.
1361
- *
1362
- * `refId` is the value we saw in the referencing field — it's the
1363
- * ID we expected to find in `refTo`, but didn't. Left as `unknown`
1364
- * because records are loosely typed at the integrity-check layer.
1365
- */
1366
- interface RefViolation {
1367
- readonly collection: string;
1368
- readonly id: string;
1369
- readonly field: string;
1370
- readonly refTo: string;
1371
- readonly refId: unknown;
1372
- readonly mode: RefMode;
1373
- }
1374
-
1375
- /**
1376
- * Query DSL `.join()` — eager, single-FK, intra-vault joins.
1377
- *
1378
- * resolves a ref()-declared foreign key into an attached
1379
- * right-side record under an alias, using one of two planner paths
1380
- * selected automatically:
1381
- *
1382
- * - **nested-loop** — right-side source exposes `lookupById`, so
1383
- * each left row costs O(1). This is the common path for joins
1384
- * against a Collection, which backs `lookupById` with a Map
1385
- * lookup.
1386
- * - **hash** — right-side has only `snapshot()`. Build a
1387
- * `Map<id, record>` once, probe per left row. Same asymptotic
1388
- * cost for our collections, but the path exists as a fallback
1389
- * for custom QuerySource implementations and as an explicit
1390
- * test-only override via `{ strategy: 'hash' }`.
1391
- *
1392
- * Scope:
1393
- *
1394
- * - Equi-joins on declared `ref()` fields only. Joins on
1395
- * undeclared fields throw at plan time with an actionable error
1396
- * naming the field and collection.
1397
- * - Same-vault only. Cross-vault correlation goes
1398
- * through `queryAcross`; this is an architectural
1399
- * invariant, not a limitation we plan to lift.
1400
- * - Hard row ceiling via `JoinTooLargeError` — default 50k per
1401
- * side, override via `{ maxRows }`. Warns at 80% of the ceiling
1402
- * on the existing warn channel.
1403
- * - Three ref-mode behaviors on dangling refs:
1404
- * strict → `DanglingReferenceError`,
1405
- * warn → attach `null` with a one-shot warning,
1406
- * cascade → attach `null` silently (cascade is a delete-time
1407
- * mode; any dangling refs still present at read time are
1408
- * mid-flight cascades or orphans from earlier, not a DSL error).
1409
- *
1410
- * Partition-awareness seam:
1411
- *
1412
- * Every `JoinLeg` carries a `partitionScope` field that is always
1413
- * `'all'` in. The executor never reads this field.
1414
- * partition-aware joins will start populating it from `where()`
1415
- * predicates on the partition key without changing the planner's
1416
- * external shape — this is the whole reason it exists now.
1417
- *
1418
- * Joins stay OUT of the ledger: reads don't touch `_ledger/`,
1419
- * including joined reads.
1420
- */
1421
-
1422
- /** Planner strategy for a single join leg. Auto-selected unless overridden. */
1423
- type JoinStrategy = 'hash' | 'nested';
1424
- /** Default per-side row ceiling before `.join()` throws `JoinTooLargeError`. */
1425
- declare const DEFAULT_JOIN_MAX_ROWS = 50000;
1426
- /**
1427
- * Internal representation of a single join leg in the query plan.
1428
- *
1429
- * This is the primary place where constraint #1 is honored:
1430
- * every leg carries a `partitionScope` field that is always `'all'`
1431
- * in and is never read by the executor. partition-aware
1432
- * joins will start populating it from `where()` predicates on the
1433
- * partition key without changing the planner's external shape.
1434
- */
1435
- interface JoinLeg {
1436
- /** Field on the left-side record holding the foreign key value. */
1437
- readonly field: string;
1438
- /** Alias key under which the joined right-side record attaches. */
1439
- readonly as: string;
1440
- /** Target collection name, resolved from the `ref()` declaration. */
1441
- readonly target: string;
1442
- /** Ref mode controlling behavior on dangling refs at read time. */
1443
- readonly mode: RefMode;
1444
- /** Manual planner strategy override. `undefined` → auto-select. */
1445
- readonly strategy: JoinStrategy | undefined;
1446
- /** Per-side row ceiling override. `undefined` → DEFAULT_JOIN_MAX_ROWS. */
1447
- readonly maxRows: number | undefined;
1448
- /**
1449
- * Partition scope for future partition-aware joins. Always `'all'`
1450
- * today — the executor never reads this field. Future versions will
1451
- * populate it from `where()` predicates without breaking the
1452
- * planner's external shape. Do not remove even though it looks
1453
- * unused today — that's the whole point of having it.
1454
- */
1455
- readonly partitionScope: 'all' | readonly string[];
1456
- /**
1457
- * When `true`, this is a dictionary join. The executor
1458
- * resolves the left-field value against the dict snapshot and
1459
- * attaches `{ ...labels, key }` rather than a right-side record.
1460
- * `target` holds the dictionary name (not a collection name).
1461
- */
1462
- readonly isDictJoin?: true;
1463
- }
1464
- /**
1465
- * Minimal shape of a joinable right-side record source.
1466
- *
1467
- * Collections implement this structurally via their `QuerySource`;
1468
- * sources without `lookupById` force the hash-join fallback. Kept as
1469
- * a thin interface so tests can wire up plain-object sources without
1470
- * pulling in the full Collection class.
1471
- *
1472
- * The optional `subscribe` is used by `Query.live()` to merge
1473
- * right-side change streams into the live re-run trigger. Sources
1474
- * that omit `subscribe` still work for live joins — they just
1475
- * don't drive re-fires when their right side mutates. Collection
1476
- * implements `subscribe` by hooking into the existing per-
1477
- * vault event emitter.
1478
- */
1479
- interface JoinableSource {
1480
- snapshot(): readonly unknown[];
1481
- lookupById?(id: string): unknown;
1482
- /**
1483
- * Subscribe to mutations on this source. The callback fires
1484
- * AFTER the underlying record set has been updated. Returns an
1485
- * unsubscribe function. Optional — sources without this method
1486
- * cannot trigger live-join re-fires from their side.
1487
- */
1488
- subscribe?(cb: () => void): () => void;
1489
- }
1490
- /**
1491
- * Join resolution context attached to a `Query` when it's constructed
1492
- * from a `Collection`. Holds everything the `.join()` method needs to
1493
- * translate a field name into a target collection + ref mode, and
1494
- * everything the executor needs to read the right side.
1495
- *
1496
- * Kept as a structural interface so `Vault` can implement it
1497
- * without `Query` needing to import `Vault` (circular-import
1498
- * avoid). The Collection wires this up in its `query()` method using
1499
- * the `joinResolver` back-reference the Vault passes in.
1500
- */
1501
- interface JoinContext {
1502
- /** Name of the left-side (owning) collection. */
1503
- readonly leftCollection: string;
1504
- /** Look up a `RefDescriptor` by field name on the left collection. */
1505
- resolveRef(field: string): RefDescriptor | null;
1506
- /** Resolve a right-side source by target collection name. */
1507
- resolveSource(collectionName: string): JoinableSource | null;
1508
- /**
1509
- * Resolve a dictKey join source. Returns a `JoinableSource`
1510
- * whose snapshot exposes `{ key, ...labels }` records, keyed by the
1511
- * stable dictionary key. `null` when the field is not a dictKey.
1512
- *
1513
- * The source is built from the compartment's in-memory dictionary
1514
- * snapshot — same data as `DictionaryHandle.list()`, O(1) per lookup.
1515
- */
1516
- resolveDictSource?(field: string): JoinableSource | null;
1517
- }
1518
- /**
1519
- * Apply every join leg in the plan against a base set of left-side
1520
- * rows. Called by the query executor after `where` / `orderBy` /
1521
- * `offset` / `limit` have narrowed the left set.
1522
- *
1523
- * Each leg attaches a `leg.as` field to every row. Returns a new
1524
- * array of plain objects — the original left rows are not mutated
1525
- * (structural sharing is fine for the inner fields, but the
1526
- * top-level object is a fresh clone so consumers can further mutate
1527
- * safely).
1528
- *
1529
- * **Ordering:** joins run AFTER orderBy / limit / offset in v1.
1530
- * This keeps the planner simple and means queries like "top 10
1531
- * invoices with client" sort and paginate the left side first, then
1532
- * join. Sorting *by* a joined field is out of scope for — users
1533
- * can post-sort the result array in userland or wait for
1534
- * (multi-FK chaining) which can be layered on top.
1535
- *
1536
- * **Multi-FK chaining:** each leg's `maxRows` is enforced
1537
- * against the current left-row count independently. Because
1538
- * joins are equi-joins on the target's primary key (one-to-one or
1539
- * one-to-null), the left row count is constant across legs — no
1540
- * cartesian blowup. The per-leg left-side check is still necessary
1541
- * so that a later leg with a tighter ceiling correctly fires on a
1542
- * query like `.join('a', { maxRows: 100_000 }).join('b', { maxRows: 50 })`,
1543
- * which should throw on the second leg if the left set exceeds 50.
1544
- */
1545
- declare function applyJoins(rows: readonly unknown[], joins: readonly JoinLeg[], context: JoinContext): unknown[];
1546
- /**
1547
- * Test-only: reset the join warning deduplication state between
1548
- * tests. Production code never calls this — the dedup state is
1549
- * intentionally process-scoped so a noisy query doesn't spam the
1550
- * console once per component render.
1551
- */
1552
- declare function resetJoinWarnings(): void;
1553
-
1554
- /**
1555
- * Reactive query primitive — `query.live()`.
1556
- *
1557
- * produces a `LiveQuery<T>` that re-runs the query and
1558
- * updates its `value` whenever any source feeding it (the left
1559
- * collection AND every right-side collection a join leg points at)
1560
- * mutates.
1561
- *
1562
- * Framework-agnostic by design. The Vue layer wraps a `LiveQuery`
1563
- * in a Vue `Ref<T[]>` by subscribing once and copying `value` into
1564
- * the ref on every notification. React/Solid/Svelte adapters do the
1565
- * same with their own primitives. Core never depends on a UI
1566
- * framework.
1567
- *
1568
- * **Error semantics.** A `.live()` query may throw at re-run time —
1569
- * a strict-mode `DanglingReferenceError` is the most common case
1570
- * (a right-side record was deleted out-of-band, leaving a left
1571
- * row's FK pointing at nothing). When the re-run throws, the
1572
- * `LiveQuery` catches the error and stores it in the `error`
1573
- * field; it does NOT propagate the throw out of the source's
1574
- * change handler, because doing so would tear down whatever
1575
- * upstream emitter is dispatching. Listeners check `error` after
1576
- * each notification and render an error state in the UI.
1577
- *
1578
- * **Dedup of right-side subscriptions.** A multi-FK chain that
1579
- * joins the same target twice (e.g.
1580
- * `.join('billingClientId').join('shippingClientId')`, both
1581
- * pointing at `clients`) only subscribes to that target once. We
1582
- * dedup by target collection name, on the assumption that
1583
- * `resolveSource(name)` returns a single subscribable source per
1584
- * vault + name. Vault's `resolveSource` reads from
1585
- * `collectionCache` so this assumption holds.
1586
- *
1587
- * **What .live() does NOT do in v1:**
1588
- * - No granular delta updates — the whole query re-runs on every
1589
- * change. Granular delta tracking is a v2 optimization once
1590
- * the API is stable.
1591
- * - No batching of bursty changes — one event in, one re-run
1592
- * out. Batching with microtask coalescing is a v2 enhancement.
1593
- * - No async notifications — every notification is synchronous
1594
- * within the source's change handler.
1595
- * - No re-planning under live mutations — the planner picks once
1596
- * at subscription time and reuses the same plan for every
1597
- * re-run.
1598
- */
1599
- /**
1600
- * The reactive primitive returned by `Query.live()`.
1601
- *
1602
- * Listeners can read the current `value` snapshot at any time and
1603
- * subscribe to changes via `.subscribe(cb)`. The `error` field
1604
- * carries the most recent re-run error, if any — read it after
1605
- * each notification to render error state.
1606
- *
1607
- * Always call `stop()` when the live query is no longer needed.
1608
- * Without it, the upstream change-stream subscriptions stay live
1609
- * forever and the query keeps re-running on every mutation.
1610
- */
1611
- interface LiveQuery<T> {
1612
- /**
1613
- * Current snapshot of the query result. Updated in place on
1614
- * every upstream change. The reference returned is the same
1615
- * `readonly T[]` array — consumers that want change detection by
1616
- * reference should copy: `const arr = [...live.value]`.
1617
- */
1618
- readonly value: readonly T[];
1619
- /**
1620
- * Most recent re-run error, or `null` on success. Set when the
1621
- * executor throws (e.g. `DanglingReferenceError` in strict mode
1622
- * after a right-side delete). Cleared on the next successful
1623
- * re-run.
1624
- */
1625
- readonly error: Error | null;
1626
- /**
1627
- * Register a notification callback. Fires AFTER `value` and
1628
- * `error` have been updated for a given upstream change.
1629
- * Returns an unsubscribe function.
1630
- *
1631
- * The first call to `subscribe` does NOT fire the callback
1632
- * immediately — call sites that want the initial value should
1633
- * read `live.value` directly before subscribing.
1634
- */
1635
- subscribe(cb: () => void): () => void;
1636
- /**
1637
- * Tear down every upstream subscription and clear the listener
1638
- * set. Idempotent — calling twice is safe. After `stop()`, the
1639
- * query no longer re-runs and `subscribe()` becomes a no-op
1640
- * (the returned unsubscribe is still callable and is also a
1641
- * no-op).
1642
- */
1643
- stop(): void;
1644
- }
1645
- /**
1646
- * Internal subscription handle for an upstream source — left or
1647
- * right side. The contract is just `subscribe(cb): unsubscribe`,
1648
- * matching the existing `QuerySource.subscribe` and the new
1649
- * `JoinableSource.subscribe` (added in ).
1650
- */
1651
- interface LiveUpstream {
1652
- subscribe(cb: () => void): () => void;
1653
- }
1654
- /**
1655
- * Build a LiveQuery from a `recompute` callback (typically the
1656
- * Query's bound `toArray`) and a list of upstream sources to
1657
- * subscribe to.
1658
- *
1659
- * The recompute fires once synchronously to populate the initial
1660
- * value, then re-fires every time any upstream notifies. Errors
1661
- * thrown by recompute are caught and stored in `error` instead of
1662
- * propagating — see the file docstring for the rationale.
1663
- */
1664
- declare function buildLiveQuery<T>(recompute: () => T[], upstreams: readonly LiveUpstream[]): LiveQuery<T>;
1665
-
1666
- /**
1667
- * Chainable, immutable query builder.
1668
- *
1669
- * Each builder operation returns a NEW Query — the underlying plan is never
1670
- * mutated. This makes plans safe to share, cache, and serialize.
1671
- */
1672
-
1673
- interface OrderBy {
1674
- readonly field: string;
1675
- readonly direction: 'asc' | 'desc';
1676
- }
1677
- /**
1678
- * A complete query plan: zero-or-more clauses, optional ordering, pagination,
1679
- * and optional joins.
1680
- *
1681
- * Plans are JSON-serializable as long as no FilterClause is present and no
1682
- * join leg carries a manual `strategy` override (JoinLeg itself is plain
1683
- * data, so it serializes cleanly).
1684
- *
1685
- * Plans are intentionally NOT parametric on T — see `predicate.ts` FilterClause
1686
- * for the variance reasoning. The public `Query<T>` API attaches the type tag.
1687
- */
1688
- interface QueryPlan {
1689
- readonly clauses: readonly Clause[];
1690
- readonly orderBy: readonly OrderBy[];
1691
- readonly limit: number | undefined;
1692
- readonly offset: number;
1693
- /**
1694
- * Zero-or-more join legs to apply after where/orderBy/limit/offset.
1695
- * Each leg attaches a resolved right-side record (or null) under its
1696
- * alias. See `query/join.ts` for the full semantics.
1697
- */
1698
- readonly joins: readonly JoinLeg[];
1699
- }
1700
- /** Default row ceiling for cross-join expansion. Matches JoinTooLargeError's ceiling. */
1701
- declare const DEFAULT_CROSS_JOIN_MAX_ROWS = 50000;
1702
- /**
1703
- * Source of records that a query executes against.
1704
- *
1705
- * The interface is non-parametric to keep variance friendly: callers cast
1706
- * their typed source (e.g. `QuerySource<Invoice>`) into this opaque shape.
1707
- *
1708
- * `getIndexes` and `lookupById` are optional fast-path hooks. When both are
1709
- * present and a where clause matches an indexed field, the executor uses
1710
- * the index to skip a linear scan. Sources without these methods (or with
1711
- * `getIndexes` returning `null`) always fall back to a linear scan.
1712
- */
1713
- interface QuerySource<T> {
1714
- /** Snapshot of all current records. The query never mutates this array. */
1715
- snapshot(): readonly T[];
1716
- /** Subscribe to mutations; returns an unsubscribe function. */
1717
- subscribe?(cb: () => void): () => void;
1718
- /** Index store for the indexed-fast-path. Optional. */
1719
- getIndexes?(): CollectionIndexes | null;
1720
- /** O(1) record lookup by id, used to materialize index hits. */
1721
- lookupById?(id: string): T | undefined;
1722
- }
1723
- /**
1724
- * The chainable builder. All methods return a new Query — the original
1725
- * remains unchanged. Terminal methods (`toArray`, `first`, `count`,
1726
- * `subscribe`) execute the plan against the source.
1727
- *
1728
- * Type parameter T flows through the public API for ergonomics, but the
1729
- * internal storage uses `unknown` so Collection<T> stays covariant.
1730
- *
1731
- * The optional `joinContext` is attached when the Query is constructed
1732
- * via `Collection.query()` (Collection passes in a context built from
1733
- * the Vault's join resolver). A Query constructed via `new Query`
1734
- * directly — e.g. from tests with a plain-object source — has no
1735
- * joinContext, and calling `.join()` on it throws with an actionable
1736
- * error. See `query/join.ts` for the full design.
1737
- */
1738
- /**
1739
- * Declared deterministic predicate. Carries the consumer's
1740
- * stable `hash` (for function-body identity), the function itself,
1741
- * and is keyed by name when registered on a `Query<T>` via
1742
- * `_withPredicates()`.
1743
- */
1744
- interface DeclaredPredicate {
1745
- hash: string;
1746
- fn: (record: unknown, ctx?: unknown) => boolean;
1747
- }
1748
- declare class Query<T> {
1749
- private readonly source;
1750
- private readonly plan;
1751
- private readonly joinContext;
1752
- private readonly aggregateStrategy;
1753
- private readonly predicates;
1754
- constructor(source: QuerySource<T>, plan?: QueryPlan, joinContext?: JoinContext, aggregateStrategy?: AggregateStrategy, predicates?: ReadonlyMap<string, DeclaredPredicate>);
1755
- /**
1756
- * @internal — accessor for the materialized-view dependency
1757
- * analyzer. Not part of the public API; consumers should use the
1758
- * builder methods, not inspect the plan directly.
1759
- */
1760
- _plan(): QueryPlan;
1761
- /**
1762
- * @internal — accessor for the materialized-view dependency
1763
- * analyzer. Returns the join resolution context (or `undefined` for
1764
- * queries constructed without a Collection backing).
1765
- */
1766
- _joinContext(): JoinContext | undefined;
1767
- /**
1768
- * @internal — clone this Query with a declared-predicate map
1769
- * attached. Used by the materialized-view registry to enable
1770
- * `.wherePredicate(name, ctx?)` for the MV's query callback.
1771
- * Consumers don't call this directly.
1772
- */
1773
- _withPredicates(predicates: ReadonlyMap<string, DeclaredPredicate>): Query<T>;
1774
- /**
1775
- * Filter by a registered deterministic predicate. Requires
1776
- * the Query to have been augmented with a predicates map (typically
1777
- * via the materialized-view registry — bare Queries constructed
1778
- * outside an MV throw on `.wherePredicate()`).
1779
- *
1780
- * `ctx` is an optional opaque value passed verbatim to the predicate
1781
- * function. Both `predicateHash` (from the registration) and a
1782
- * canonical-JSON hash of `ctx` fold into the MV's `queryHash`, so
1783
- * either changing forces refresh on next visit.
1784
- */
1785
- wherePredicate(name: string, ctx?: unknown): Query<T>;
1786
- /** Add a field comparison. Multiple where() calls are AND-combined. */
1787
- where(field: string, op: Operator, value: unknown): Query<T>;
1788
- /**
1789
- * Logical OR group. Pass a callback that builds a sub-query.
1790
- * Each clause inside the callback is OR-combined; the group itself
1791
- * joins the parent plan with AND.
1792
- */
1793
- or(builder: (q: Query<T>) => Query<T>): Query<T>;
1794
- /**
1795
- * Logical AND group. Same shape as `or()` but every clause inside the group
1796
- * must match. Useful for explicit grouping inside a larger OR.
1797
- */
1798
- and(builder: (q: Query<T>) => Query<T>): Query<T>;
1799
- /** Escape hatch: add an arbitrary predicate function. Not serializable. */
1800
- filter(fn: (record: T) => boolean): Query<T>;
1801
- /** Sort by a field. Subsequent calls are tie-breakers. */
1802
- orderBy(field: string, direction?: 'asc' | 'desc'): Query<T>;
1803
- /** Cap the result size. */
1804
- limit(n: number): Query<T>;
1805
- /** Skip the first N matching records (after ordering). */
1806
- offset(n: number): Query<T>;
1807
- /**
1808
- * Resolve a `ref()`-declared foreign key and attach the right-side
1809
- * record under `opts.as`. — eager, single-FK, intra-
1810
- * vault joins.
1811
- *
1812
- * ```ts
1813
- * const rows = invoices.query()
1814
- * .where('status', '==', 'open')
1815
- * .join('clientId', { as: 'client' })
1816
- * .toArray()
1817
- * // → [{ id, amount, client: { id, name, ... } }, ...]
1818
- * ```
1819
- *
1820
- * Preconditions:
1821
- * - The Query must have a `joinContext` (constructed via
1822
- * `Collection.query()`, not `new Query`).
1823
- * - `field` must have a matching `refs: { [field]: ref('<target>') }`
1824
- * declaration on the left collection.
1825
- * - The target collection must be reachable via the vault
1826
- * (either currently open or openable on demand).
1827
- *
1828
- * Strategy:
1829
- * - Nested-loop against `lookupById` when the target source
1830
- * provides it (the common path for Collection targets).
1831
- * - Hash join otherwise, or when `{ strategy: 'hash' }` is
1832
- * explicitly passed for test purposes.
1833
- *
1834
- * Ref-mode semantics on dangling refs (left record has a non-null
1835
- * FK value pointing at a right-side id that doesn't exist):
1836
- * - `strict` → throws `DanglingReferenceError` with the full
1837
- * field / target / refId context.
1838
- * - `warn` → attaches `null` and emits a one-shot warning per
1839
- * unique dangling pair.
1840
- * - `cascade` → attaches `null` silently. Cascade is a
1841
- * delete-time mode; dangling refs visible at read time are
1842
- * either mid-flight cascades or pre-existing orphans, not a
1843
- * DSL-level error.
1844
- *
1845
- * A left-side record whose FK field is `null` / `undefined` is NOT
1846
- * a dangling ref — it's "no reference at all", always allowed
1847
- * regardless of mode.
1848
- *
1849
- * The return type widens `T` with `Record<As, R | null>`. The `R`
1850
- * parameter is optional — supply it explicitly for type-checked
1851
- * access to the joined fields:
1852
- *
1853
- * ```ts
1854
- * invoices.query().join<'client', Client>('clientId', { as: 'client' })
1855
- * // ^^^^^^^^^^^^^^^^^^^ alias literal + right-side type
1856
- * ```
1857
- *
1858
- * Without the generic, the joined field is typed as `unknown`, which
1859
- * still works but requires a cast to access its properties.
1860
- *
1861
- * Joins stay intra-vault by construction — cross-vault
1862
- * correlation goes through `Noydb.queryAcross`, not
1863
- * `.join()`.
1864
- */
1865
- join<As extends string, R = unknown>(field: string, opts: {
1866
- as: As;
1867
- strategy?: JoinStrategy;
1868
- maxRows?: number;
1869
- }): Query<T & Record<As, R | null>>;
1870
- /**
1871
- * Cartesian-product cross-join against `target` collection. Each result row
1872
- * carries the original `T` fields plus `result[as]` populated from every
1873
- * right-side row (or the filtered subset when `on:` is supplied).
1874
- *
1875
- * **Order matters:** `.where().crossJoin()` filters BEFORE expanding (cheaper);
1876
- * `.crossJoin().where('alias.field', ...)` filters AFTER (required when the
1877
- * where clause references the aliased fields).
1878
- *
1879
- * **Cost ceiling:** `CrossJoinTooLargeError` fires before allocation when
1880
- * `leftRows × rightRows` (or the cumulative lateral count) exceeds the limit.
1881
- * Default: 50,000 rows. Override per-clause with `{ maxRows: N }`.
1882
- *
1883
- * **`on:` shapes:**
1884
- * - `on: (left) => TTarget[]` — subset form (most efficient)
1885
- * - `on: (left) => (right) => boolean` — predicate form
1886
- * - `on: { predicate: 'name' }` — MV-safe, hash-tracked form
1887
- * (requires the Query to have been augmented via `_withPredicates`)
1888
- *
1889
- * Requires a JoinContext (constructed via `collection.query()`).
1890
- */
1891
- crossJoin<TTarget = unknown, As extends string = string>(target: string, opts: {
1892
- as: As;
1893
- on?: ((left: T) => unknown[] | ((right: TTarget) => boolean)) | {
1894
- readonly predicate: string;
1895
- };
1896
- maxRows?: number;
1897
- }): Query<T & {
1898
- [K in As]: TTarget;
1899
- }>;
1900
- /**
1901
- * Execute the plan and return the matching records. When the plan
1902
- * carries any join legs, they are applied after `where` / `orderBy`
1903
- * / `limit` / `offset` narrow the left set. See the `.join()` doc
1904
- * for the ordering rationale.
1905
- */
1906
- toArray(): T[];
1907
- /** Return the first matching record, or null. Joins are applied. */
1908
- first(): T | null;
1909
- /**
1910
- * Return the number of matching records (after where/filter,
1911
- * before limit). **Joins are NOT applied** — count() reports the
1912
- * left-side cardinality, because joins in are projection-only
1913
- * (they attach an aliased field; they never filter). Running joins
1914
- * here just to discard the aliases would be wasteful, and in strict
1915
- * mode it could throw `DanglingReferenceError` for a call whose
1916
- * intent is purely to count.
1917
- */
1918
- count(): number;
1919
- /**
1920
- * Reduce the matching records through a named set of reducers.
1921
- * the aggregation terminal.
1922
- *
1923
- * ```ts
1924
- * const { total, n, avgAmount } = invoices.query()
1925
- * .where('status', '==', 'open')
1926
- * .aggregate({
1927
- * total: sum('amount'),
1928
- * n: count(),
1929
- * avgAmount: avg('amount'),
1930
- * })
1931
- * .run()
1932
- * ```
1933
- *
1934
- * Returns an `Aggregation<R>` wrapper with two terminals:
1935
- * - `.run(): R` — synchronous one-shot reduction
1936
- * - `.live(): LiveAggregation<R>` — reactive primitive that
1937
- * re-runs the reduction whenever the source notifies of a
1938
- * change. Always call `live.stop()` when finished.
1939
- *
1940
- * The reducer spec is bound here once and reused by both
1941
- * terminals — this is why `.aggregate()` returns a wrapper instead
1942
- * of being a direct terminal. Consumers who only need the static
1943
- * value read `.run()`; consumers wiring a reactive UI read
1944
- * `.live()`.
1945
- *
1946
- * Joins are intentionally NOT applied to aggregations in —
1947
- * the same logic as `.count()`. Joins in are projection-only
1948
- * (they attach an aliased field and never filter), so running
1949
- * them just to throw the aliases away would be wasteful. If you
1950
- * need a reducer that reads a joined field, open an issue —
1951
- * aggregations-across-joins is explicitly out of scope for v1.
1952
- *
1953
- * Every reducer factory accepts an optional `{ seed }` parameter
1954
- * that is plumbed through the protocol but unused by the
1955
- * executor — that's constraint #2. When partition-aware
1956
- * aggregation lands, the seed will carry running state across
1957
- * partition boundaries without an API break.
1958
- */
1959
- aggregate<Spec extends AggregateSpec>(spec: Spec): Aggregation<AggregateResult<Spec>>;
1960
- /**
1961
- * Partition matching records into buckets keyed by a field, then
1962
- * terminate with `.aggregate(spec)` to compute per-bucket
1963
- * reducers..
1964
- *
1965
- * ```ts
1966
- * const byClient = invoices.query()
1967
- * .where('status', '==', 'open')
1968
- * .groupBy('clientId')
1969
- * .aggregate({ total: sum('amount'), n: count() })
1970
- * .run()
1971
- * // → [ { clientId: 'c1', total: 5250, n: 3 }, … ]
1972
- * ```
1973
- *
1974
- * Result rows carry the group key value under the grouping field
1975
- * name plus every reducer output from the spec. Buckets are
1976
- * emitted in first-seen order — consumers who want a specific
1977
- * ordering should `.sort()` downstream.
1978
- *
1979
- * **Cardinality caps:** a one-shot warning fires at 10_000
1980
- * distinct groups; `GroupCardinalityError` throws at 100_000.
1981
- * Grouping on a high-uniqueness field like `id` or `createdAt` is
1982
- * almost always a query mistake — the error message names the
1983
- * field and observed cardinality and suggests narrowing with
1984
- * `.where()` first.
1985
- *
1986
- * **Null / undefined keys:** records with a missing or explicitly
1987
- * `null` group field get their own buckets. `Map`-based
1988
- * partitioning distinguishes `undefined` from `null`, so the two
1989
- * cases do NOT merge. Consumers who want them merged should
1990
- * coalesce upstream with `.filter()`.
1991
- *
1992
- * **Joins are not applied** — same rationale as `.count()` and
1993
- * `.aggregate()`. Joined fields in are projection-only, so
1994
- * running a join inside a grouping pipeline would be wasteful and
1995
- * could trigger `DanglingReferenceError` in strict mode for a
1996
- * call whose intent is purely to bucket-and-reduce. Grouping by
1997
- * a joined field is explicitly out of scope for — file an
1998
- * issue if a real consumer needs it.
1999
- *
2000
- * **Filter clauses (`.filter(fn)`):** grouped queries still
2001
- * support filter clauses in the underlying plan — they run in
2002
- * the same candidate/filter pipeline that `.aggregate()` uses.
2003
- * The performance caveat is the same: filter clauses cost O(N)
2004
- * per record and can't be index-accelerated.
2005
- */
2006
- groupBy<F extends string>(field: F): GroupedQuery<T, F>;
2007
- groupBy<F extends readonly [string, string, ...string[]]>(...fields: F): GroupedQueryN<T, F>;
2008
- /**
2009
- * Re-run the query whenever the source notifies of changes.
2010
- * Returns an unsubscribe function. The callback receives the latest result.
2011
- * Throws if the source does not support subscriptions.
2012
- *
2013
- * **For joined queries, prefer `.live()`** — `subscribe()`
2014
- * only re-fires on LEFT-side changes, so joined data can be
2015
- * stale if the right side mutates between emissions. `.live()`
2016
- * merges change streams from every join target.
2017
- */
2018
- subscribe(cb: (result: T[]) => void): () => void;
2019
- /**
2020
- * Reactive terminal — returns a `LiveQuery<T>` that re-runs the
2021
- * query and updates its `value` whenever any source feeding it
2022
- * mutates..
2023
- *
2024
- * For non-joined queries, `.live()` is a convenience over the
2025
- * existing `.subscribe()` callback shape: a hand-rolled reactive
2026
- * primitive with `value` / `error` fields and a `subscribe(cb)`
2027
- * notification channel. Frame-agnostic — Vue / React / Solid
2028
- * adapters wrap it in their own primitive.
2029
- *
2030
- * For joined queries, `.live()` additionally subscribes to every
2031
- * join target's change stream. Mutations on a right-side
2032
- * collection (insert / update / delete of a client referenced by
2033
- * an invoice) re-fire the live query and re-evaluate every
2034
- * dependent left row. Right-side targets are deduped by
2035
- * collection name, so a chain that joins the same target twice
2036
- * (e.g. billing client + shipping client → both 'clients') only
2037
- * subscribes once.
2038
- *
2039
- * **Ref-mode behavior on right-side disappearance** — matches the
2040
- * eager `.toArray()` contract from :
2041
- * - `strict` → re-run throws `DanglingReferenceError`. The
2042
- * LiveQuery catches the throw, stores it in `live.error`, and
2043
- * notifies listeners (the throw does NOT propagate out of
2044
- * the source's change handler — that would tear down the
2045
- * emitter). Consumers check `live.error` after each
2046
- * notification and render an error state in the UI.
2047
- * - `warn` → joined value flips to `null`; the existing
2048
- * warn-channel deduplication keeps repeated re-runs from
2049
- * spamming the console.
2050
- * - `cascade` → no special handling needed; the cascade-
2051
- * delete mechanism propagates the right-side delete into the
2052
- * left collection on the next tick, and the live query
2053
- * naturally re-fires with the orphaned left rows gone.
2054
- *
2055
- * Always call `live.stop()` when finished — it tears down every
2056
- * upstream subscription. The Vue layer's `onUnmounted` hook
2057
- * should call `stop()` automatically; raw consumers must do it
2058
- * themselves.
2059
- *
2060
- * **Limitations:**
2061
- * - No granular delta updates — the whole query re-runs on
2062
- * every change.
2063
- * - No microtask batching — bursty changes produce one re-run
2064
- * per change.
2065
- * - No re-planning under live mutations — the planner picks
2066
- * once at subscription time and reuses the same plan.
2067
- * - Streaming live joins are deferred.
2068
- */
2069
- live(): LiveQuery<T>;
2070
- /**
2071
- * Return the plan as a JSON-friendly object. FilterClause entries are
2072
- * stripped (their `fn` cannot be serialized) and replaced with
2073
- * { type: 'filter', fn: '[function]' } so devtools can still see them.
2074
- */
2075
- toPlan(): unknown;
2076
- }
2077
- /**
2078
- * Execute a plan against a snapshot of records.
2079
- * Pure function — same input, same output, no side effects.
2080
- *
2081
- * Records are typed as `unknown` because plans are non-parametric; callers
2082
- * cast the return type at the API surface (see `Query.toArray()`).
2083
- */
2084
- declare function executePlan(records: readonly unknown[], plan: QueryPlan): unknown[];
2085
-
2086
- /**
2087
- * Streaming scan builder with filter + aggregate support.
2088
- *
2089
- * `Collection.scan()` now returns a `ScanBuilder<T>` that
2090
- * implements `AsyncIterable<T>` (for existing `for await … of`
2091
- * consumers) AND exposes chainable `.where()` / `.filter()` clauses
2092
- * plus a `.aggregate(spec)` async terminal that reduces the scan
2093
- * stream through the same reducer protocol as `Query.aggregate()`
2094
- *.
2095
- *
2096
- * **Memory model:** O(reducers), not O(records). The aggregate
2097
- * terminal initializes one state per reducer, iterates through the
2098
- * scan one record at a time via `for await`, applies every reducer's
2099
- * `step` per record, and never collects the stream into an array.
2100
- * This is what makes `scan().aggregate()` suitable for collections
2101
- * that don't fit in memory — the bound is a code-level invariant
2102
- * visible in the function body, not a runtime assertion.
2103
- *
2104
- * **Paginated iteration:** the builder holds a `pageProvider`
2105
- * closure that maps `(cursor, limit) → Promise<page>`, plumbed by
2106
- * `Collection.scan()` to `collection.listPage(...)`. The page
2107
- * iterator walks cursors forward until exhaustion, same as the
2108
- * previous async-generator `scan()` did.
2109
- *
2110
- * **Backward compatibility:** existing `for await (const rec of
2111
- * collection.scan()) { … }` code continues to work because
2112
- * `ScanBuilder` implements `[Symbol.asyncIterator]`. The previous
2113
- * signature returned an `AsyncIterableIterator<T>` (which has both
2114
- * `[Symbol.asyncIterator]` and `.next()`). We verified at grep time
2115
- * that no call sites use `.next()` on the scan result directly, so
2116
- * the narrowed interface is safe.
2117
- *
2118
- * **Immutability:** each `.where()` / `.filter()` call returns a
2119
- * fresh builder sharing the same page provider and page size. This
2120
- * lets a base scan be reused for multiple parallel aggregations:
2121
- *
2122
- * ```ts
2123
- * const scan = invoices.scan()
2124
- * const [open, paid] = await Promise.all([
2125
- * scan.where('status', '==', 'open').aggregate({ n: count() }),
2126
- * scan.where('status', '==', 'paid').aggregate({ n: count() }),
2127
- * ])
2128
- * ```
2129
- *
2130
- * Note that each aggregation pays a full scan — there's no shared
2131
- * iteration across the two. Multi-way aggregation in a single pass
2132
- * is out of scope; consumers who need it should build a compound spec
2133
- * and run a single `.aggregate({ openN, paidN })` at the DSL level.
2134
- *
2135
- * **Out of scope for (tracked separately):**
2136
- * - `scan().aggregate().live()` — unbounded scan + change-stream
2137
- * reconciliation is a design problem, not just a code one
2138
- * - `scan().groupBy().aggregate()` — high-cardinality grouping on
2139
- * huge collections would re-introduce the O(groups) memory
2140
- * problem that aggregate fixes
2141
- * - Parallel scan across pages — race-safe page cursor contracts
2142
- * are not in the adapter API yet
2143
- * - `scan().join(...)` — tracked under (streaming join)
2144
- */
2145
-
2146
- /**
2147
- * Page provider — the Collection-shaped hook the builder calls to
2148
- * walk cursors forward. Kept as a structural interface so tests can
2149
- * wire up a synthetic provider without pulling in the full
2150
- * Collection class. Collection's `listPage` matches this shape
2151
- * exactly.
2152
- */
2153
- interface ScanPageProvider<T> {
2154
- listPage(opts: {
2155
- cursor?: string;
2156
- limit?: number;
2157
- }): Promise<{
2158
- items: T[];
2159
- nextCursor: string | null;
2160
- }>;
2161
- }
2162
- /**
2163
- * Chainable streaming scan. Implements `AsyncIterable<T>` for
2164
- * drop-in use with `for await … of`; adds `.where()` / `.filter()`
2165
- * chainable clauses and a `.aggregate(spec)` async terminal.
2166
- *
2167
- * The builder is immutable per operation — each chained call
2168
- * returns a fresh `ScanBuilder` sharing the same page provider and
2169
- * page size. The original builder is never mutated, so it's safe
2170
- * to reuse across multiple parallel consumers.
2171
- */
2172
- declare class ScanBuilder<T> implements AsyncIterable<T> {
2173
- private readonly pageProvider;
2174
- private readonly pageSize;
2175
- private readonly clauses;
2176
- /**
2177
- * Zero-or-more join legs to apply per record as the stream flows.
2178
- * Each leg attaches the resolved right-side record (or null) under
2179
- * its alias. — streaming joins.
2180
- *
2181
- * Joins are evaluated AFTER clauses, so a `where()` filtered-out
2182
- * record never triggers a right-side lookup. This is the same
2183
- * ordering as `Query.toArray()` (clauses first, joins after) and
2184
- * keeps the streaming path from doing wasted work.
2185
- */
2186
- private readonly joins;
2187
- /**
2188
- * Join resolution context. Required for `.join()` to translate a
2189
- * field name into a target collection + ref mode and to resolve
2190
- * the right-side `JoinableSource`. Optional because tests
2191
- * construct ScanBuilder directly with synthetic page providers
2192
- * that don't know about ref() — calling `.join()` without a
2193
- * context throws with an actionable error.
2194
- */
2195
- private readonly joinContext;
2196
- constructor(pageProvider: ScanPageProvider<T>, pageSize?: number, clauses?: readonly Clause[], joins?: readonly JoinLeg[], joinContext?: JoinContext);
2197
- /**
2198
- * Add a field comparison. Runs per record as the scan stream
2199
- * flows through, so non-matching records are dropped before they
2200
- * reach `.aggregate()` or the iteration consumer. Multiple
2201
- * `.where()` calls are AND-combined — same semantics as
2202
- * `Query.where()`.
2203
- *
2204
- * Clauses cannot use the secondary-index fast path here because
2205
- * the scan sources records from the adapter's paginator, not from
2206
- * the in-memory cache where indexes live. Index-accelerated scans
2207
- * are a future optimization — the current implementation
2208
- * evaluates clauses per record in O(1) per clause.
2209
- */
2210
- where(field: string, op: Operator, value: unknown): ScanBuilder<T>;
2211
- /**
2212
- * Escape hatch: add an arbitrary predicate function. Same
2213
- * non-serializable caveat as `Query.filter()` — filter clauses
2214
- * don't round-trip through `toPlan()`. Prefer `.where()` when
2215
- * possible.
2216
- */
2217
- filter(fn: (record: T) => boolean): ScanBuilder<T>;
2218
- /**
2219
- * Resolve a `ref()`-declared foreign key per record as the scan
2220
- * stream flows, attaching the right-side record (or null) under
2221
- * `opts.as`. — streaming joins over `scan()`.
2222
- *
2223
- * ```ts
2224
- * for await (const inv of invoices.scan().join('clientId', { as: 'client' })) {
2225
- * await processInvoice(inv) // inv.client is attached
2226
- * }
2227
- *
2228
- * // Or terminate with .aggregate() for streaming joined aggregation
2229
- * const { total } = await invoices.scan()
2230
- * .where('status', '==', 'open')
2231
- * .join('clientId', { as: 'client' })
2232
- * .aggregate({ total: sum('amount') })
2233
- * ```
2234
- *
2235
- * **The key difference from eager `.join()`:** the LEFT
2236
- * side streams page-by-page from the adapter and is never
2237
- * materialized. Memory ceiling on the left is O(pageSize), not
2238
- * O(rowCount). This is what makes streaming joins suitable for
2239
- * collections that exceed the eager join's 50_000-row ceiling.
2240
- *
2241
- * **Right-side strategy** is auto-selected per leg:
2242
- * - **Indexed** — right source exposes `lookupById`, so each
2243
- * left row costs O(1). This is the common path for
2244
- * Collection right sides, which back `lookupById` with a Map
2245
- * lookup over the in-memory cache. The right collection must
2246
- * be in eager mode (the same constraint as eager join's
2247
- * `querySourceForJoin` from ).
2248
- * - **Hash** — right source has only `snapshot()`. Build a
2249
- * `Map<id, record>` once at iteration start, probe per left
2250
- * row. Same correctness, same per-row cost as the indexed
2251
- * path; the difference is the upfront cost of materializing
2252
- * the right side once.
2253
- *
2254
- * Both strategies hold the right side in memory for the duration
2255
- * of the iteration. The "streaming" property applies to the LEFT
2256
- * side only — true left-and-right streaming joins (where neither
2257
- * side fits in memory) require a sort-merge join planner that's
2258
- * out of scope for.
2259
- *
2260
- * **Ref-mode semantics** match eager `.join()` exactly:
2261
- * - `strict` → throws `DanglingReferenceError` mid-stream
2262
- * when a left record points at a non-existent right id.
2263
- * The throw aborts the async iterator — consumers should
2264
- * wrap the `for await` in try/catch if they want to recover.
2265
- * - `warn` → attaches `null` and emits a one-shot warning
2266
- * per unique dangling pair (deduped via the same warn
2267
- * channel as eager join).
2268
- * - `cascade` → attaches `null` silently. A delete-time mode;
2269
- * dangling refs at read time are mid-flight or pre-existing
2270
- * orphans, not a DSL error.
2271
- *
2272
- * Left records with null/undefined FK values attach `null`
2273
- * regardless of mode — same "no reference at all" policy as
2274
- * eager join and write-time `enforceRefsOnPut`.
2275
- *
2276
- * **Multi-FK chaining** is supported via repeated `.join()`
2277
- * calls: each leg resolves an independent ref. Each leg
2278
- * independently picks its right-side strategy and applies its
2279
- * own ref mode.
2280
- *
2281
- * **Joins are NOT applied** to a `.aggregate()` terminal that
2282
- * doesn't reference joined fields — wait, that's not quite
2283
- * right. The streaming path actually DOES apply joins before
2284
- * `.aggregate()` because the join attaches a field that the
2285
- * spec might reference. Unlike `Query.aggregate()` (which skips
2286
- * joins entirely as a projection-only short-circuit), the
2287
- * streaming aggregation can't know whether the spec touches a
2288
- * joined field, so it always applies joins. Consumers who want
2289
- * unjoined streaming aggregation should leave `.join()` off the
2290
- * chain — the chain is composable for a reason.
2291
- *
2292
- * constraint #1 — every JoinLeg carries `partitionScope:
2293
- * 'all'` plumbed through but never read by. Same seam as
2294
- * eager join.
2295
- */
2296
- join<As extends string, R = unknown>(field: string, opts: {
2297
- as: As;
2298
- }): ScanBuilder<T & Record<As, R | null>>;
2299
- /**
2300
- * Iterate the scan as an async iterable. Walks the page
2301
- * provider's cursors forward until exhaustion, applying every
2302
- * clause per record — only matching records are yielded.
2303
- *
2304
- * Backward-compatible with the previous async-generator `scan()`
2305
- * return type for `for await … of` consumers.
2306
- */
2307
- [Symbol.asyncIterator](): AsyncIterator<T>;
2308
- /**
2309
- * Per-leg right-side resolution state. Built once at iteration
2310
- * start and reused for every left record. Two strategies:
2311
- *
2312
- * - `lookupById`: present when the right source exposes the
2313
- * hook directly (typical Collection right side). Per-row
2314
- * cost is O(1).
2315
- * - `hashByPrimaryKey`: built from `snapshot()` when no
2316
- * lookupById. Per-row cost is O(1) after the upfront O(N)
2317
- * materialization. Same as eager join's hash strategy.
2318
- *
2319
- * `warnedKeys` is the per-leg dedup set for ref-mode 'warn'. We
2320
- * key on `field→target:refId` so the same dangling pair only
2321
- * warns once per iteration. The dedup is per-iteration, not
2322
- * per-process — a long-running scan that re-iterates would warn
2323
- * again, which is the desired behavior (the data may have
2324
- * changed between iterations).
2325
- */
2326
- private buildJoinResolvers;
2327
- /**
2328
- * Resolve a single join leg for one left record and return the
2329
- * left record with the joined field attached under
2330
- * `leg.as`. Pure function over `(left, resolver)`; never
2331
- * mutates the input.
2332
- *
2333
- * Ref-mode dispatch matches eager `applyJoins` from :
2334
- * - null/undefined FK → attach null silently (always allowed)
2335
- * - dangling FK + strict → throw `DanglingReferenceError`
2336
- * - dangling FK + warn → attach null, warn-once per pair
2337
- * - dangling FK + cascade → attach null silently
2338
- */
2339
- private applyOneJoinStreaming;
2340
- /**
2341
- * Reduce the scan stream through a named set of reducers and
2342
- * return the final aggregated shape.
2343
- *
2344
- * Memory is O(reducers): one mutable state slot per spec key.
2345
- * Records flow through the pipeline one at a time via
2346
- * `for await` and are discarded after their `step()` is applied
2347
- * — never collected into an array. This is the distinguishing
2348
- * property from `Query.aggregate()`, which materializes the full
2349
- * match set first.
2350
- *
2351
- * Reuses the same reducer protocol as `Query.aggregate()`,
2352
- * so `count()`, `sum(field)`, `avg(field)`, `min(field)`,
2353
- * `max(field)` all work unchanged. The `{ seed }` parameter
2354
- * plumbing from constraint #2 is honored transparently — the
2355
- * factories ignore it in and the scan executor never
2356
- * touches the per-reducer state construction.
2357
- *
2358
- * **Returns a Promise**, unlike `Query.aggregate().run()` which
2359
- * is synchronous. The scan is inherently async because it walks
2360
- * adapter pages, so the terminal has to be too. Consumers
2361
- * destructure with await:
2362
- *
2363
- * ```ts
2364
- * const { total, n } = await invoices.scan()
2365
- * .where('year', '==', 2025)
2366
- * .aggregate({ total: sum('amount'), n: count() })
2367
- * ```
2368
- *
2369
- * **No `.live()` in.** `scan().aggregate().live()` would
2370
- * require reconciling an unbounded streaming iteration with a
2371
- * change-stream subscription — a design problem, not just a code
2372
- * one. Consumers with huge collections and live needs should
2373
- * narrow with `.where()` enough to fit in the 50k `query()`
2374
- * limit and use `query().aggregate().live()` instead.
2375
- */
2376
- aggregate<Spec extends AggregateSpec>(spec: Spec): Promise<AggregateResult<Spec>>;
2377
- /**
2378
- * Evaluate the clause list against a single record. Linear in
2379
- * the clause count; short-circuits on first false. Clauses on a
2380
- * scan are always re-evaluated per record — no index-accelerated
2381
- * path, because the stream sources records from the adapter
2382
- * paginator, not from the in-memory cache where indexes live.
2383
- */
2384
- private recordMatches;
2385
- }
2386
-
2387
- export { ImportCapabilityError as $, AmendmentForbiddenError as A, BackupCorruptedError as B, ConflictError as C, DictKeyInUseError as D, CrossJoinSourceUnknownError as E, FieldFrozenError as F, CrossJoinTooLargeError as G, DEFAULT_CROSS_JOIN_MAX_ROWS as H, InvariantError as I, DEFAULT_JOIN_MAX_ROWS as J, DanglingReferenceError as K, LocaleNotSpecifiedError as L, MissingTranslationError as M, NoydbError as N, OverlayBaseIsVirtualError as O, PartitionExtractionError as P, Query as Q, ReservedCollectionNameError as R, ScriptViolationError as S, TranslatorNotConfiguredError as T, DecryptionError as U, DelegationTargetMissingError as V, DirectoryDisabledError as W, ElevationExpiredError as X, ExportCapabilityError as Y, FilenameSanitizationError as Z, GroupCardinalityError as _, DictKeyMissingError as a, IndexRequiredError as a0, IndexWriteFailureError as a1, InvalidKeyError as a2, type JoinContext as a3, type JoinLeg as a4, type JoinStrategy as a5, JoinTooLargeError as a6, type JoinableSource as a7, KeyringCorruptError as a8, KeyringExpiredError as a9, type ScanPageProvider as aA, SchemaFenceError as aB, SchemaLockedError as aC, SchemaUpdateError as aD, SchemaValidationError as aE, StoreCapabilityError as aF, TamperedError as aG, TierDemoteDeniedError as aH, TierNotGrantedError as aI, ValidationError as aJ, applyJoins as aK, buildLiveQuery as aL, executePlan as aM, ref as aN, resetJoinWarnings as aO, LedgerContentionError as aa, type LiveQuery as ab, type LiveUpstream as ac, MigrationRequiredError as ad, NetworkError as ae, NoAccessError as af, NonAdditiveSchemaChangeError as ag, NotFoundError as ah, type OrderBy as ai, PathEscapeError as aj, PeriodClosedError as ak, PermissionDeniedError as al, PrivilegeEscalationError as am, type QueryPlan as an, type QuerySource as ao, QuiesceTimeoutError as ap, ReadOnlyAtInstantError as aq, ReadOnlyError as ar, ReadOnlyFrameError as as, type RefDescriptor as at, RefIntegrityError as au, type RefMode as av, RefRegistry as aw, RefScopeError as ax, type RefViolation as ay, ScanBuilder as az, SessionExpiredError as b, SessionNotFoundError as c, SessionPolicyError as d, RecordLockedError as e, SnapshotNotFoundError as f, DerivationCapExceededError as g, DerivationCycleError as h, DerivationDepthError as i, DerivationOutputShapeError as j, DerivationOutputUnknownError as k, OverlayCollectionUnavailableError as l, OverlayIdMismatchError as m, OverlayNameCollisionError as n, AttestationError as o, AdoptionStateError as p, BackupLedgerError as q, BundleIntegrityError as r, BundleSealMismatchError as s, BundleVersionConflictError as t, TransferSealError as u, MaterializedViewConfigError as v, MaterializedViewCycleError as w, MaterializedViewSourceUnknownError as x, MaterializedViewTooLargeError as y, AlreadyElevatedError as z };