@vandenberghinc/volt 1.2.5 → 1.2.6

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 (489) hide show
  1. package/frontend/assets/admin/admin.png +0 -0
  2. package/frontend/assets/admin/password.webp +0 -0
  3. package/frontend/assets/icons/arrow.v1.webp +0 -0
  4. package/frontend/assets/icons/copy.webp +0 -0
  5. package/frontend/assets/payments/arrow.long.webp +0 -0
  6. package/frontend/assets/payments/arrow.long2.webp +0 -0
  7. package/frontend/assets/payments/cancelled.webp +0 -0
  8. package/frontend/assets/payments/check.sign.webp +0 -0
  9. package/frontend/assets/payments/check.webp +0 -0
  10. package/frontend/assets/payments/close.webp +0 -0
  11. package/frontend/assets/payments/error.webp +0 -0
  12. package/frontend/assets/payments/exclamation.webp +0 -0
  13. package/frontend/assets/payments/minus.webp +0 -0
  14. package/frontend/assets/payments/party.webp +0 -0
  15. package/frontend/assets/payments/plus.webp +0 -0
  16. package/frontend/assets/payments/shopping_cart.webp +0 -0
  17. package/frontend/assets/payments/trash.webp +0 -0
  18. package/package.json +5 -1
  19. package/.libris/config.json +0 -82
  20. package/backend/dist/cjs/backend/src/blacklist.d.ts +0 -12
  21. package/backend/dist/cjs/backend/src/blacklist.js +0 -78
  22. package/backend/dist/cjs/backend/src/cli.d.ts +0 -2
  23. package/backend/dist/cjs/backend/src/cli.js +0 -198
  24. package/backend/dist/cjs/backend/src/database/collection.d.ts +0 -1765
  25. package/backend/dist/cjs/backend/src/database/collection.js +0 -3301
  26. package/backend/dist/cjs/backend/src/database/database.d.ts +0 -92
  27. package/backend/dist/cjs/backend/src/database/database.js +0 -170
  28. package/backend/dist/cjs/backend/src/database/document.d.ts +0 -1
  29. package/backend/dist/cjs/backend/src/database/document.js +0 -15
  30. package/backend/dist/cjs/backend/src/database/filters/filters.d.ts +0 -6
  31. package/backend/dist/cjs/backend/src/database/filters/filters.js +0 -15
  32. package/backend/dist/cjs/backend/src/database/filters/strict_filter.d.ts +0 -223
  33. package/backend/dist/cjs/backend/src/database/filters/strict_filter.js +0 -15
  34. package/backend/dist/cjs/backend/src/database/filters/strict_filter_test.d.ts +0 -1
  35. package/backend/dist/cjs/backend/src/database/filters/strict_filter_test.js +0 -443
  36. package/backend/dist/cjs/backend/src/database/filters/strict_filter_test_v0.d.ts +0 -1
  37. package/backend/dist/cjs/backend/src/database/filters/strict_filter_test_v0.js +0 -15
  38. package/backend/dist/cjs/backend/src/database/filters/strict_filter_v0.d.ts +0 -50
  39. package/backend/dist/cjs/backend/src/database/filters/strict_filter_v0.js +0 -15
  40. package/backend/dist/cjs/backend/src/database/filters/strict_filter_v1.d.ts +0 -76
  41. package/backend/dist/cjs/backend/src/database/filters/strict_filter_v1.js +0 -15
  42. package/backend/dist/cjs/backend/src/database/filters/strict_filter_v2.d.ts +0 -75
  43. package/backend/dist/cjs/backend/src/database/filters/strict_filter_v2.js +0 -15
  44. package/backend/dist/cjs/backend/src/database/filters/strict_filter_v3.d.ts +0 -219
  45. package/backend/dist/cjs/backend/src/database/filters/strict_filter_v3.js +0 -15
  46. package/backend/dist/cjs/backend/src/database/filters/strict_update_filter.d.ts +0 -165
  47. package/backend/dist/cjs/backend/src/database/filters/strict_update_filter.js +0 -15
  48. package/backend/dist/cjs/backend/src/database/filters/strict_update_filter_test.d.ts +0 -5
  49. package/backend/dist/cjs/backend/src/database/filters/strict_update_filter_test.js +0 -355
  50. package/backend/dist/cjs/backend/src/database/flatten.d.ts +0 -78
  51. package/backend/dist/cjs/backend/src/database/flatten.js +0 -53
  52. package/backend/dist/cjs/backend/src/database/flatten_test.d.ts +0 -1
  53. package/backend/dist/cjs/backend/src/database/flatten_test.js +0 -175
  54. package/backend/dist/cjs/backend/src/database/quota/quoata_v2.d.ts +0 -533
  55. package/backend/dist/cjs/backend/src/database/quota/quoata_v2.js +0 -1046
  56. package/backend/dist/cjs/backend/src/database/quota/quota.d.ts +0 -551
  57. package/backend/dist/cjs/backend/src/database/quota/quota.js +0 -1108
  58. package/backend/dist/cjs/backend/src/database/quota/quota_v1.d.ts +0 -534
  59. package/backend/dist/cjs/backend/src/database/quota/quota_v1.js +0 -1087
  60. package/backend/dist/cjs/backend/src/database/quota/safe_int.d.ts +0 -412
  61. package/backend/dist/cjs/backend/src/database/quota/safe_int.js +0 -745
  62. package/backend/dist/cjs/backend/src/endpoint.d.ts +0 -346
  63. package/backend/dist/cjs/backend/src/endpoint.js +0 -468
  64. package/backend/dist/cjs/backend/src/errors/index.d.ts +0 -7
  65. package/backend/dist/cjs/backend/src/errors/index.js +0 -25
  66. package/backend/dist/cjs/backend/src/errors/internal_external.d.ts +0 -52
  67. package/backend/dist/cjs/backend/src/errors/internal_external.js +0 -95
  68. package/backend/dist/cjs/backend/src/errors/invalid_usage_error.d.ts +0 -41
  69. package/backend/dist/cjs/backend/src/errors/invalid_usage_error.js +0 -47
  70. package/backend/dist/cjs/backend/src/errors/system_error.d.ts +0 -261
  71. package/backend/dist/cjs/backend/src/errors/system_error.js +0 -436
  72. package/backend/dist/cjs/backend/src/events.d.ts +0 -97
  73. package/backend/dist/cjs/backend/src/events.js +0 -15
  74. package/backend/dist/cjs/backend/src/frontend.d.ts +0 -11
  75. package/backend/dist/cjs/backend/src/frontend.js +0 -37
  76. package/backend/dist/cjs/backend/src/image_endpoint.d.ts +0 -44
  77. package/backend/dist/cjs/backend/src/image_endpoint.js +0 -185
  78. package/backend/dist/cjs/backend/src/index.d.ts +0 -23
  79. package/backend/dist/cjs/backend/src/index.js +0 -70
  80. package/backend/dist/cjs/backend/src/logger.d.ts +0 -5
  81. package/backend/dist/cjs/backend/src/logger.js +0 -15
  82. package/backend/dist/cjs/backend/src/meta.d.ts +0 -112
  83. package/backend/dist/cjs/backend/src/meta.js +0 -181
  84. package/backend/dist/cjs/backend/src/payments/paddle.d.ts +0 -329
  85. package/backend/dist/cjs/backend/src/payments/paddle.js +0 -1996
  86. package/backend/dist/cjs/backend/src/payments/stripe/checkout.d.ts +0 -113
  87. package/backend/dist/cjs/backend/src/payments/stripe/checkout.js +0 -295
  88. package/backend/dist/cjs/backend/src/payments/stripe/customers.d.ts +0 -17
  89. package/backend/dist/cjs/backend/src/payments/stripe/customers.js +0 -164
  90. package/backend/dist/cjs/backend/src/payments/stripe/error.d.ts +0 -74
  91. package/backend/dist/cjs/backend/src/payments/stripe/error.js +0 -64
  92. package/backend/dist/cjs/backend/src/payments/stripe/events.d.ts +0 -155
  93. package/backend/dist/cjs/backend/src/payments/stripe/events.js +0 -15
  94. package/backend/dist/cjs/backend/src/payments/stripe/meters.d.ts +0 -105
  95. package/backend/dist/cjs/backend/src/payments/stripe/meters.js +0 -230
  96. package/backend/dist/cjs/backend/src/payments/stripe/payment_methods.d.ts +0 -58
  97. package/backend/dist/cjs/backend/src/payments/stripe/payment_methods.js +0 -109
  98. package/backend/dist/cjs/backend/src/payments/stripe/products.d.ts +0 -519
  99. package/backend/dist/cjs/backend/src/payments/stripe/products.js +0 -650
  100. package/backend/dist/cjs/backend/src/payments/stripe/stripe.d.ts +0 -215
  101. package/backend/dist/cjs/backend/src/payments/stripe/stripe.js +0 -468
  102. package/backend/dist/cjs/backend/src/payments/stripe/subscriptions.d.ts +0 -172
  103. package/backend/dist/cjs/backend/src/payments/stripe/subscriptions.js +0 -557
  104. package/backend/dist/cjs/backend/src/payments/stripe/utils.d.ts +0 -63
  105. package/backend/dist/cjs/backend/src/payments/stripe/utils.js +0 -118
  106. package/backend/dist/cjs/backend/src/payments/stripe/webhooks.d.ts +0 -105
  107. package/backend/dist/cjs/backend/src/payments/stripe/webhooks.js +0 -627
  108. package/backend/dist/cjs/backend/src/plugins/browser.d.ts +0 -1
  109. package/backend/dist/cjs/backend/src/plugins/browser.js +0 -15
  110. package/backend/dist/cjs/backend/src/plugins/communication.d.ts +0 -70
  111. package/backend/dist/cjs/backend/src/plugins/communication.js +0 -196
  112. package/backend/dist/cjs/backend/src/plugins/mail/mail.d.ts +0 -255
  113. package/backend/dist/cjs/backend/src/plugins/mail/mail.js +0 -381
  114. package/backend/dist/cjs/backend/src/plugins/mail/ui.d.ts +0 -297
  115. package/backend/dist/cjs/backend/src/plugins/mail/ui.js +0 -1370
  116. package/backend/dist/cjs/backend/src/plugins/pdf.d.ts +0 -1
  117. package/backend/dist/cjs/backend/src/plugins/pdf.js +0 -1456
  118. package/backend/dist/cjs/backend/src/plugins/thread_monitor.d.ts +0 -18
  119. package/backend/dist/cjs/backend/src/plugins/thread_monitor.js +0 -116
  120. package/backend/dist/cjs/backend/src/rate_limit.d.ts +0 -148
  121. package/backend/dist/cjs/backend/src/rate_limit.js +0 -543
  122. package/backend/dist/cjs/backend/src/route.d.ts +0 -39
  123. package/backend/dist/cjs/backend/src/route.js +0 -172
  124. package/backend/dist/cjs/backend/src/server.d.ts +0 -502
  125. package/backend/dist/cjs/backend/src/server.js +0 -1713
  126. package/backend/dist/cjs/backend/src/server.old.d.ts +0 -594
  127. package/backend/dist/cjs/backend/src/server.old.js +0 -2058
  128. package/backend/dist/cjs/backend/src/splash_screen.d.ts +0 -93
  129. package/backend/dist/cjs/backend/src/splash_screen.js +0 -119
  130. package/backend/dist/cjs/backend/src/status.d.ts +0 -89
  131. package/backend/dist/cjs/backend/src/status.js +0 -211
  132. package/backend/dist/cjs/backend/src/stream.d.ts +0 -494
  133. package/backend/dist/cjs/backend/src/stream.js +0 -1370
  134. package/backend/dist/cjs/backend/src/users.d.ts +0 -926
  135. package/backend/dist/cjs/backend/src/users.js +0 -2223
  136. package/backend/dist/cjs/backend/src/utils.d.ts +0 -22
  137. package/backend/dist/cjs/backend/src/utils.js +0 -626
  138. package/backend/dist/cjs/backend/src/view.d.ts +0 -115
  139. package/backend/dist/cjs/backend/src/view.js +0 -519
  140. package/backend/dist/cjs/backend/src/vinc.d.ts +0 -6
  141. package/backend/dist/cjs/backend/src/vinc.js +0 -40
  142. package/backend/dist/cjs/backend/src/volt.d.ts +0 -24
  143. package/backend/dist/cjs/backend/src/volt.js +0 -72
  144. package/backend/dist/cjs/frontend/src/modules/request.d.ts +0 -70
  145. package/backend/dist/cjs/frontend/src/modules/request.js +0 -99
  146. package/backend/dist/cjs/package.json +0 -1
  147. package/backend/dist/esm/backend/src/blacklist.d.ts +0 -12
  148. package/backend/dist/esm/backend/src/blacklist.js +0 -52
  149. package/backend/dist/esm/backend/src/cli.d.ts +0 -2
  150. package/backend/dist/esm/backend/src/cli.js +0 -211
  151. package/backend/dist/esm/backend/src/database/collection.d.ts +0 -1765
  152. package/backend/dist/esm/backend/src/database/collection.js +0 -3779
  153. package/backend/dist/esm/backend/src/database/database.d.ts +0 -92
  154. package/backend/dist/esm/backend/src/database/database.js +0 -214
  155. package/backend/dist/esm/backend/src/database/document.d.ts +0 -1
  156. package/backend/dist/esm/backend/src/database/document.js +0 -558
  157. package/backend/dist/esm/backend/src/database/filters/filters.d.ts +0 -6
  158. package/backend/dist/esm/backend/src/database/filters/filters.js +0 -1
  159. package/backend/dist/esm/backend/src/database/filters/strict_filter.d.ts +0 -223
  160. package/backend/dist/esm/backend/src/database/filters/strict_filter.js +0 -3
  161. package/backend/dist/esm/backend/src/database/filters/strict_filter_test.d.ts +0 -1
  162. package/backend/dist/esm/backend/src/database/filters/strict_filter_test.js +0 -505
  163. package/backend/dist/esm/backend/src/database/filters/strict_filter_test_v0.d.ts +0 -1
  164. package/backend/dist/esm/backend/src/database/filters/strict_filter_test_v0.js +0 -712
  165. package/backend/dist/esm/backend/src/database/filters/strict_filter_v0.d.ts +0 -50
  166. package/backend/dist/esm/backend/src/database/filters/strict_filter_v0.js +0 -5
  167. package/backend/dist/esm/backend/src/database/filters/strict_filter_v1.d.ts +0 -76
  168. package/backend/dist/esm/backend/src/database/filters/strict_filter_v1.js +0 -44
  169. package/backend/dist/esm/backend/src/database/filters/strict_filter_v2.d.ts +0 -75
  170. package/backend/dist/esm/backend/src/database/filters/strict_filter_v2.js +0 -5
  171. package/backend/dist/esm/backend/src/database/filters/strict_filter_v3.d.ts +0 -219
  172. package/backend/dist/esm/backend/src/database/filters/strict_filter_v3.js +0 -1
  173. package/backend/dist/esm/backend/src/database/filters/strict_update_filter.d.ts +0 -165
  174. package/backend/dist/esm/backend/src/database/filters/strict_update_filter.js +0 -5
  175. package/backend/dist/esm/backend/src/database/filters/strict_update_filter_test.d.ts +0 -5
  176. package/backend/dist/esm/backend/src/database/filters/strict_update_filter_test.js +0 -415
  177. package/backend/dist/esm/backend/src/database/flatten.d.ts +0 -78
  178. package/backend/dist/esm/backend/src/database/flatten.js +0 -22
  179. package/backend/dist/esm/backend/src/database/flatten_test.d.ts +0 -1
  180. package/backend/dist/esm/backend/src/database/flatten_test.js +0 -174
  181. package/backend/dist/esm/backend/src/database/quota/quoata_v2.d.ts +0 -533
  182. package/backend/dist/esm/backend/src/database/quota/quoata_v2.js +0 -1155
  183. package/backend/dist/esm/backend/src/database/quota/quota.d.ts +0 -551
  184. package/backend/dist/esm/backend/src/database/quota/quota.js +0 -1219
  185. package/backend/dist/esm/backend/src/database/quota/quota_v1.d.ts +0 -534
  186. package/backend/dist/esm/backend/src/database/quota/quota_v1.js +0 -1242
  187. package/backend/dist/esm/backend/src/database/quota/safe_int.d.ts +0 -412
  188. package/backend/dist/esm/backend/src/database/quota/safe_int.js +0 -810
  189. package/backend/dist/esm/backend/src/endpoint.d.ts +0 -346
  190. package/backend/dist/esm/backend/src/endpoint.js +0 -479
  191. package/backend/dist/esm/backend/src/errors/index.d.ts +0 -7
  192. package/backend/dist/esm/backend/src/errors/index.js +0 -7
  193. package/backend/dist/esm/backend/src/errors/internal_external.d.ts +0 -52
  194. package/backend/dist/esm/backend/src/errors/internal_external.js +0 -86
  195. package/backend/dist/esm/backend/src/errors/invalid_usage_error.d.ts +0 -41
  196. package/backend/dist/esm/backend/src/errors/invalid_usage_error.js +0 -33
  197. package/backend/dist/esm/backend/src/errors/system_error.d.ts +0 -261
  198. package/backend/dist/esm/backend/src/errors/system_error.js +0 -444
  199. package/backend/dist/esm/backend/src/events.d.ts +0 -97
  200. package/backend/dist/esm/backend/src/events.js +0 -5
  201. package/backend/dist/esm/backend/src/frontend.d.ts +0 -11
  202. package/backend/dist/esm/backend/src/frontend.js +0 -12
  203. package/backend/dist/esm/backend/src/image_endpoint.d.ts +0 -44
  204. package/backend/dist/esm/backend/src/image_endpoint.js +0 -196
  205. package/backend/dist/esm/backend/src/index.d.ts +0 -23
  206. package/backend/dist/esm/backend/src/index.js +0 -26
  207. package/backend/dist/esm/backend/src/logger.d.ts +0 -5
  208. package/backend/dist/esm/backend/src/logger.js +0 -8
  209. package/backend/dist/esm/backend/src/meta.d.ts +0 -112
  210. package/backend/dist/esm/backend/src/meta.js +0 -152
  211. package/backend/dist/esm/backend/src/payments/paddle.d.ts +0 -329
  212. package/backend/dist/esm/backend/src/payments/paddle.js +0 -2276
  213. package/backend/dist/esm/backend/src/payments/stripe/checkout.d.ts +0 -113
  214. package/backend/dist/esm/backend/src/payments/stripe/checkout.js +0 -356
  215. package/backend/dist/esm/backend/src/payments/stripe/customers.d.ts +0 -17
  216. package/backend/dist/esm/backend/src/payments/stripe/customers.js +0 -193
  217. package/backend/dist/esm/backend/src/payments/stripe/error.d.ts +0 -74
  218. package/backend/dist/esm/backend/src/payments/stripe/error.js +0 -51
  219. package/backend/dist/esm/backend/src/payments/stripe/events.d.ts +0 -155
  220. package/backend/dist/esm/backend/src/payments/stripe/events.js +0 -5
  221. package/backend/dist/esm/backend/src/payments/stripe/meters.d.ts +0 -105
  222. package/backend/dist/esm/backend/src/payments/stripe/meters.js +0 -318
  223. package/backend/dist/esm/backend/src/payments/stripe/payment_methods.d.ts +0 -58
  224. package/backend/dist/esm/backend/src/payments/stripe/payment_methods.js +0 -135
  225. package/backend/dist/esm/backend/src/payments/stripe/products.d.ts +0 -519
  226. package/backend/dist/esm/backend/src/payments/stripe/products.js +0 -896
  227. package/backend/dist/esm/backend/src/payments/stripe/stripe.d.ts +0 -215
  228. package/backend/dist/esm/backend/src/payments/stripe/stripe.js +0 -464
  229. package/backend/dist/esm/backend/src/payments/stripe/subscriptions.d.ts +0 -172
  230. package/backend/dist/esm/backend/src/payments/stripe/subscriptions.js +0 -754
  231. package/backend/dist/esm/backend/src/payments/stripe/utils.d.ts +0 -63
  232. package/backend/dist/esm/backend/src/payments/stripe/utils.js +0 -131
  233. package/backend/dist/esm/backend/src/payments/stripe/webhooks.d.ts +0 -105
  234. package/backend/dist/esm/backend/src/payments/stripe/webhooks.js +0 -752
  235. package/backend/dist/esm/backend/src/plugins/browser.d.ts +0 -1
  236. package/backend/dist/esm/backend/src/plugins/browser.js +0 -170
  237. package/backend/dist/esm/backend/src/plugins/communication.d.ts +0 -70
  238. package/backend/dist/esm/backend/src/plugins/communication.js +0 -169
  239. package/backend/dist/esm/backend/src/plugins/mail/mail.d.ts +0 -255
  240. package/backend/dist/esm/backend/src/plugins/mail/mail.js +0 -396
  241. package/backend/dist/esm/backend/src/plugins/mail/ui.d.ts +0 -297
  242. package/backend/dist/esm/backend/src/plugins/mail/ui.js +0 -1400
  243. package/backend/dist/esm/backend/src/plugins/pdf.d.ts +0 -1
  244. package/backend/dist/esm/backend/src/plugins/pdf.js +0 -1694
  245. package/backend/dist/esm/backend/src/plugins/thread_monitor.d.ts +0 -18
  246. package/backend/dist/esm/backend/src/plugins/thread_monitor.js +0 -120
  247. package/backend/dist/esm/backend/src/rate_limit.d.ts +0 -148
  248. package/backend/dist/esm/backend/src/rate_limit.js +0 -667
  249. package/backend/dist/esm/backend/src/route.d.ts +0 -39
  250. package/backend/dist/esm/backend/src/route.js +0 -222
  251. package/backend/dist/esm/backend/src/server.d.ts +0 -502
  252. package/backend/dist/esm/backend/src/server.js +0 -2034
  253. package/backend/dist/esm/backend/src/server.old.d.ts +0 -594
  254. package/backend/dist/esm/backend/src/server.old.js +0 -2630
  255. package/backend/dist/esm/backend/src/splash_screen.d.ts +0 -93
  256. package/backend/dist/esm/backend/src/splash_screen.js +0 -156
  257. package/backend/dist/esm/backend/src/status.d.ts +0 -89
  258. package/backend/dist/esm/backend/src/status.js +0 -213
  259. package/backend/dist/esm/backend/src/stream.d.ts +0 -494
  260. package/backend/dist/esm/backend/src/stream.js +0 -1611
  261. package/backend/dist/esm/backend/src/users.d.ts +0 -926
  262. package/backend/dist/esm/backend/src/users.js +0 -2423
  263. package/backend/dist/esm/backend/src/utils.d.ts +0 -22
  264. package/backend/dist/esm/backend/src/utils.js +0 -463
  265. package/backend/dist/esm/backend/src/view.d.ts +0 -115
  266. package/backend/dist/esm/backend/src/view.js +0 -584
  267. package/backend/dist/esm/backend/src/vinc.d.ts +0 -6
  268. package/backend/dist/esm/backend/src/vinc.js +0 -6
  269. package/backend/dist/esm/backend/src/volt.d.ts +0 -24
  270. package/backend/dist/esm/backend/src/volt.js +0 -27
  271. package/backend/dist/esm/frontend/src/modules/request.d.ts +0 -70
  272. package/backend/dist/esm/frontend/src/modules/request.js +0 -117
  273. package/backend/old/file_watcher.ts +0 -359
  274. package/backend/old/request.deprc.js +0 -626
  275. package/backend/old/response.deprc.js +0 -354
  276. package/frontend/dist/backend/src/database/collection.d.ts +0 -1765
  277. package/frontend/dist/backend/src/database/collection.js +0 -3779
  278. package/frontend/dist/backend/src/database/database.d.ts +0 -92
  279. package/frontend/dist/backend/src/database/database.js +0 -214
  280. package/frontend/dist/backend/src/database/filters/filters.d.ts +0 -6
  281. package/frontend/dist/backend/src/database/filters/filters.js +0 -1
  282. package/frontend/dist/backend/src/database/filters/strict_filter.d.ts +0 -223
  283. package/frontend/dist/backend/src/database/filters/strict_filter.js +0 -3
  284. package/frontend/dist/backend/src/database/filters/strict_update_filter.d.ts +0 -165
  285. package/frontend/dist/backend/src/database/filters/strict_update_filter.js +0 -5
  286. package/frontend/dist/backend/src/database/flatten.d.ts +0 -78
  287. package/frontend/dist/backend/src/database/flatten.js +0 -22
  288. package/frontend/dist/backend/src/endpoint.d.ts +0 -346
  289. package/frontend/dist/backend/src/endpoint.js +0 -479
  290. package/frontend/dist/backend/src/errors/index.d.ts +0 -7
  291. package/frontend/dist/backend/src/errors/index.js +0 -7
  292. package/frontend/dist/backend/src/errors/internal_external.d.ts +0 -52
  293. package/frontend/dist/backend/src/errors/internal_external.js +0 -86
  294. package/frontend/dist/backend/src/errors/invalid_usage_error.d.ts +0 -41
  295. package/frontend/dist/backend/src/errors/invalid_usage_error.js +0 -33
  296. package/frontend/dist/backend/src/errors/system_error.d.ts +0 -261
  297. package/frontend/dist/backend/src/errors/system_error.js +0 -444
  298. package/frontend/dist/backend/src/events.d.ts +0 -97
  299. package/frontend/dist/backend/src/events.js +0 -5
  300. package/frontend/dist/backend/src/frontend.d.ts +0 -11
  301. package/frontend/dist/backend/src/frontend.js +0 -12
  302. package/frontend/dist/backend/src/image_endpoint.d.ts +0 -44
  303. package/frontend/dist/backend/src/image_endpoint.js +0 -196
  304. package/frontend/dist/backend/src/meta.d.ts +0 -112
  305. package/frontend/dist/backend/src/meta.js +0 -152
  306. package/frontend/dist/backend/src/payments/paddle.d.ts +0 -329
  307. package/frontend/dist/backend/src/payments/paddle.js +0 -2276
  308. package/frontend/dist/backend/src/payments/stripe/checkout.d.ts +0 -113
  309. package/frontend/dist/backend/src/payments/stripe/checkout.js +0 -356
  310. package/frontend/dist/backend/src/payments/stripe/customers.d.ts +0 -17
  311. package/frontend/dist/backend/src/payments/stripe/customers.js +0 -193
  312. package/frontend/dist/backend/src/payments/stripe/error.d.ts +0 -74
  313. package/frontend/dist/backend/src/payments/stripe/error.js +0 -51
  314. package/frontend/dist/backend/src/payments/stripe/events.d.ts +0 -155
  315. package/frontend/dist/backend/src/payments/stripe/events.js +0 -5
  316. package/frontend/dist/backend/src/payments/stripe/meters.d.ts +0 -105
  317. package/frontend/dist/backend/src/payments/stripe/meters.js +0 -318
  318. package/frontend/dist/backend/src/payments/stripe/payment_methods.d.ts +0 -58
  319. package/frontend/dist/backend/src/payments/stripe/payment_methods.js +0 -135
  320. package/frontend/dist/backend/src/payments/stripe/products.d.ts +0 -519
  321. package/frontend/dist/backend/src/payments/stripe/products.js +0 -896
  322. package/frontend/dist/backend/src/payments/stripe/stripe.d.ts +0 -215
  323. package/frontend/dist/backend/src/payments/stripe/stripe.js +0 -464
  324. package/frontend/dist/backend/src/payments/stripe/subscriptions.d.ts +0 -172
  325. package/frontend/dist/backend/src/payments/stripe/subscriptions.js +0 -754
  326. package/frontend/dist/backend/src/payments/stripe/utils.d.ts +0 -63
  327. package/frontend/dist/backend/src/payments/stripe/utils.js +0 -131
  328. package/frontend/dist/backend/src/payments/stripe/webhooks.d.ts +0 -105
  329. package/frontend/dist/backend/src/payments/stripe/webhooks.js +0 -752
  330. package/frontend/dist/backend/src/plugins/mail/mail.d.ts +0 -255
  331. package/frontend/dist/backend/src/plugins/mail/mail.js +0 -396
  332. package/frontend/dist/backend/src/plugins/mail/ui.d.ts +0 -297
  333. package/frontend/dist/backend/src/plugins/mail/ui.js +0 -1400
  334. package/frontend/dist/backend/src/rate_limit.d.ts +0 -148
  335. package/frontend/dist/backend/src/rate_limit.js +0 -667
  336. package/frontend/dist/backend/src/route.d.ts +0 -39
  337. package/frontend/dist/backend/src/route.js +0 -222
  338. package/frontend/dist/backend/src/server.d.ts +0 -502
  339. package/frontend/dist/backend/src/server.js +0 -2034
  340. package/frontend/dist/backend/src/splash_screen.d.ts +0 -93
  341. package/frontend/dist/backend/src/splash_screen.js +0 -156
  342. package/frontend/dist/backend/src/status.d.ts +0 -89
  343. package/frontend/dist/backend/src/status.js +0 -213
  344. package/frontend/dist/backend/src/stream.d.ts +0 -494
  345. package/frontend/dist/backend/src/stream.js +0 -1611
  346. package/frontend/dist/backend/src/users.d.ts +0 -926
  347. package/frontend/dist/backend/src/users.js +0 -2423
  348. package/frontend/dist/backend/src/utils.d.ts +0 -22
  349. package/frontend/dist/backend/src/utils.js +0 -463
  350. package/frontend/dist/backend/src/view.d.ts +0 -115
  351. package/frontend/dist/backend/src/view.js +0 -584
  352. package/frontend/dist/frontend/src/elements/base.d.ts +0 -3743
  353. package/frontend/dist/frontend/src/elements/base.js +0 -12151
  354. package/frontend/dist/frontend/src/elements/module.d.ts +0 -95
  355. package/frontend/dist/frontend/src/elements/module.js +0 -216
  356. package/frontend/dist/frontend/src/elements/register_element.d.ts +0 -3
  357. package/frontend/dist/frontend/src/elements/register_element.js +0 -22
  358. package/frontend/dist/frontend/src/elements/resize_query_manager.d.ts +0 -0
  359. package/frontend/dist/frontend/src/elements/resize_query_manager.js +0 -150
  360. package/frontend/dist/frontend/src/elements/types.d.ts +0 -52
  361. package/frontend/dist/frontend/src/elements/types.js +0 -5
  362. package/frontend/dist/frontend/src/index.d.ts +0 -21
  363. package/frontend/dist/frontend/src/index.js +0 -29
  364. package/frontend/dist/frontend/src/modules/attachment.d.ts +0 -126
  365. package/frontend/dist/frontend/src/modules/attachment.js +0 -306
  366. package/frontend/dist/frontend/src/modules/auth.d.ts +0 -44
  367. package/frontend/dist/frontend/src/modules/auth.js +0 -80
  368. package/frontend/dist/frontend/src/modules/color.d.ts +0 -160
  369. package/frontend/dist/frontend/src/modules/color.js +0 -316
  370. package/frontend/dist/frontend/src/modules/compression.d.ts +0 -39
  371. package/frontend/dist/frontend/src/modules/compression.js +0 -102
  372. package/frontend/dist/frontend/src/modules/cookies.d.ts +0 -44
  373. package/frontend/dist/frontend/src/modules/cookies.js +0 -143
  374. package/frontend/dist/frontend/src/modules/events.d.ts +0 -31
  375. package/frontend/dist/frontend/src/modules/events.js +0 -79
  376. package/frontend/dist/frontend/src/modules/google.d.ts +0 -23
  377. package/frontend/dist/frontend/src/modules/google.js +0 -52
  378. package/frontend/dist/frontend/src/modules/meta.d.ts +0 -14
  379. package/frontend/dist/frontend/src/modules/meta.js +0 -48
  380. package/frontend/dist/frontend/src/modules/paddle.d.ts +0 -1207
  381. package/frontend/dist/frontend/src/modules/paddle.js +0 -2594
  382. package/frontend/dist/frontend/src/modules/request.d.ts +0 -70
  383. package/frontend/dist/frontend/src/modules/request.js +0 -117
  384. package/frontend/dist/frontend/src/modules/settings.d.ts +0 -3
  385. package/frontend/dist/frontend/src/modules/settings.js +0 -5
  386. package/frontend/dist/frontend/src/modules/statics.d.ts +0 -21
  387. package/frontend/dist/frontend/src/modules/statics.js +0 -43
  388. package/frontend/dist/frontend/src/modules/stripe/cart.d.ts +0 -112
  389. package/frontend/dist/frontend/src/modules/stripe/cart.js +0 -321
  390. package/frontend/dist/frontend/src/modules/stripe/checkout.d.ts +0 -7
  391. package/frontend/dist/frontend/src/modules/stripe/checkout.js +0 -37
  392. package/frontend/dist/frontend/src/modules/stripe/index.m.d.ts +0 -6
  393. package/frontend/dist/frontend/src/modules/stripe/index.m.js +0 -6
  394. package/frontend/dist/frontend/src/modules/stripe/payments.d.ts +0 -58
  395. package/frontend/dist/frontend/src/modules/stripe/payments.js +0 -92
  396. package/frontend/dist/frontend/src/modules/support.d.ts +0 -30
  397. package/frontend/dist/frontend/src/modules/support.js +0 -53
  398. package/frontend/dist/frontend/src/modules/theme.d.ts +0 -133
  399. package/frontend/dist/frontend/src/modules/theme.js +0 -406
  400. package/frontend/dist/frontend/src/modules/themes.d.ts +0 -12
  401. package/frontend/dist/frontend/src/modules/themes.js +0 -22
  402. package/frontend/dist/frontend/src/modules/user.d.ts +0 -164
  403. package/frontend/dist/frontend/src/modules/user.js +0 -270
  404. package/frontend/dist/frontend/src/modules/utils.d.ts +0 -176
  405. package/frontend/dist/frontend/src/modules/utils.js +0 -569
  406. package/frontend/dist/frontend/src/types/gradient.d.ts +0 -29
  407. package/frontend/dist/frontend/src/types/gradient.js +0 -79
  408. package/frontend/dist/frontend/src/ui/border_button.d.ts +0 -94
  409. package/frontend/dist/frontend/src/ui/border_button.js +0 -228
  410. package/frontend/dist/frontend/src/ui/button.d.ts +0 -241
  411. package/frontend/dist/frontend/src/ui/button.js +0 -682
  412. package/frontend/dist/frontend/src/ui/canvas.d.ts +0 -138
  413. package/frontend/dist/frontend/src/ui/canvas.js +0 -444
  414. package/frontend/dist/frontend/src/ui/checkbox.d.ts +0 -74
  415. package/frontend/dist/frontend/src/ui/checkbox.js +0 -321
  416. package/frontend/dist/frontend/src/ui/code.d.ts +0 -235
  417. package/frontend/dist/frontend/src/ui/code.js +0 -1007
  418. package/frontend/dist/frontend/src/ui/context_menu.d.ts +0 -36
  419. package/frontend/dist/frontend/src/ui/context_menu.js +0 -205
  420. package/frontend/dist/frontend/src/ui/css.d.ts +0 -16
  421. package/frontend/dist/frontend/src/ui/css.js +0 -48
  422. package/frontend/dist/frontend/src/ui/divider.d.ts +0 -15
  423. package/frontend/dist/frontend/src/ui/divider.js +0 -78
  424. package/frontend/dist/frontend/src/ui/dropdown.d.ts +0 -176
  425. package/frontend/dist/frontend/src/ui/dropdown.js +0 -481
  426. package/frontend/dist/frontend/src/ui/for_each.d.ts +0 -37
  427. package/frontend/dist/frontend/src/ui/for_each.js +0 -92
  428. package/frontend/dist/frontend/src/ui/form.d.ts +0 -34
  429. package/frontend/dist/frontend/src/ui/form.js +0 -233
  430. package/frontend/dist/frontend/src/ui/frame_modes.d.ts +0 -37
  431. package/frontend/dist/frontend/src/ui/frame_modes.js +0 -108
  432. package/frontend/dist/frontend/src/ui/google_map.d.ts +0 -24
  433. package/frontend/dist/frontend/src/ui/google_map.js +0 -106
  434. package/frontend/dist/frontend/src/ui/gradient.d.ts +0 -25
  435. package/frontend/dist/frontend/src/ui/gradient.js +0 -131
  436. package/frontend/dist/frontend/src/ui/image.d.ts +0 -111
  437. package/frontend/dist/frontend/src/ui/image.js +0 -576
  438. package/frontend/dist/frontend/src/ui/input.d.ts +0 -392
  439. package/frontend/dist/frontend/src/ui/input.js +0 -1201
  440. package/frontend/dist/frontend/src/ui/link.d.ts +0 -25
  441. package/frontend/dist/frontend/src/ui/link.js +0 -140
  442. package/frontend/dist/frontend/src/ui/list.d.ts +0 -37
  443. package/frontend/dist/frontend/src/ui/list.js +0 -170
  444. package/frontend/dist/frontend/src/ui/loader_button.d.ts +0 -80
  445. package/frontend/dist/frontend/src/ui/loader_button.js +0 -193
  446. package/frontend/dist/frontend/src/ui/loaders.d.ts +0 -57
  447. package/frontend/dist/frontend/src/ui/loaders.js +0 -157
  448. package/frontend/dist/frontend/src/ui/popup.d.ts +0 -94
  449. package/frontend/dist/frontend/src/ui/popup.js +0 -510
  450. package/frontend/dist/frontend/src/ui/pseudo.d.ts +0 -44
  451. package/frontend/dist/frontend/src/ui/pseudo.js +0 -154
  452. package/frontend/dist/frontend/src/ui/scroller.d.ts +0 -105
  453. package/frontend/dist/frontend/src/ui/scroller.js +0 -1253
  454. package/frontend/dist/frontend/src/ui/slider.d.ts +0 -45
  455. package/frontend/dist/frontend/src/ui/slider.js +0 -217
  456. package/frontend/dist/frontend/src/ui/spacer.d.ts +0 -15
  457. package/frontend/dist/frontend/src/ui/spacer.js +0 -78
  458. package/frontend/dist/frontend/src/ui/span.d.ts +0 -15
  459. package/frontend/dist/frontend/src/ui/span.js +0 -73
  460. package/frontend/dist/frontend/src/ui/stack.d.ts +0 -66
  461. package/frontend/dist/frontend/src/ui/stack.js +0 -335
  462. package/frontend/dist/frontend/src/ui/steps.d.ts +0 -131
  463. package/frontend/dist/frontend/src/ui/steps.js +0 -308
  464. package/frontend/dist/frontend/src/ui/style.d.ts +0 -17
  465. package/frontend/dist/frontend/src/ui/style.js +0 -73
  466. package/frontend/dist/frontend/src/ui/switch.d.ts +0 -69
  467. package/frontend/dist/frontend/src/ui/switch.js +0 -357
  468. package/frontend/dist/frontend/src/ui/table.d.ts +0 -100
  469. package/frontend/dist/frontend/src/ui/table.js +0 -405
  470. package/frontend/dist/frontend/src/ui/tabs.d.ts +0 -111
  471. package/frontend/dist/frontend/src/ui/tabs.js +0 -424
  472. package/frontend/dist/frontend/src/ui/text.d.ts +0 -15
  473. package/frontend/dist/frontend/src/ui/text.js +0 -83
  474. package/frontend/dist/frontend/src/ui/title.d.ts +0 -91
  475. package/frontend/dist/frontend/src/ui/title.js +0 -272
  476. package/frontend/dist/frontend/src/ui/ui.d.ts +0 -35
  477. package/frontend/dist/frontend/src/ui/ui.js +0 -38
  478. package/frontend/dist/frontend/src/ui/view.d.ts +0 -15
  479. package/frontend/dist/frontend/src/ui/view.js +0 -88
  480. package/frontend/dist/frontend/src/volt.d.ts +0 -20
  481. package/frontend/dist/frontend/src/volt.js +0 -27
  482. package/frontend/examples/theme/theme.ts +0 -58
  483. package/frontend/tools/bundle_d_ts.js +0 -71
  484. package/frontend/tools/convert_to_jsdoc_input.txt +0 -9452
  485. package/frontend/tools/convert_to_jsdoc_output.txt +0 -7626
  486. package/frontend/tools/convert_to_jsdoc_tmp.js +0 -345
  487. package/frontend/tools/scan_mixed_imports.js +0 -69
  488. /package/frontend/{dist/frontend/src/css → css}/adyen.css +0 -0
  489. /package/frontend/{dist/frontend/src/css → css}/volt.css +0 -0
@@ -1,3301 +0,0 @@
1
- var __create = Object.create;
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __getProtoOf = Object.getPrototypeOf;
6
- var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __export = (target, all) => {
8
- for (var name in all)
9
- __defProp(target, name, { get: all[name], enumerable: true });
10
- };
11
- var __copyProps = (to, from, except, desc) => {
12
- if (from && typeof from === "object" || typeof from === "function") {
13
- for (let key of __getOwnPropNames(from))
14
- if (!__hasOwnProp.call(to, key) && key !== except)
15
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
- }
17
- return to;
18
- };
19
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
- // If the importer is in node compatibility mode or this is not an ESM
21
- // file that has been converted to a CommonJS file using a Babel-
22
- // compatible transform (i.e. "__esModule" has not been set), then set
23
- // "default" to the CommonJS "module.exports" for node compatibility.
24
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
- mod
26
- ));
27
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
- var stdin_exports = {};
29
- __export(stdin_exports, {
30
- Collection: () => Collection,
31
- TransactionCollection: () => TransactionCollection
32
- });
33
- module.exports = __toCommonJS(stdin_exports);
34
- var mongodb = __toESM(require("mongodb"));
35
- var vlib = __toESM(require("@vandenberghinc/vlib"));
36
- var import_flatten = require("./flatten.js");
37
- var import_errors = require("../errors/index.js");
38
- class Collection {
39
- /** Collection name */
40
- name;
41
- /** The mongo collection. */
42
- _col;
43
- /**
44
- * The Database parent class, used to initialize the collection on demand.
45
- * So the user can define collections at root level before the database is initialized.
46
- */
47
- db;
48
- /** Is initialized. */
49
- initialized = false;
50
- /** Whether this collection instance is transaction-based. */
51
- is_transaction = false;
52
- /** Whether this transaction has been finalized (committed or aborted). */
53
- is_finalized_transaction = false;
54
- /** Time to live in msec for all documents. */
55
- ttl;
56
- /** Is ttl behaviour enabled? */
57
- ttl_enabled;
58
- /** Enable sliding ttl (refreshes ttl on update), or static ttl (sets ttl on insert) */
59
- sliding_ttl;
60
- /**
61
- * The temporary indexes passed to the constructor for the init method.
62
- * @note This is not private so it can be updated by {@link QuotaManager}.
63
- */
64
- _init_indexes;
65
- /** The MongoDB client session for transaction support. */
66
- _session;
67
- /**
68
- * The record type version for the database.
69
- * See {@link Collection.Opts.record_version} for more info.
70
- *
71
- * Ensure its always defined so we always set the version to `1`,
72
- * in case the user decides later that it would need the transform version
73
- * for older documents. Otherwise they would not have the old `1` version.
74
- */
75
- record_version;
76
- /**
77
- * The function to transform an older document version to the current version.
78
- * See {@link Collection.Opts.on_transform_version} for more info.
79
- */
80
- on_transform_version;
81
- /**
82
- * Save fully transformed documents again to prevent unneeded future transformations.
83
- * See {@link Collection.Opts.persist_transformed_on_load} for more info.
84
- */
85
- persist_transformed_on_load;
86
- /**
87
- * The function to call when a document is loaded (also when a default value is used).
88
- * See {@link Collection.Opts.on_load} for more info.
89
- */
90
- on_load_cb;
91
- /**
92
- * Constructs a new Collection instance.
93
- *
94
- * @param opts The constructor options for the collection.
95
- *
96
- * @throws An error when attempting to initialize a transaction-based collection without initializing the derived collection first.
97
- *
98
- * @docs
99
- */
100
- constructor(opts) {
101
- if (!opts.transaction_based) {
102
- this.name = opts.name;
103
- this._col = opts.col;
104
- this.db = opts.db;
105
- this._init_indexes = opts.indexes;
106
- this.is_transaction = false;
107
- let ttl_ms;
108
- let ttl_sliding = true;
109
- if (typeof opts.ttl === "number") {
110
- ttl_ms = opts.ttl;
111
- ttl_sliding = true;
112
- } else if (opts.ttl && typeof opts.ttl === "object") {
113
- ttl_ms = opts.ttl.milliseconds;
114
- ttl_sliding = opts.ttl.sliding ?? true;
115
- } else {
116
- ttl_ms = void 0;
117
- ttl_sliding = true;
118
- }
119
- this.ttl = ttl_ms;
120
- this.ttl_enabled = this.ttl != null;
121
- this.sliding_ttl = ttl_sliding;
122
- if (opts.on_transform_version != null && opts.record_version == null) {
123
- throw new import_errors.InvalidUsageError({
124
- message: "Option 'on_transform_version' requires 'record_version' to be defined.",
125
- reason: "missing_record_version"
126
- });
127
- }
128
- if (opts.record_version != null && (!Number.isInteger(opts.record_version) || opts.record_version < 1)) {
129
- throw new import_errors.InvalidUsageError({
130
- message: "Option 'record_version' must be a positive integer.",
131
- reason: "invalid_record_version"
132
- });
133
- }
134
- const version = opts.record_version ?? 1;
135
- if (version !== 1 && opts.on_transform_version == null) {
136
- throw new import_errors.InvalidUsageError({
137
- message: "Option 'on_transform_version' must be set when 'record_version' is not 1.",
138
- reason: "missing_transform_version"
139
- });
140
- }
141
- this.record_version = opts.record_version ?? 1;
142
- this.on_transform_version = opts.on_transform_version;
143
- this.on_load_cb = opts.on_load;
144
- this.persist_transformed_on_load = opts.persist_transformed_on_load ?? true;
145
- } else {
146
- if (!opts.derived_collection.initialized) {
147
- throw new import_errors.InvalidUsageError({
148
- message: `Derived collection "${opts.derived_collection.name}" is not yet initialized, this is required in order to construct a transaction based collection.`,
149
- reason: "collection_not_initialized"
150
- });
151
- }
152
- this.name = opts.derived_collection.name;
153
- this._col = opts.derived_collection._col;
154
- this.ttl = opts.derived_collection.ttl;
155
- this.sliding_ttl = opts.derived_collection.sliding_ttl;
156
- this.ttl_enabled = opts.derived_collection.ttl_enabled;
157
- this.db = opts.derived_collection.db;
158
- this.is_transaction = true;
159
- this.record_version = opts.derived_collection.record_version;
160
- this.on_transform_version = opts.derived_collection.on_transform_version;
161
- this.on_load_cb = opts.derived_collection.on_load_cb;
162
- this.persist_transformed_on_load = opts.derived_collection.persist_transformed_on_load;
163
- }
164
- }
165
- // -------------------------------------------------------------------
166
- // Private methods.
167
- // -------------------------------------------------------------------
168
- /**
169
- * Initialize a database query from path or object.
170
- * @throws An error if the input type is incorrect, and optionally if the query is empty.
171
- */
172
- _init_query(query, allow_empty, param_name) {
173
- if (!query || typeof query !== "object" || Array.isArray(query)) {
174
- throw new import_errors.InvalidUsageError({
175
- message: `Parameter "${param_name}" is not a valid query.`,
176
- reason: "invalid_query",
177
- field: param_name
178
- });
179
- }
180
- if (!allow_empty && Object.keys(query).length === 0) {
181
- throw new import_errors.InvalidUsageError({
182
- message: `Parameter "${param_name}" is an empty object.`,
183
- reason: "empty_query",
184
- field: param_name
185
- });
186
- }
187
- return query;
188
- }
189
- /**
190
- * Setup the ttl configuration.
191
- *
192
- * @note When transaction mode is enabled, the session option will not be used.
193
- */
194
- async _setup_ttl() {
195
- this.assert_not_transaction_based();
196
- if (!this.initialized) {
197
- await this.init();
198
- }
199
- this.assert_init();
200
- if (!this.ttl_enabled || this.ttl == null) {
201
- return;
202
- }
203
- const desired_seconds = Math.max(1, Math.ceil(this.ttl / 1e3));
204
- const indexes = await this._col.indexes();
205
- const ttl_index = indexes.find((ix) => ix && typeof ix.key === "object" && ix.key.__ttl_timestamp === 1);
206
- if (!ttl_index) {
207
- await this._col.createIndex({ __ttl_timestamp: 1 }, { expireAfterSeconds: desired_seconds });
208
- return;
209
- }
210
- if (ttl_index.expireAfterSeconds !== desired_seconds) {
211
- let coll_mod_succeeded = false;
212
- try {
213
- await this.db._db.command({
214
- collMod: this.name,
215
- index: {
216
- name: ttl_index.name,
217
- expireAfterSeconds: desired_seconds
218
- }
219
- });
220
- coll_mod_succeeded = true;
221
- } catch (error) {
222
- }
223
- if (!coll_mod_succeeded) {
224
- try {
225
- await this._col.dropIndex(ttl_index.name ?? "__ttl_timestamp_1");
226
- } catch {
227
- }
228
- await this._col.createIndex({ __ttl_timestamp: 1 }, { expireAfterSeconds: desired_seconds });
229
- }
230
- }
231
- }
232
- /**
233
- * Apply the ttl timestamp to a database operation (update doc or pipeline).
234
- * Do not upsert if the user explicitly sets `upsert: false` in the operation.
235
- */
236
- _apply_ttl_to_operation(operation, upsert) {
237
- if (!this.ttl_enabled)
238
- return;
239
- const now = /* @__PURE__ */ new Date();
240
- if (Array.isArray(operation)) {
241
- if (this.sliding_ttl) {
242
- operation.push({ $set: { __ttl_timestamp: now } });
243
- } else {
244
- operation.push({ $set: { __ttl_timestamp: { $ifNull: ["$__ttl_timestamp", now] } } });
245
- }
246
- return;
247
- }
248
- const opKey = this.sliding_ttl ? "$set" : "$setOnInsert";
249
- if (this.sliding_ttl || upsert !== false) {
250
- const bucket = operation[opKey];
251
- if (bucket == null) {
252
- operation[opKey] = { __ttl_timestamp: now };
253
- } else if (typeof bucket === "object") {
254
- bucket.__ttl_timestamp = now;
255
- } else {
256
- throw new import_errors.InvalidUsageError({
257
- message: `Invalid update operator object for TTL control at "${opKey}".`,
258
- reason: "bad_ttl_operator"
259
- });
260
- }
261
- }
262
- }
263
- /**
264
- * Injects `__record_version` into an update **only on insert paths**.
265
- *
266
- * Rules:
267
- * - **Pipeline updates** (`update: Document[]`): no-op here (MongoDB has no `$setOnInsert` in pipelines).
268
- * If you rely on upsert+pipeline, set `__record_version` explicitly in your pipeline.
269
- * - **Replacement doc** (no operators):
270
- * - When `upsert === true`, set `__record_version` **only if missing**.
271
- * - When `upsert !== true`, do nothing (don’t mask older stored versions).
272
- * - **Operator doc**:
273
- * - Respect any user-provided `__record_version` in `$set` or `$setOnInsert`.
274
- * - When `upsert === true` and the user didn’t provide a value, set it via `$setOnInsert`.
275
- *
276
- * Rationale:
277
- * This avoids bumping `__record_version` during normal updates (which would mask older versions)
278
- * while still stamping newly inserted documents.
279
- */
280
- _apply_record_version_to_operation(operation, upsert) {
281
- const current = this.record_version;
282
- if (current == null)
283
- return;
284
- if (Array.isArray(operation))
285
- return;
286
- const op = operation;
287
- const hasDollar = Object.keys(op).some((k) => k[0] === "$");
288
- if (!hasDollar) {
289
- if (!upsert)
290
- return;
291
- if (op.__record_version == null) {
292
- op.__record_version = current;
293
- }
294
- return;
295
- }
296
- const userSet = op?.$set?.__record_version;
297
- const userOnIns = op?.$setOnInsert?.__record_version;
298
- if (userSet != null || userOnIns != null)
299
- return;
300
- if (upsert) {
301
- op.$setOnInsert = { ...op.$setOnInsert ?? {}, __record_version: current };
302
- }
303
- }
304
- /**
305
- * Decide if an error is worth a bounded retry.
306
- * Prefers label-based detection and adds well-known transient/network surfaces.
307
- *
308
- * @param unknown_err The thrown error.
309
- * @returns True for retryable/transient errors; false otherwise.
310
- */
311
- _should_retry_error(unknown_err) {
312
- if (typeof unknown_err !== "object" || !unknown_err || Array.isArray(unknown_err)) {
313
- return false;
314
- }
315
- const err = unknown_err;
316
- const name = err?.name;
317
- const code_name = err?.codeName;
318
- const has_label = (label) => {
319
- if (typeof err?.hasErrorLabel === "function") {
320
- try {
321
- return !!err.hasErrorLabel(label);
322
- } catch {
323
- return false;
324
- }
325
- }
326
- const labels = err?.errorLabels;
327
- return Array.isArray(labels) && labels.includes(label);
328
- };
329
- const raw_code = err?.code;
330
- const numeric_code = typeof raw_code === "number" ? raw_code : typeof raw_code === "string" && /^\d+$/.test(raw_code) ? Number(raw_code) : void 0;
331
- const sys_code = typeof raw_code === "string" && isNaN(Number(raw_code)) ? raw_code : void 0;
332
- const transient_sys = /* @__PURE__ */ new Set([
333
- "ECONNRESET",
334
- "ETIMEDOUT",
335
- "EPIPE",
336
- "ECONNREFUSED",
337
- "ENETUNREACH",
338
- "ENETDOWN",
339
- "EHOSTUNREACH",
340
- "EAI_AGAIN"
341
- ]);
342
- if (name === "AbortError")
343
- return false;
344
- if (has_label("TransientTransactionError") || has_label("UnknownTransactionCommitResult") || has_label("RetryableWriteError")) {
345
- return true;
346
- }
347
- if (name === "MongoNetworkError" || name === "MongoNetworkTimeoutError" || name === "MongoServerSelectionError" || name === "MongoTopologyClosedError" || sys_code && transient_sys.has(sys_code)) {
348
- return true;
349
- }
350
- switch (numeric_code) {
351
- case 6:
352
- return true;
353
- case 7:
354
- return true;
355
- case 50:
356
- return true;
357
- case 89:
358
- return true;
359
- case 91:
360
- return true;
361
- case 112:
362
- return true;
363
- case 189:
364
- return true;
365
- case 262:
366
- return true;
367
- case 10107:
368
- return true;
369
- case 11600:
370
- return true;
371
- case 11602:
372
- return true;
373
- case 13435:
374
- return true;
375
- case 13436:
376
- return true;
377
- case 9001:
378
- return true;
379
- default:
380
- break;
381
- }
382
- if (code_name === "PoolClearedError")
383
- return true;
384
- return false;
385
- }
386
- /**
387
- * Execute an async function with bounded, exponential backoff retries for retryable errors.
388
- *
389
- * - attempts: 1 ⇒ no retry (single execution).
390
- * - Uses small bounded jitter to smooth load (see Collection.Retry).
391
- *
392
- * @param fn The async operation to execute.
393
- * @param retry Number of attempts (1 = no retries) or {@link Collection.Retry.Opts}.
394
- * @returns The function result when successful.
395
- * @throws The last error if not retryable or retries exhausted.
396
- */
397
- async _with_retry(fn, retry) {
398
- const opts = Collection.Retry.normalize(retry);
399
- if (opts.attempts <= 1) {
400
- return await Promise.resolve().then(fn);
401
- }
402
- const last_index = opts.attempts - 1;
403
- for (let i = 0; i < opts.attempts; i++) {
404
- try {
405
- return await Promise.resolve().then(fn);
406
- } catch (err) {
407
- if (!this._should_retry_error(err) || i >= last_index) {
408
- throw err;
409
- }
410
- const delay = Collection.Retry.compute_backoff_delay(i, opts);
411
- if (delay > 0) {
412
- await new Promise((resolve) => setTimeout(resolve, delay));
413
- }
414
- }
415
- }
416
- throw new Error("Unexpected retry loop termination in _with_retry");
417
- }
418
- /**
419
- * Ensure `__record_version` is properly included for projections so version
420
- * transformation can determine the original version reliably.
421
- *
422
- * @param projection The user-specified projection (if any).
423
- * @returns A projection with `__record_version` enforced where needed.
424
- */
425
- _ensure_version_in_projection(projection) {
426
- if (!projection)
427
- return projection;
428
- if (Array.isArray(projection)) {
429
- return projection.includes("__record_version") ? projection : [...projection, "__record_version"];
430
- }
431
- if (Object.values(projection).some((v) => v === 0 || v === false)) {
432
- if (projection["__record_version"] != null) {
433
- const clone = { ...projection };
434
- delete clone["__record_version"];
435
- return clone;
436
- }
437
- return projection;
438
- }
439
- if (projection["__record_version"] !== 1 && projection["__record_version"] !== true) {
440
- return { ...projection, __record_version: 1 };
441
- }
442
- return projection;
443
- }
444
- /**
445
- * Determine whether a projection should be considered partial.
446
- * @param projection The user-specified projection (if any).
447
- * @returns True when a non-empty projection was provided.
448
- */
449
- _is_partial_projection(projection) {
450
- if (!projection)
451
- return false;
452
- if (Array.isArray(projection))
453
- return projection.length > 0;
454
- return Object.keys(projection).length > 0;
455
- }
456
- /**
457
- * Check whether the given update is operator-style (or a pipeline).
458
- * - Aggregation pipeline: Array → valid.
459
- * - Operator update: at least one top-level key starts with '$' → valid.
460
- * - Plain object without '$' keys → NOT valid for updateOne/findOneAndUpdate.
461
- */
462
- _is_operator_update_or_pipeline(operation) {
463
- return Array.isArray(operation) || operation && typeof operation === "object" && Object.keys(operation).some((k) => k[0] === "$");
464
- }
465
- _index_key_signature(keys) {
466
- return Object.entries(keys).map(([k, v]) => `${k}:${v}`).join("|");
467
- }
468
- _keys_equal(a, b) {
469
- const aEnt = Object.entries(a);
470
- const bEnt = Object.entries(b);
471
- if (aEnt.length !== bEnt.length)
472
- return false;
473
- for (let i = 0; i < aEnt.length; i++) {
474
- const [ak, av] = aEnt[i];
475
- const [bk, bv] = bEnt[i];
476
- if (ak !== bk || av !== bv)
477
- return false;
478
- }
479
- return true;
480
- }
481
- _normalize_index_opts(opts) {
482
- let key;
483
- let keys;
484
- let options;
485
- let unique;
486
- let sparse;
487
- let forced = false;
488
- if (typeof opts === "string") {
489
- key = opts;
490
- unique = void 0;
491
- sparse = void 0;
492
- } else {
493
- ({ key, keys, forced = false } = opts);
494
- const user_options = opts.options;
495
- options = user_options ? { ...user_options } : void 0;
496
- if (opts.unique != null && options?.unique != null && opts.unique !== options.unique) {
497
- throw new import_errors.InvalidUsageError({
498
- message: `Encountered different values for attribute 'unique': ${opts.unique} and 'options.unique': ${options.unique}.`,
499
- reason: "invalid_unique_option"
500
- });
501
- }
502
- unique = opts.unique ?? options?.unique;
503
- if (opts.sparse != null && options?.sparse != null && opts.sparse !== options.sparse) {
504
- throw new import_errors.InvalidUsageError({
505
- message: `Encountered different values for attribute 'sparse': ${opts.sparse} and 'options.sparse': ${options.sparse}.`,
506
- reason: "invalid_sparse_option"
507
- });
508
- }
509
- sparse = opts.sparse ?? options?.sparse;
510
- }
511
- if (unique != null) {
512
- options = options || {};
513
- options.unique = unique;
514
- }
515
- if (sparse != null) {
516
- options = options || {};
517
- options.sparse = sparse;
518
- }
519
- let keys_obj;
520
- if (key) {
521
- keys_obj = { [key]: 1 };
522
- } else if (Array.isArray(keys) && keys.length > 0) {
523
- keys_obj = {};
524
- for (const k of keys)
525
- keys_obj[k] = 1;
526
- } else if (keys != null && typeof keys === "object") {
527
- keys_obj = keys;
528
- } else {
529
- throw new import_errors.InvalidUsageError({
530
- message: "Define one of the following parameters: [key, keys].",
531
- reason: "invalid_index_definition"
532
- });
533
- }
534
- return { keys_obj, options, forced };
535
- }
536
- /**
537
- * Drop all indexes that are NOT part of this._init_indexes, excluding _id_ (and TTL index if enabled).
538
- *
539
- * @note We match by key pattern rather than name because names can differ.
540
- */
541
- async _drop_non_init_indexes() {
542
- this.assert_not_transaction_based();
543
- this.assert_init();
544
- const existing = await this._col.listIndexes().toArray();
545
- const desired = /* @__PURE__ */ new Set();
546
- for (const item of this._init_indexes ?? []) {
547
- const { keys_obj } = this._normalize_index_opts(item);
548
- desired.add(this._index_key_signature(keys_obj));
549
- }
550
- const protected_names = /* @__PURE__ */ new Set(["_id_"]);
551
- const keep_ttl = this.ttl_enabled;
552
- const ttl_sig = this._index_key_signature({ __ttl_timestamp: 1 });
553
- for (const ix of existing) {
554
- const name = ix?.name;
555
- if (!name)
556
- continue;
557
- if (protected_names.has(name))
558
- continue;
559
- const keyObj = ix.key;
560
- if (!keyObj)
561
- continue;
562
- const sig = this._index_key_signature(keyObj);
563
- if (desired.has(sig))
564
- continue;
565
- if (keep_ttl && sig === ttl_sig)
566
- continue;
567
- try {
568
- this.db.server.log(3, `Dropping stale index "${name}" on collection: ${this.name}`);
569
- await this._col.dropIndex(name);
570
- } catch (err) {
571
- if (err?.codeName !== "IndexNotFound")
572
- throw err;
573
- }
574
- }
575
- }
576
- /**
577
- * Creates indexes on collections.
578
- *
579
- * @note When transaction mode is enabled, the session option will not be used.
580
- *
581
- * @param opts The index create options.
582
- */
583
- async _create_index(opts) {
584
- this.assert_not_transaction_based();
585
- if (!this.initialized) {
586
- await this.init();
587
- }
588
- this.assert_init();
589
- const { keys_obj, options, forced } = this._normalize_index_opts(opts);
590
- const drop_index = async () => {
591
- const existing = await this._col.listIndexes().toArray();
592
- const match = existing.find((ix) => {
593
- const ix_key = ix?.key;
594
- if (!ix_key)
595
- return false;
596
- return this._keys_equal(ix_key, keys_obj);
597
- });
598
- if (match?.name) {
599
- try {
600
- await this._col.dropIndex(match.name);
601
- } catch (err) {
602
- if (err?.codeName !== "IndexNotFound")
603
- throw err;
604
- }
605
- return;
606
- }
607
- if (options?.name) {
608
- try {
609
- await this._col.dropIndex(options.name);
610
- } catch (err) {
611
- if (err?.codeName !== "IndexNotFound")
612
- throw err;
613
- }
614
- return;
615
- }
616
- const synthesized = Object.entries(keys_obj).map(([k, v]) => `${k}_${v}`).join("_");
617
- try {
618
- await this._col.dropIndex(synthesized);
619
- } catch (err) {
620
- if (err?.codeName !== "IndexNotFound")
621
- throw err;
622
- }
623
- };
624
- try {
625
- try {
626
- return await this._col.createIndex(keys_obj, options);
627
- } catch (err) {
628
- if (forced && err && typeof err === "object" && err.codeName === "IndexKeySpecsConflict") {
629
- await drop_index();
630
- return await this._col.createIndex(keys_obj, options);
631
- }
632
- throw err;
633
- }
634
- } catch (err) {
635
- throw new Error(`Failed to create index on collection "${this.name}": ${err}`, { cause: err });
636
- }
637
- }
638
- // async create_index(opts: string | Collection.IndexOpts): Promise<string> {
639
- // // Not supported on transaction-based collections.
640
- // this.assert_not_transaction_based();
641
- // // Ensure initialized
642
- // if (!this.initialized) { await this.init(); } this.assert_init();
643
- // // ---- Normalize inputs ----
644
- // let key: string | undefined;
645
- // let keys: string[] | Record<string, number> | undefined;
646
- // let options: mongodb.CreateIndexesOptions | undefined;
647
- // let unique: boolean | undefined;
648
- // let sparse: boolean | undefined;
649
- // let forced = false;
650
- // if (typeof opts === "string") {
651
- // key = opts;
652
- // unique = undefined;
653
- // sparse = undefined;
654
- // } else {
655
- // ({ key, keys, forced = false } = opts);
656
- // const options = opts.options as unknown as undefined | mongodb.CreateIndexesOptions;
657
- // // Conflict guard between `unique` and `options.unique`
658
- // if (opts.unique != null && options?.unique != null && opts.unique !== options.unique) {
659
- // throw new InvalidUsageError({
660
- // message: `Encountered different values for attribute 'unique': ${opts.unique} and 'options.unique': ${options.unique}.`,
661
- // reason: "invalid_unique_option",
662
- // });
663
- // }
664
- // unique = opts.unique ?? options?.unique;
665
- // // Conflict guard between `sparse` and `options.sparse`
666
- // if (opts.sparse != null && options?.sparse != null && opts.sparse !== options.sparse) {
667
- // throw new InvalidUsageError({
668
- // message: `Encountered different values for attribute 'sparse': ${opts.sparse} and 'options.sparse': ${options.sparse}.`,
669
- // reason: "invalid_sparse_option",
670
- // });
671
- // }
672
- // sparse = opts.sparse ?? options?.sparse;
673
- // }
674
- // // Ensure `unique` in options when provided
675
- // if (unique) {
676
- // options = options || {};
677
- // options.unique = unique;
678
- // }
679
- // // Ensure `sparse` in options when provided
680
- // if (sparse) {
681
- // options = options || {};
682
- // options.sparse = sparse;
683
- // }
684
- // // Build keys object
685
- // let keys_obj: Record<string, number>;
686
- // if (key) {
687
- // keys_obj = { [key]: 1 };
688
- // } else if (Array.isArray(keys) && keys.length > 0) {
689
- // keys_obj = {};
690
- // for (const k of keys) keys_obj[k] = 1;
691
- // } else if (keys != null && typeof keys === "object") {
692
- // keys_obj = keys as Record<string, number>;
693
- // } else {
694
- // throw new InvalidUsageError({
695
- // message: "Define one of the following parameters: [key, keys].",
696
- // reason: "invalid_index_definition",
697
- // });
698
- // }
699
- // const drop_index = async () => {
700
- // try {
701
- // const existing = await this._col.listIndexes().toArray();
702
- // const match = existing.find(ix => {
703
- // const ix_key = ix?.key as Record<string, number> | undefined;
704
- // if (!ix_key) return false;
705
- // const a = Object.entries(ix_key);
706
- // const b = Object.entries(keys_obj);
707
- // if (a.length !== b.length) return false;
708
- // // exact key-value equality (order-insensitive)
709
- // const as = new Map(a);
710
- // for (const [kk, vv] of b) {
711
- // if (as.get(kk) !== vv) return false;
712
- // }
713
- // return true;
714
- // });
715
- // // Prefer matched key's real name
716
- // if (match?.name) {
717
- // try { await this._col.dropIndex(match.name); }
718
- // catch (err: any) { if (err?.codeName !== "IndexNotFound") throw err; }
719
- // } else if (options?.name) {
720
- // try { await this._col.dropIndex(options.name); }
721
- // catch (err: any) { if (err?.codeName !== "IndexNotFound") throw err; }
722
- // } else {
723
- // // last-resort synthesized name (simple cases)
724
- // const synthesized = Object.entries(keys_obj).map(([k, v]) => `${k}_${v}`).join("_");
725
- // try { await this._col.dropIndex(synthesized); }
726
- // catch (err: any) { if (err?.codeName !== "IndexNotFound") throw err; }
727
- // }
728
- // } catch (err) {
729
- // // If listIndexes itself fails for some reason, do not hide the error
730
- // throw new Error(`Failed to create index on collection "${this.name}": ${err}`, { cause: err });
731
- // }
732
- // }
733
- // try {
734
- // // Create (or re-create)
735
- // try {
736
- // return await this._col.createIndex(keys_obj, options);
737
- // }
738
- // // Retry once on IndexKeySpecsConflict when forced=true
739
- // catch (err) {
740
- // if (forced && err && typeof err === "object" && (
741
- // (err as any).codeName === "IndexKeySpecsConflict"
742
- // )) {
743
- // await drop_index();
744
- // return await this._col.createIndex(keys_obj, options);
745
- // }
746
- // throw err;
747
- // }
748
- // } catch (err) {
749
- // throw new Error(`Failed to create index on collection "${this.name}": ${err}`, { cause: err });
750
- // }
751
- // }
752
- // -------------------------------------------------------------------
753
- // Public methods.
754
- // -------------------------------------------------------------------
755
- /**
756
- * Initialize the collection, creating indexes and setting up TTL if needed.
757
- * @returns The initialized collection instance.
758
- *
759
- * @docs
760
- */
761
- async init() {
762
- if (this.initialized === false) {
763
- this.db.server.log(3, "Initializing collection: ", this.name);
764
- if (!this.is_transaction) {
765
- if (this._col == null) {
766
- this.db.server.log(3, "Checking collection: ", this.name);
767
- if (!this.db.server.production) {
768
- await this.db.ensure_connection();
769
- }
770
- if (!this.db.connected || !this.db._db) {
771
- throw new import_errors.InvalidUsageError({
772
- message: `Database client is not connected.`,
773
- reason: "client_not_connected"
774
- });
775
- }
776
- if (this.db._listed_cols == null) {
777
- this.db.server.log(3, "Listing collections...");
778
- this.db._listed_cols = await this.db._db.listCollections().toArray();
779
- this.db.server.log(3, "Listed collections: " + this.db._listed_cols.map((x) => x.name).join(", "));
780
- }
781
- if (!this.db._listed_cols.find((x) => x.name === this.name)) {
782
- this.db.server.log(3, "Creating collection: " + this.name);
783
- let create_col_retries = 3;
784
- let last_error = null;
785
- let collection_created = false;
786
- while (create_col_retries > 0 && !collection_created) {
787
- try {
788
- await this.db._db.createCollection(this.name);
789
- collection_created = true;
790
- } catch (error) {
791
- last_error = error;
792
- if (error.codeName === "NamespaceExists") {
793
- collection_created = true;
794
- } else if (create_col_retries > 1 && (error.code === 11e3 || error.code === 48)) {
795
- create_col_retries--;
796
- await new Promise((r) => setTimeout(r, 100));
797
- } else {
798
- throw error;
799
- }
800
- }
801
- }
802
- if (!collection_created && last_error) {
803
- throw last_error;
804
- }
805
- }
806
- this.db.server.log(3, "Initializing mongodb collection connection: " + this.name);
807
- this._col = this.db._db.collection(this.name);
808
- }
809
- this.initialized = true;
810
- if (this.ttl_enabled) {
811
- this.db.server.log(3, "Setting up TTL index for collection: " + this.name);
812
- await this._setup_ttl();
813
- }
814
- await this._drop_non_init_indexes();
815
- if (this._init_indexes?.length) {
816
- for (const item of this._init_indexes) {
817
- this.db.server.log(3, "Creating index " + JSON.stringify(item) + " on collection: " + this.name);
818
- await this._create_index(item);
819
- }
820
- }
821
- } else {
822
- if (!this.db.client) {
823
- throw new import_errors.InvalidUsageError({
824
- message: "Database client is not initialized, this is likely because you did not initialize the transaction based collection through 'Collection.start_transaction'.",
825
- reason: "client_not_connected"
826
- });
827
- }
828
- if (!this._col) {
829
- throw new import_errors.InvalidUsageError({
830
- message: "Derived collection is not initialized, this should have been initialized before passing it to a transaction based collection constructor.",
831
- reason: "derived_collection_not_initialized"
832
- });
833
- }
834
- this._session = this.db.client.startSession();
835
- this._session.startTransaction();
836
- this.initialized = true;
837
- }
838
- }
839
- return this;
840
- }
841
- /**
842
- * Assert that the collection is initialized and has a valid MongoDB collection.
843
- * @throws {Error} Throws if the collection is not initialized or _col is null
844
- * @returns An initialized collection type assertion
845
- *
846
- * @docs
847
- */
848
- assert_init() {
849
- if (!this.initialized || this._col == null) {
850
- throw new import_errors.InvalidUsageError({
851
- message: `Collection "${this.name}" is not initialized.`,
852
- reason: "collection_not_initialized"
853
- });
854
- }
855
- }
856
- /**
857
- * Assert that if this is a transaction, it has not been finalized.
858
- * @throws Error if this is a finalized transaction.
859
- *
860
- * @docs
861
- */
862
- assert_not_finalized() {
863
- if (this.is_transaction && this.is_finalized_transaction) {
864
- throw new import_errors.InvalidUsageError({
865
- message: `Transaction has already been finalized (committed or aborted).`,
866
- reason: "transaction_finalized"
867
- });
868
- }
869
- }
870
- /**
871
- * Assert that this collection is not transaction based.
872
- *
873
- * @docs
874
- */
875
- assert_not_transaction_based() {
876
- if (this.is_transaction) {
877
- throw new import_errors.InvalidUsageError({
878
- message: `Collection "${this.name}" is transaction based.`,
879
- reason: "collection_is_transaction"
880
- });
881
- }
882
- }
883
- /**
884
- * Get operation options with session if this is a transaction.
885
- * @returns Options object with session if applicable.
886
- *
887
- * @docs
888
- */
889
- get_operation_options(opts) {
890
- if (this.is_transaction && this._session) {
891
- return { ...opts, session: this._session };
892
- }
893
- return opts ?? {};
894
- }
895
- /**
896
- * Get the raw and initialized MongoDB collection.
897
- * @returns The MongoDB collection instance.
898
- *
899
- * @docs
900
- */
901
- async col() {
902
- await this.init();
903
- return this._col;
904
- }
905
- /**
906
- * Check if an index exists.
907
- * @note Not supported for transaction based collections.
908
- * @param index The name of the index to check.
909
- * @returns True if the index exists, false otherwise.
910
- *
911
- * @docs
912
- */
913
- async has_index(index) {
914
- if (!this.initialized) {
915
- await this.init();
916
- }
917
- this.assert_init();
918
- this.assert_not_finalized();
919
- this.assert_not_transaction_based();
920
- return (await this._col.listIndexes().toArray()).some((x) => x.name === index);
921
- }
922
- /**
923
- * Standalone helper: merge `source` into `target` for missing keys only.
924
- * Clones assigned nested objects/arrays/dates once (when `clone` is true).
925
- *
926
- * @throws An error if the max depth recursion depth has been exceeded.
927
- *
928
- * @docs
929
- */
930
- static insert_defaults(target, source, opts = {}) {
931
- const max_depth = opts.max_depth ?? 1e3;
932
- const depth = opts.depth ?? 0;
933
- const should_clone = opts.clone ?? true;
934
- const isPlainObject = (v) => v != null && typeof v === "object" && Object.getPrototypeOf(v) === Object.prototype;
935
- const cloneAssigned = (val, d) => {
936
- if (!should_clone)
937
- return val;
938
- if (d > max_depth)
939
- return val;
940
- if (Array.isArray(val)) {
941
- return val.map((item) => cloneAssigned(item, d + 1));
942
- }
943
- if (val instanceof Date) {
944
- return new Date(val.getTime());
945
- }
946
- if (isPlainObject(val)) {
947
- const out = {};
948
- for (const k of Object.keys(val)) {
949
- out[k] = cloneAssigned(val[k], d + 1);
950
- }
951
- return out;
952
- }
953
- return val;
954
- };
955
- if (depth > max_depth) {
956
- throw new Error(`Maximum recursion depth (${max_depth}) exceeded in 'insert_defaults'`);
957
- }
958
- for (const key of Object.keys(source)) {
959
- const v = target[key];
960
- const d = source[key];
961
- if (v === void 0) {
962
- target[key] = cloneAssigned(d, depth + 1);
963
- } else if (isPlainObject(v) && isPlainObject(d)) {
964
- Collection.insert_defaults(v, d, { depth: depth + 1, max_depth, clone: should_clone });
965
- }
966
- }
967
- }
968
- flatten(obj, prefix = "") {
969
- return (0, import_flatten.flatten)(obj, prefix);
970
- }
971
- /**
972
- * Execute `on_transform_version` and `on_load_cb` on a loaded document.
973
- * Ensures `__record_version` is set when {@link record_version} is defined.
974
- *
975
- * @note This is done automatically during load operations.
976
- *
977
- * @param data The loaded document.
978
- * @param opts Additional options.
979
- *
980
- * @returns The transformed document.
981
- *
982
- * @throws {Collection.OnTransformError} When an error occurs during the {@link Collection.Opts.on_transform_version} callback.
983
- * @throws {Collection.OnLoadError} When an error occurs during the {@link Collection.Opts.on_load} callback.
984
- *
985
- * @docs
986
- */
987
- async apply_on_load(data, opts) {
988
- let transformed = false;
989
- const is_partial = this._is_partial_projection(opts.projection);
990
- if (this.record_version != null && this.on_transform_version != null && data && data.__record_version !== this.record_version) {
991
- try {
992
- data = await this.on_transform_version(data, {
993
- from_version: data.__record_version,
994
- to_version: this.record_version,
995
- projection: opts.projection,
996
- is_partial
997
- });
998
- transformed = true;
999
- } catch (error) {
1000
- throw new Collection.OnTransformError({
1001
- message: `Failed to transform document from version '${data.__record_version}' to '${this.record_version}'.`,
1002
- query: {},
1003
- reason: "callback_error",
1004
- cause: error
1005
- });
1006
- }
1007
- data.__record_version = this.record_version;
1008
- }
1009
- if (this.on_load_cb) {
1010
- try {
1011
- data = await this.on_load_cb(data, {
1012
- projection: opts.projection,
1013
- is_partial
1014
- });
1015
- } catch (error) {
1016
- throw new Collection.OnLoadError({
1017
- message: `Encountered an error during the 'on_load' callback.`,
1018
- query: {},
1019
- reason: "callback_error",
1020
- cause: error
1021
- });
1022
- }
1023
- }
1024
- if (transformed && this.persist_transformed_on_load && opts.persist && // only persist if doc came from DB (not a default)
1025
- !is_partial && // only when we have a full document
1026
- data?._id != null) {
1027
- try {
1028
- if (this.persist_transformed_on_load === "replace") {
1029
- const replace_doc = { ...data };
1030
- if (this.ttl_enabled && replace_doc.__ttl_timestamp == null) {
1031
- replace_doc.__ttl_timestamp = /* @__PURE__ */ new Date();
1032
- }
1033
- if (this.record_version != null && replace_doc.__record_version == null) {
1034
- replace_doc.__record_version = this.record_version;
1035
- }
1036
- const res = this.replace(
1037
- { _id: data._id },
1038
- replace_doc,
1039
- { upsert: false, throw: false, apply_ttl: false }
1040
- // do not create on read
1041
- );
1042
- if (opts.await_persist) {
1043
- await res;
1044
- } else {
1045
- void res;
1046
- }
1047
- } else {
1048
- const set_doc = { ...data };
1049
- delete set_doc._id;
1050
- delete set_doc.__ttl_timestamp;
1051
- const res = this.save(
1052
- { _id: data._id },
1053
- { $set: set_doc },
1054
- { upsert: false, throw: false, apply_ttl: false }
1055
- // do not create on read
1056
- );
1057
- if (opts.await_persist) {
1058
- await res;
1059
- } else {
1060
- void res;
1061
- }
1062
- }
1063
- } catch {
1064
- }
1065
- }
1066
- return data;
1067
- }
1068
- /**
1069
- * Count documents accurately using MongoDB's `countDocuments`.
1070
- *
1071
- * @param query An optional filter to count matching documents. When omitted, counts all documents.
1072
- * @param opts Additional options, see {@link Collection.CountOpts}.
1073
- *
1074
- * @note The `opts.throw` option defaults to `true`.
1075
- *
1076
- * @returns
1077
- * - A number representing the accurate count when successful.
1078
- * - A {@link Collection.CountError} when `opts.throw === false` and an error occurs.
1079
- *
1080
- * @throws {Collection.CountError} When `throw !== false` and the count fails.
1081
- * @throws {InvalidUsageError} (always) When the provided argument(s) are invalid or if the collection was not used properly.
1082
- *
1083
- * @docs
1084
- */
1085
- async count(query, opts) {
1086
- if (!this.initialized) {
1087
- await this.init();
1088
- }
1089
- this.assert_init();
1090
- this.assert_not_finalized();
1091
- const query_op = this._init_query(query ?? {}, true, "query");
1092
- const throw_errors = opts?.throw ?? true;
1093
- try {
1094
- const n = await this._with_retry(() => this._col.countDocuments(query_op, this.get_operation_options(typeof opts?.timeout === "number" ? { maxTimeMS: opts.timeout } : {})), opts?.retry);
1095
- return n;
1096
- } catch (e) {
1097
- const err = new Collection.CountError({
1098
- message: "Count operation failed due to an unexpected error.",
1099
- query: query_op,
1100
- reason: this._should_retry_error(e) ? Collection.Retry.get_attempts(opts?.retry) > 1 ? "retries_exhausted" : "retryable" : "unknown",
1101
- cause: e
1102
- });
1103
- if (throw_errors)
1104
- throw err;
1105
- return err;
1106
- }
1107
- }
1108
- /**
1109
- * Return a fast, approximate count of the entire collection using
1110
- * MongoDB's `estimatedDocumentCount`. This method does **not** accept
1111
- * a filter and may be off under heavy churn.
1112
- *
1113
- * @param opts Additional options, see {@link Collection.CountOpts}.
1114
- *
1115
- * @note The `opts.throw` option defaults to `true`.
1116
- *
1117
- * @returns
1118
- * - A number representing the estimated total number of documents when successful.
1119
- * - A {@link Collection.CountError} when `opts.throw === false` and an error occurs.
1120
- *
1121
- * @throws {Collection.CountError} When `throw !== false` and the count fails.
1122
- * @throws {InvalidUsageError} (always) When the collection was not used properly.
1123
- *
1124
- * @docs
1125
- */
1126
- async count_estimated(opts) {
1127
- if (!this.initialized) {
1128
- await this.init();
1129
- }
1130
- this.assert_init();
1131
- this.assert_not_finalized();
1132
- const throw_errors = opts?.throw ?? true;
1133
- try {
1134
- const n = await this._with_retry(() => this._col.estimatedDocumentCount(this.get_operation_options(typeof opts?.timeout === "number" ? { maxTimeMS: opts.timeout } : {})), opts?.retry);
1135
- return n;
1136
- } catch (e) {
1137
- const err = new Collection.CountError({
1138
- message: "Estimated count operation failed due to an unexpected error.",
1139
- query: {},
1140
- // no filter for estimatedDocumentCount
1141
- reason: this._should_retry_error(e) ? Collection.Retry.get_attempts(opts?.retry) > 1 ? "retries_exhausted" : "retryable" : "unknown",
1142
- cause: e
1143
- });
1144
- if (throw_errors)
1145
- throw err;
1146
- return err;
1147
- }
1148
- }
1149
- /**
1150
- * List all documents for a specific query.
1151
- *
1152
- * @param query The database directory path.
1153
- * @param opts The list options, see {@link Collection.ListOpts}.
1154
- * @param allow_empty_query When `true`, allows an empty query (i.e. `{}`) to be passed, which would otherwise throw an error.
1155
- *
1156
- * @note The `opts.throw` option defaults to `true`.
1157
- * @note The {@link Collection.Opts.on_load} and {@link Collection.Opts.on_transform_version} callbacks
1158
- * are not executed when `opts.cursor === true`.
1159
- * @note When `opts.callback` is a function (and `opts.cursor !== true`), this method streams documents and
1160
- * invokes the callback for each processed document, then returns `undefined` on success.
1161
- * This mode is memory-friendly and avoids accumulating the entire result set.
1162
- *
1163
- * @returns
1164
- * - An error if `opts.throw === false` and a {@link Collection.ListError} has occurred.
1165
- * - The find cursor when `opts.cursor === true`.
1166
- * - When `opts.callback && !opts.cursor` is provided, `undefined` on success.
1167
- * - When `opts.page_info === true && !opts.cursor && !opts.callback`, returns {@link Collection.ListedPage}.
1168
- * - Otherwise, an array of documents matching the path.
1169
- *
1170
- * @throws {Collection.ListError} When `throw !== false` if an error occurred during the operation, in which case {@link Collection.ListError.cause} is defined.
1171
- * @throws {InvalidUsageError} (always) When the provided argument(s) are invalid or if the collection was not used properly.
1172
- *
1173
- * @docs
1174
- */
1175
- async list(query, opts, allow_empty_query = false) {
1176
- if (!this.initialized) {
1177
- await this.init();
1178
- }
1179
- this.assert_init();
1180
- this.assert_not_finalized();
1181
- const throw_errors = opts?.throw ?? true;
1182
- const has_callback = typeof opts?.callback === "function";
1183
- const page_info_requested = opts?.page_info === true && opts?.cursor !== true && !has_callback;
1184
- if (has_callback && opts?.cursor === true) {
1185
- throw new import_errors.InvalidUsageError({
1186
- message: "Option 'callback' cannot be combined with 'cursor: true'.",
1187
- reason: "invalid_option_combination",
1188
- field: "opts.callback"
1189
- });
1190
- }
1191
- if (has_callback && opts?.page_info === true) {
1192
- throw new import_errors.InvalidUsageError({
1193
- message: "Option 'callback' cannot be combined with 'page_info: true'.",
1194
- reason: "invalid_option_combination",
1195
- field: "opts.callback"
1196
- });
1197
- }
1198
- const user_limit = opts?.limit;
1199
- if (typeof user_limit === "number") {
1200
- const effective_user_limit = page_info_requested ? user_limit + 1 : user_limit;
1201
- const is_integer = Number.isInteger(user_limit);
1202
- const is_valid = user_limit >= 0 && Number.isFinite(effective_user_limit);
1203
- if (!is_integer || !is_valid) {
1204
- throw new import_errors.InvalidUsageError({
1205
- message: `Option 'limit' must be a non-negative finite integer${page_info_requested ? " (including +1 for pagination)." : "."}`,
1206
- reason: "invalid_limit",
1207
- field: "opts.limit"
1208
- });
1209
- }
1210
- }
1211
- const probing_limit = typeof user_limit === "number" && page_info_requested ? user_limit + 1 : user_limit;
1212
- if (opts?.skip != null) {
1213
- if (!Number.isInteger(opts.skip) || opts.skip < 0) {
1214
- throw new import_errors.InvalidUsageError({
1215
- message: "Option 'skip' must be a non-negative integer.",
1216
- reason: "invalid_skip",
1217
- field: "opts.skip"
1218
- });
1219
- }
1220
- }
1221
- if (user_limit === 0 && !opts?.cursor) {
1222
- if (has_callback) {
1223
- return void 0;
1224
- }
1225
- return page_info_requested ? { items: [], has_more: false } : [];
1226
- }
1227
- let batch_size = typeof opts?.pagination?.batch_size === "number" ? Math.floor(opts.pagination.batch_size) : 1e3;
1228
- if (!Number.isFinite(batch_size) || batch_size < 1 || batch_size > 1e4) {
1229
- throw new import_errors.InvalidUsageError({
1230
- message: "Option `pagination.batch_size` must be an integer between '1' and '10000'.",
1231
- reason: "invalid_pagination_batch_size",
1232
- field: "opts.pagination.batch_size"
1233
- });
1234
- }
1235
- if (typeof probing_limit === "number" && probing_limit > 0 && probing_limit < 1e4) {
1236
- batch_size = Math.min(batch_size, probing_limit);
1237
- }
1238
- const query_op = this._init_query(query, allow_empty_query, "query");
1239
- const find_options = {
1240
- projection: opts?.projection ? Collection.Projection.init(this._ensure_version_in_projection(opts.projection)) : void 0,
1241
- sort: opts?.sort,
1242
- skip: opts?.skip,
1243
- // no default so we can stream all docs if no limit was set.
1244
- // allow +1 probe for page_info
1245
- limit: probing_limit
1246
- };
1247
- if (typeof opts?.timeout === "number") {
1248
- find_options.maxTimeMS = opts.timeout;
1249
- }
1250
- try {
1251
- const cursor = await this._with_retry(() => this._col.find(query_op, this.get_operation_options(find_options)), opts?.retry);
1252
- cursor.batchSize(batch_size);
1253
- if (typeof opts?.timeout === "number") {
1254
- cursor.maxTimeMS(opts.timeout);
1255
- }
1256
- if (opts?.cursor)
1257
- return cursor;
1258
- if (has_callback) {
1259
- const max_docs2 = user_limit ?? Number.POSITIVE_INFINITY;
1260
- let processed_count = 0;
1261
- try {
1262
- while (processed_count < max_docs2) {
1263
- const first = await this._with_retry(() => cursor.next(), opts?.retry);
1264
- if (first == null)
1265
- break;
1266
- let processed = first;
1267
- if (processed && typeof processed === "object") {
1268
- processed = await this.apply_on_load(processed, {
1269
- projection: opts?.projection,
1270
- persist: true,
1271
- await_persist: false
1272
- });
1273
- }
1274
- try {
1275
- await opts.callback(processed);
1276
- } catch (cb_err) {
1277
- throw new Collection.ListError({
1278
- message: "List callback failed for a streamed document.",
1279
- query: query_op,
1280
- reason: "callback_error",
1281
- cause: cb_err
1282
- });
1283
- }
1284
- processed_count++;
1285
- if (processed_count >= max_docs2)
1286
- break;
1287
- let drained = 1;
1288
- while (drained < batch_size && processed_count < max_docs2) {
1289
- const next_in_buffer = await cursor.tryNext();
1290
- if (next_in_buffer == null)
1291
- break;
1292
- let processed2 = next_in_buffer;
1293
- if (processed2 && typeof processed2 === "object") {
1294
- processed2 = await this.apply_on_load(processed2, {
1295
- projection: opts?.projection,
1296
- persist: true,
1297
- await_persist: false
1298
- });
1299
- }
1300
- try {
1301
- await opts.callback(processed2);
1302
- } catch (cb_err) {
1303
- throw new Collection.ListError({
1304
- message: "List callback failed for a streamed document.",
1305
- query: query_op,
1306
- reason: "callback_error",
1307
- cause: cb_err
1308
- });
1309
- }
1310
- processed_count++;
1311
- drained++;
1312
- }
1313
- }
1314
- } finally {
1315
- if (!cursor.closed) {
1316
- await cursor.close().catch(() => {
1317
- });
1318
- }
1319
- }
1320
- return void 0;
1321
- }
1322
- const max_docs = user_limit ?? Number.POSITIVE_INFINITY;
1323
- const target = page_info_requested && typeof user_limit === "number" ? user_limit + 1 : max_docs;
1324
- const docs = [];
1325
- let fetched = 0;
1326
- try {
1327
- while (fetched < target) {
1328
- const first = await this._with_retry(() => cursor.next(), opts?.retry);
1329
- if (first == null) {
1330
- break;
1331
- }
1332
- let processed = first;
1333
- if (processed && typeof processed === "object") {
1334
- processed = await this.apply_on_load(processed, {
1335
- projection: opts?.projection,
1336
- persist: true,
1337
- await_persist: false
1338
- });
1339
- }
1340
- docs.push(processed);
1341
- fetched++;
1342
- if (fetched >= target) {
1343
- break;
1344
- }
1345
- let drained = 1;
1346
- while (drained < batch_size && fetched < target) {
1347
- const next_in_buffer = await cursor.tryNext();
1348
- if (next_in_buffer == null) {
1349
- break;
1350
- }
1351
- let processed2 = next_in_buffer;
1352
- if (processed2 && typeof processed2 === "object") {
1353
- processed2 = await this.apply_on_load(processed2, {
1354
- projection: opts?.projection,
1355
- persist: true,
1356
- await_persist: false
1357
- });
1358
- }
1359
- docs.push(processed2);
1360
- fetched++;
1361
- drained++;
1362
- }
1363
- }
1364
- } finally {
1365
- if (!cursor.closed) {
1366
- await cursor.close().catch(() => {
1367
- });
1368
- }
1369
- }
1370
- if (page_info_requested) {
1371
- let has_more = false;
1372
- let out = docs;
1373
- if (typeof user_limit === "number" && docs.length > user_limit) {
1374
- has_more = true;
1375
- out = docs.slice(0, user_limit);
1376
- }
1377
- return { items: out, has_more };
1378
- }
1379
- if (docs.length > max_docs && max_docs !== Number.POSITIVE_INFINITY) {
1380
- return docs.slice(0, max_docs);
1381
- }
1382
- return docs;
1383
- } catch (e) {
1384
- if (e instanceof Collection.ListError) {
1385
- if (throw_errors)
1386
- throw e;
1387
- return e;
1388
- }
1389
- const error = new Collection.ListError({
1390
- message: "Encountered an error while listing documents.",
1391
- query: query_op,
1392
- reason: this._should_retry_error(e) ? Collection.Retry.get_attempts(opts?.retry) > 1 ? "retries_exhausted" : "retryable" : "unknown",
1393
- cause: e
1394
- });
1395
- if (throw_errors)
1396
- throw error;
1397
- return error;
1398
- }
1399
- }
1400
- /**
1401
- * List all documents of the collection.
1402
- *
1403
- * @param opts The list options, see {@link Collection.ListOpts}.
1404
- *
1405
- * @note The `opts.throw` option defaults to `true`.
1406
- * @note The {@link Collection.Opts.on_load} and {@link Collection.Opts.on_transform_version} callbacks
1407
- * are not executed when `opts.cursor === true`.
1408
- * @note When `opts.callback` is a function (and `opts.cursor !== true`), this method streams documents and
1409
- * invokes the callback for each processed document, then returns `undefined` on success.
1410
- *
1411
- * @returns
1412
- * - Array of all documents in the collection.
1413
- * - The find cursor when `opts.cursor === true`.
1414
- * - `undefined` when `opts.callback && !opts.cursor`.
1415
- * - An error if `opts.throw === false` and a {@link Collection.ListError} has occurred.
1416
- *
1417
- * @throws {Collection.ListError} When `throw !== false` if an error occurred during the operation, in which case {@link Collection.ListError.cause} is defined.
1418
- * @throws {InvalidUsageError} (always) When the provided argument(s) are invalid or if the collection was not used properly.
1419
- *
1420
- * @docs
1421
- */
1422
- async list_all(opts) {
1423
- return this.list({}, opts, true);
1424
- }
1425
- /**
1426
- * Check if a document exists by only loading the document's id.
1427
- *
1428
- * @param query The database path to the document.
1429
- * @param opts The exists options, see {@link Collection.ExistsOpts}.
1430
- *
1431
- * @note The `opts.throw` option defaults to `true`.
1432
- * @note This method does not execute the {@link Collection.Opts.on_load}
1433
- * and {@link Collection.Opts.on_transform_version} callbacks.
1434
- *
1435
- * @returns
1436
- * - An error if `opts.throw === false` and a {@link Collection.ExistsError} has occurred.
1437
- * - True if the document exists, false otherwise.
1438
- *
1439
- * @throws {Collection.ExistsError} When `throw !== false` if an error occurred during the operation, in which case {@link Collection.ExistsError.cause} is defined.
1440
- * @throws {InvalidUsageError} (always) When the provided argument(s) are invalid or if the collection was not used properly.
1441
- *
1442
- * @docs
1443
- */
1444
- async exists(query, opts) {
1445
- if (!this.initialized) {
1446
- await this.init();
1447
- }
1448
- this.assert_init();
1449
- this.assert_not_finalized();
1450
- const query_op = this._init_query(query, false, "query");
1451
- const throw_errors = opts?.throw ?? true;
1452
- try {
1453
- const find_opts = {
1454
- projection: { _id: 1 }
1455
- };
1456
- if (typeof opts?.timeout === "number") {
1457
- find_opts.maxTimeMS = opts.timeout;
1458
- }
1459
- const doc = await this._with_retry(() => this._col.findOne(query_op, this.get_operation_options(find_opts)), opts?.retry);
1460
- return doc != null;
1461
- } catch (e) {
1462
- const err = new Collection.ExistsError({
1463
- message: "Failed to check if the queried document exists due to an unexpected error.",
1464
- query: query_op,
1465
- reason: this._should_retry_error(e) ? Collection.Retry.get_attempts(opts?.retry) > 1 ? "retries_exhausted" : "retryable" : "unknown",
1466
- cause: e
1467
- });
1468
- if (throw_errors)
1469
- throw err;
1470
- return err;
1471
- }
1472
- }
1473
- /**
1474
- * Load a single document by query.
1475
- *
1476
- * Applies an optional projection and, if a `default` is provided, inserts any
1477
- * missing keys from the default into the loaded document (values are deep-cloned).
1478
- *
1479
- * @note The `default` value is deep-cloned if it is returned or inserted.
1480
- * @note The `opts.throw` option defaults to `true`.
1481
- *
1482
- * @param query The database query.
1483
- * @param opts Additional load options {@link Collection.LoadOpts}.
1484
- *
1485
- * @returns
1486
- * - When `opts.throw === false`:
1487
- * - If found: the loaded (projected) document.
1488
- * - If not found and `opts.default` is provided: the deep-cloned default data.
1489
- * - If not found and no default: a {@link Collection.NotFoundError}.
1490
- * - On load failure: a {@link Collection.LoadError}.
1491
- * - When `opts.throw !== false` (default):
1492
- * - If found: the loaded (projected) document.
1493
- * - If not found and `opts.default` is provided: the deep-cloned default data.
1494
- * - If not found and no default: a {@link Collection.NotFoundError} is **thrown**.
1495
- * - On load failure: a {@link Collection.LoadError} is **thrown**.
1496
- *
1497
- * @throws {Collection.LoadError} Only when `opts.throw !== false` and the load fails.
1498
- * @throws {Collection.NotFoundError} When the document is not found and `opts.throw !== false && opts.default == null`.
1499
- * @throws {InvalidUsageError} When the provided arguments are invalid or if the collection was not used properly.
1500
- *
1501
- * @docs
1502
- */
1503
- async load(query, opts) {
1504
- if (!this.initialized) {
1505
- await this.init();
1506
- }
1507
- this.assert_init();
1508
- this.assert_not_finalized();
1509
- const retry = opts?.retry;
1510
- const throw_errors = opts?.throw ?? true;
1511
- const find_query = this._init_query(query, false, "query");
1512
- const base_find = {};
1513
- if (opts?.projection)
1514
- base_find.projection = Collection.Projection.init(this._ensure_version_in_projection(opts.projection));
1515
- if (typeof opts?.timeout === "number")
1516
- base_find.maxTimeMS = opts.timeout;
1517
- const find_opts = this.get_operation_options(base_find);
1518
- try {
1519
- const doc = await this._with_retry(() => this._col.findOne(find_query, find_opts), opts?.retry);
1520
- if (!doc) {
1521
- if (opts?.default) {
1522
- let default_doc;
1523
- if (typeof opts.default === "function") {
1524
- default_doc = vlib.Object.deep_copy(opts.default());
1525
- } else {
1526
- default_doc = vlib.Object.deep_copy(opts.default);
1527
- }
1528
- if (default_doc._id == null) {
1529
- default_doc._id = new mongodb.ObjectId();
1530
- }
1531
- if (this.record_version != null) {
1532
- default_doc.__record_version = this.record_version;
1533
- }
1534
- let out = default_doc;
1535
- const is_partial = this._is_partial_projection(opts?.projection);
1536
- out = await this.apply_on_load(out, {
1537
- projection: opts?.projection,
1538
- persist: false,
1539
- // do not persist defaults.
1540
- await_persist: true
1541
- });
1542
- return out;
1543
- }
1544
- const err = new Collection.NotFoundError({
1545
- message: "Document not found.",
1546
- query: find_query,
1547
- reason: "not_found"
1548
- });
1549
- if (throw_errors)
1550
- throw err;
1551
- return err;
1552
- }
1553
- let working = doc;
1554
- if (opts?.default) {
1555
- if (typeof opts.default === "function") {
1556
- Collection.insert_defaults(working, opts.default(), { clone: true });
1557
- } else {
1558
- Collection.insert_defaults(working, opts.default, { clone: true });
1559
- }
1560
- }
1561
- working = await this.apply_on_load(working, {
1562
- projection: opts?.projection,
1563
- persist: true,
1564
- await_persist: true
1565
- });
1566
- return working;
1567
- } catch (e) {
1568
- if (e instanceof Collection.NotFoundError) {
1569
- if (throw_errors)
1570
- throw e;
1571
- return e;
1572
- }
1573
- const err = new Collection.LoadError({
1574
- message: "Load failed due to an unexpected error.",
1575
- query: find_query,
1576
- reason: this._should_retry_error(e) ? Collection.Retry.get_attempts(retry) > 1 ? "retries_exhausted" : "retryable" : "unknown",
1577
- cause: e
1578
- });
1579
- if (throw_errors)
1580
- throw err;
1581
- return err;
1582
- }
1583
- }
1584
- /**
1585
- * Save data with predefined `$set` behaviour.
1586
- * When the document already exists this function only updates the specified content attributes.
1587
- * When a document does not exist it will automatically be created, unless `opts.upsert !== false`.
1588
- *
1589
- * @param query The database query / path to the document.
1590
- * @param content The data to save.
1591
- * @param opts Additional options, see {@link Collection.SetOpts}.
1592
- *
1593
- * @note The `opts.throw` option defaults to `true`.
1594
- * @note The `opts.upsert` option defaults to `true`.
1595
- * @note `set()` does not deep-merge nested objects.
1596
- * With `flatten: false`, nested objects are written as whole objects—so their keys are replaced
1597
- * by exactly what you provide (missing nested keys can be overwritten/removed).
1598
- * With `flatten: true`, nested objects are flattened into dot notation, allowing you to update specific nested keys without affecting siblings.
1599
- *
1600
- * @returns
1601
- * - When `opts.bulk === true`: an unexecuted bulk operation.
1602
- * - When `opts.return === true`: the **updated** document; or a {@link Collection.SaveError} when `throw:false` and a write failure occurs.
1603
- * - Otherwise: `undefined` on success; or a {@link Collection.SaveError} when `throw:false` and a write failure occurs.
1604
- *
1605
- * @throws {Collection.SaveError} Only when `opts.throw !== false` and the write fails.
1606
- * @throws {InvalidUsageError} (always) When the provided argument(s) are invalid or if the collection was not used properly.
1607
- *
1608
- * @docs
1609
- */
1610
- async set(query, content, opts) {
1611
- if (opts?.flatten)
1612
- content = this.flatten(content);
1613
- const operation = { $set: content };
1614
- return await this.save(query, operation, opts);
1615
- }
1616
- /**
1617
- * Save a single document without performing any default `$set` or `$inc` like operations.
1618
- * When a document does not exist it will automatically be created unless `opts.upsert === false`.
1619
- *
1620
- * @param query The database query / path to the document.
1621
- * @param operation The MongoDB update document or pipeline (e.g. `{ $set: { key: value } }`).
1622
- * @param opts Additional options, see {@link Collection.SaveOpts}.
1623
- *
1624
- * @note The `opts.throw` option defaults to `true`.
1625
- * @note The `opts.upsert` option defaults to `true`.
1626
- * @note Replacement documents are not allowed here. An update operator
1627
- * document (e.g. `$set`, `$inc`) or an aggregation pipeline is required.
1628
- * To replace a document use {@link replace}.
1629
- *
1630
- * @note This writes the value you pass in—it does not deep-merge nested objects.
1631
- * If you save a nested object, any nested keys you leave out may be overwritten/removed.
1632
- * Use `set()` in combination with `flatten: true` to perform deep merges on nested objects without worrying about this behavior.
1633
- *
1634
- * @returns
1635
- * - When `opts.bulk === true`: an unexecuted bulk operation.
1636
- * - When `opts.return === true`: the **updated** document; or a {@link Collection.SaveError} when `throw:false` and a write failure occurs.
1637
- * - Otherwise: {@link mongodb.UpdateResult} on success; or a {@link Collection.SaveError} when `throw:false` and a write failure occurs.
1638
- *
1639
- * @throws {Collection.SaveError} Only when `opts.throw !== false` and the write fails.
1640
- * @throws {InvalidUsageError} (always) When the provided argument(s) are invalid or if the collection was not used properly.
1641
- *
1642
- * @docs
1643
- */
1644
- async save(query, operation, opts) {
1645
- if (!this.initialized) {
1646
- await this.init();
1647
- }
1648
- this.assert_init();
1649
- this.assert_not_finalized();
1650
- if (!this._is_operator_update_or_pipeline(operation)) {
1651
- throw new import_errors.InvalidUsageError({
1652
- message: "Plain replacement documents are not allowed for 'save()' (uses updateOne/findOneAndUpdate). Pass an operator update or aggregation pipeline. To replace a document, call 'replace()'.",
1653
- reason: "invalid_update_document",
1654
- field: "operation"
1655
- });
1656
- }
1657
- const query_op = this._init_query(query, false, "query");
1658
- const throw_errors = opts?.throw ?? true;
1659
- const retry = opts?.retry;
1660
- const upsert = opts?.upsert ?? true;
1661
- if (this.ttl_enabled && opts?.apply_ttl !== false)
1662
- this._apply_ttl_to_operation(operation, upsert);
1663
- if (this.record_version != null)
1664
- this._apply_record_version_to_operation(operation, upsert);
1665
- if (opts?.bulk) {
1666
- const b_op = {
1667
- updateOne: {
1668
- filter: query_op,
1669
- update: operation,
1670
- upsert
1671
- }
1672
- };
1673
- return b_op;
1674
- }
1675
- if (opts?.return) {
1676
- let res;
1677
- try {
1678
- res = await this._with_retry(() => this._col.findOneAndUpdate(query_op, operation, this.get_operation_options({
1679
- upsert,
1680
- returnDocument: mongodb.ReturnDocument.AFTER,
1681
- includeResultMetadata: false,
1682
- ...typeof opts?.timeout === "number" ? { maxTimeMS: opts.timeout } : {}
1683
- })), retry);
1684
- } catch (e) {
1685
- const err = new Collection.SaveError({
1686
- message: "Update failed due to an unexpected error.",
1687
- query: query_op,
1688
- reason: this._should_retry_error(e) ? Collection.Retry.get_attempts(retry) > 1 ? "retries_exhausted" : "retryable" : "unknown",
1689
- cause: e
1690
- });
1691
- if (throw_errors)
1692
- throw err;
1693
- return err;
1694
- }
1695
- if (!res) {
1696
- const err = new Collection.SaveError({
1697
- message: "Document write was not acknowledged.",
1698
- query: query_op,
1699
- reason: "not_acknowledged"
1700
- });
1701
- if (throw_errors)
1702
- throw err;
1703
- return err;
1704
- }
1705
- try {
1706
- const processed = await this.apply_on_load(res, {
1707
- projection: void 0,
1708
- persist: true,
1709
- await_persist: true
1710
- });
1711
- return processed;
1712
- } catch (e) {
1713
- const err = new Collection.SaveError({
1714
- message: "Update succeeded but post-load processing failed.",
1715
- query: query_op,
1716
- reason: "post_process_failed",
1717
- cause: e
1718
- });
1719
- if (throw_errors)
1720
- throw err;
1721
- return err;
1722
- }
1723
- } else {
1724
- let res;
1725
- try {
1726
- res = await this._with_retry(() => this._col.updateOne(query_op, operation, this.get_operation_options({
1727
- upsert,
1728
- ...typeof opts?.timeout === "number" ? { maxTimeMS: opts.timeout } : {}
1729
- })), retry);
1730
- } catch (e) {
1731
- const err = new Collection.SaveError({
1732
- message: "Update failed due to an unexpected error.",
1733
- query: query_op,
1734
- reason: this._should_retry_error(e) ? Collection.Retry.get_attempts(retry) > 1 ? "retries_exhausted" : "retryable" : "unknown",
1735
- cause: e
1736
- });
1737
- if (throw_errors)
1738
- throw err;
1739
- return err;
1740
- }
1741
- if (!res.acknowledged || res.matchedCount === 0 && res.upsertedCount === 0) {
1742
- const err = new Collection.SaveError({
1743
- message: !res.acknowledged ? "Document write was not acknowledged." : "No document matched the filter and no upsert occurred.",
1744
- query: query_op,
1745
- reason: !res.acknowledged ? "not_acknowledged" : "no_match"
1746
- });
1747
- if (throw_errors)
1748
- throw err;
1749
- return err;
1750
- }
1751
- return res;
1752
- }
1753
- }
1754
- /**
1755
- * Save multiple documents without performing any default `$set` or `$inc` operations.
1756
- * Uses MongoDB `updateMany` (unlike {@link save}, which uses `updateOne`).
1757
- *
1758
- * @param query The database query / path to the documents.
1759
- * @param operation The MongoDB update document or pipeline (e.g. `{ $set: { ... } }`).
1760
- * @param opts Additional options, see {@link Collection.SaveManyOpts}.
1761
- *
1762
- * @note The `opts.throw` option defaults to `true`.
1763
- * @note The `opts.upsert` option defaults to `false` (unlike {@link save}, which defaults to `true`).
1764
- * @note When `opts.return` is truthy, this performs a **follow-up** {@link list} with the same `query`
1765
- * to return the (post-update) documents. This is **less efficient** than `save(..., { return: true })`
1766
- * because it requires an additional list query after the write.
1767
- * @note If the follow-up `list()` fails:
1768
- * - with `opts.throw !== false`, it will throw a {@link Collection.ListError};
1769
- * - with `opts.throw === false`, it will return a {@link Collection.ListError}.
1770
- *
1771
- * @returns
1772
- * - When `opts.bulk === true`: an unexecuted bulk operation (`{ updateMany: ... }`).
1773
- * - When `opts.return` is falsy: {@link mongodb.UpdateResult} on success; or a {@link Collection.SaveError} when `throw:false`.
1774
- * - When `opts.return` is truthy: the matched/updated docs (via `list()`); or
1775
- * - a {@link Collection.SaveError} when the write fails and `throw:false`, or
1776
- * - a {@link Collection.ListError} when the follow-up read fails and `throw:false`.
1777
- *
1778
- * @throws {Collection.SaveError} Only when `opts.throw !== false` and the write fails.
1779
- * @throws {Collection.ListError} Only when `opts.throw !== false` and the follow-up list fails.
1780
- * @throws {InvalidUsageError} (always) When the provided argument(s) are invalid or the collection was misused.
1781
- *
1782
- * @docs
1783
- */
1784
- async save_many(query, operation, opts) {
1785
- if (!this.initialized) {
1786
- await this.init();
1787
- }
1788
- this.assert_init();
1789
- this.assert_not_finalized();
1790
- if (!this._is_operator_update_or_pipeline(operation)) {
1791
- throw new import_errors.InvalidUsageError({
1792
- message: "Plain replacement documents are not allowed for 'save_many()' (uses updateMany). Pass an operator update or aggregation pipeline. To replace documents, call 'replace_many()'.",
1793
- reason: "invalid_update_document",
1794
- field: "operation"
1795
- });
1796
- }
1797
- const query_op = this._init_query(query, false, "query");
1798
- const throw_errors = opts?.throw ?? true;
1799
- const retry = opts?.retry;
1800
- const upsert = opts?.upsert ?? false;
1801
- if (this.ttl_enabled && opts?.apply_ttl !== false) {
1802
- this._apply_ttl_to_operation(operation, upsert);
1803
- }
1804
- if (this.record_version != null) {
1805
- this._apply_record_version_to_operation(operation, upsert);
1806
- }
1807
- if (opts?.bulk) {
1808
- const b_op = {
1809
- updateMany: {
1810
- filter: query_op,
1811
- update: operation,
1812
- upsert
1813
- }
1814
- };
1815
- return b_op;
1816
- }
1817
- let write;
1818
- try {
1819
- write = await this._with_retry(() => this._col.updateMany(query_op, operation, this.get_operation_options({
1820
- upsert,
1821
- ...typeof opts?.timeout === "number" ? { maxTimeMS: opts.timeout } : {}
1822
- })), retry);
1823
- } catch (e) {
1824
- const err = new Collection.SaveError({
1825
- message: "Update-many failed due to an unexpected error.",
1826
- query: query_op,
1827
- reason: this._should_retry_error(e) ? Collection.Retry.get_attempts(retry) > 1 ? "retries_exhausted" : "retryable" : "unknown",
1828
- cause: e
1829
- });
1830
- if (throw_errors)
1831
- throw err;
1832
- return err;
1833
- }
1834
- if (!write.acknowledged || write.matchedCount === 0 && write.upsertedCount === 0) {
1835
- const err = new Collection.SaveError({
1836
- message: !write.acknowledged ? "Document write was not acknowledged." : "No document matched the filter and no upsert occurred.",
1837
- query: query_op,
1838
- reason: !write.acknowledged ? "not_acknowledged" : "no_match"
1839
- });
1840
- if (throw_errors)
1841
- throw err;
1842
- return err;
1843
- }
1844
- if (!opts?.return) {
1845
- return write;
1846
- }
1847
- const follow = typeof opts.return === "object" ? opts.return : {};
1848
- const out = await this.list(query, {
1849
- ...follow,
1850
- // copy control fields from the write options
1851
- throw: opts.throw,
1852
- retry: opts.retry,
1853
- timeout: opts.timeout
1854
- // Note: we intentionally do NOT set cursor/page_info (they're excluded in SaveManyReturnOpts).
1855
- });
1856
- return out;
1857
- }
1858
- /**
1859
- * Build an aggregation replacement pipeline that preserves _id on matches and
1860
- * applies versioning/TTL consistently with non-pipeline paths.
1861
- *
1862
- * - On matches: preserve stored `__record_version` and (for static TTL) stored `__ttl_timestamp`.
1863
- * - On upserts:
1864
- * - `__record_version`: respect user value if provided, else stamp `this.record_version`.
1865
- * - `__ttl_timestamp`:
1866
- * • sliding TTL → always set to "now"
1867
- * • static TTL → respect user value if provided, else set to "now"
1868
- *
1869
- * @param base_replacement A shallow clone of the user replacement. For replace_many, pass without `_id`.
1870
- * @param upsert Whether the write is an upsert.
1871
- * @param apply_ttl Whether TTL logic should be applied (`this.ttl_enabled && opts?.apply_ttl !== false`).
1872
- * @returns A MongoDB aggregation pipeline that performs the replacement.
1873
- */
1874
- _build_replace_pipeline(base_replacement, upsert, apply_ttl) {
1875
- const now = /* @__PURE__ */ new Date();
1876
- const merge_objects = [
1877
- base_replacement,
1878
- {
1879
- $cond: [
1880
- { $ne: ["$_id", null] },
1881
- { _id: "$_id" },
1882
- {}
1883
- ]
1884
- }
1885
- ];
1886
- if (this.record_version != null) {
1887
- merge_objects.push({ __old_rv: "$__record_version" });
1888
- }
1889
- if (apply_ttl) {
1890
- merge_objects.push({ __old_ttl: "$__ttl_timestamp" });
1891
- } else {
1892
- merge_objects.push({ __ttl_timestamp: "$__ttl_timestamp" });
1893
- }
1894
- const pipeline = [
1895
- { $replaceWith: { $mergeObjects: merge_objects } }
1896
- ];
1897
- if (this.record_version != null) {
1898
- pipeline.push({
1899
- $set: {
1900
- /**
1901
- * Matches:
1902
- * Prefer stored version (`__old_rv`), otherwise keep any user-provided value.
1903
- * Upserts:
1904
- * Respect user-provided value if present; otherwise default to `this.record_version`.
1905
- */
1906
- __record_version: {
1907
- $cond: [
1908
- { $ne: ["$__old_rv", null] },
1909
- "$__old_rv",
1910
- upsert ? { $ifNull: ["$__record_version", this.record_version] } : "$__record_version"
1911
- ]
1912
- }
1913
- }
1914
- });
1915
- }
1916
- if (apply_ttl) {
1917
- pipeline.push({
1918
- $set: this.sliding_ttl ? { __ttl_timestamp: now } : {
1919
- __ttl_timestamp: {
1920
- $cond: [
1921
- { $ne: ["$__old_ttl", null] },
1922
- "$__old_ttl",
1923
- { $ifNull: ["$__ttl_timestamp", now] }
1924
- ]
1925
- }
1926
- }
1927
- });
1928
- }
1929
- pipeline.push({ $unset: ["__old_rv", "__old_ttl"] });
1930
- return pipeline;
1931
- }
1932
- /**
1933
- * Replace a single document.
1934
- * Accepts a replacement document only (no update operators/pipelines).
1935
- *
1936
- * Internally uses an aggregation pipeline to emulate a full replacement while preserving `_id`
1937
- * for matched documents and applying record-version/TTL semantics consistently.
1938
- *
1939
- * @param query The match filter.
1940
- * @param replacement The replacement document, no `$` operators.
1941
- * @param opts Options, see {@link Collection.ReplaceOpts}.
1942
- *
1943
- * @note The `opts.throw` option defaults to `true`.
1944
- * @note The `opts.upsert` option defaults to `true`.
1945
- * @note TTL semantics:
1946
- * - When `opts.apply_ttl === false` (or TTL is disabled), the existing TTL is preserved for matched docs.
1947
- * - With sliding TTL, `__ttl_timestamp` is refreshed on every write.
1948
- * - With static TTL, matched docs keep their original TTL; upserts receive a fresh timestamp.
1949
- *
1950
- * @warning Updating the document id `_id` will cause undefined behaviour on matches. On matched documents,
1951
- * a user-supplied `_id` is ignored and the existing `_id` is preserved. On true upserts, a
1952
- * user-supplied `_id` is allowed and will be used by the server.
1953
- *
1954
- * @returns
1955
- * - When `opts.bulk === true`: an unexecuted bulk operation.
1956
- * - When `opts.return === true`: the **updated** document; or a {@link Collection.SaveError} when `throw:false` and a write failure occurs.
1957
- * - Otherwise: {@link mongodb.UpdateResult} on success; or a {@link Collection.SaveError} when `throw:false` and a write failure occurs.
1958
- *
1959
- * @throws {Collection.SaveError} Only when `opts.throw !== false` and the write fails.
1960
- * @throws {InvalidUsageError} (always) When the provided argument(s) are invalid or if the collection was not used properly.
1961
- *
1962
- * @docs
1963
- */
1964
- async replace(query, replacement, opts) {
1965
- if (!this.initialized) {
1966
- await this.init();
1967
- }
1968
- this.assert_init();
1969
- this.assert_not_finalized();
1970
- if (this._is_operator_update_or_pipeline(replacement)) {
1971
- throw new import_errors.InvalidUsageError({
1972
- message: "The 'replace()' method accepts a replacement document only (no update operators or pipelines).",
1973
- reason: "invalid_replacement_document",
1974
- field: "replacement"
1975
- });
1976
- }
1977
- const query_op = this._init_query(query, false, "query");
1978
- const throw_errors = opts?.throw ?? true;
1979
- const retry = opts?.retry;
1980
- const upsert = opts?.upsert ?? true;
1981
- const apply_ttl = this.ttl_enabled && opts?.apply_ttl !== false;
1982
- const base_replacement = { ...replacement };
1983
- if (upsert === false) {
1984
- delete base_replacement._id;
1985
- }
1986
- const pipeline = this._build_replace_pipeline(base_replacement, upsert, apply_ttl);
1987
- if (opts?.bulk) {
1988
- const b_op = {
1989
- updateOne: {
1990
- filter: query_op,
1991
- update: pipeline,
1992
- upsert
1993
- }
1994
- };
1995
- return b_op;
1996
- }
1997
- if (opts?.return) {
1998
- let res;
1999
- try {
2000
- res = await this._with_retry(() => this._col.findOneAndUpdate(query_op, pipeline, this.get_operation_options({
2001
- upsert,
2002
- returnDocument: mongodb.ReturnDocument.AFTER,
2003
- includeResultMetadata: false,
2004
- ...typeof opts?.timeout === "number" ? { maxTimeMS: opts.timeout } : {}
2005
- })), retry);
2006
- } catch (e) {
2007
- const err = new Collection.SaveError({
2008
- message: "Replace failed due to an unexpected error.",
2009
- query: query_op,
2010
- reason: this._should_retry_error(e) ? Collection.Retry.get_attempts(retry) > 1 ? "retries_exhausted" : "retryable" : "unknown",
2011
- cause: e
2012
- });
2013
- if (throw_errors)
2014
- throw err;
2015
- return err;
2016
- }
2017
- if (!res) {
2018
- const err = new Collection.SaveError({
2019
- message: "Document write was not acknowledged.",
2020
- query: query_op,
2021
- reason: "not_acknowledged"
2022
- });
2023
- if (throw_errors)
2024
- throw err;
2025
- return err;
2026
- }
2027
- try {
2028
- const processed = await this.apply_on_load(res, {
2029
- projection: void 0,
2030
- persist: true,
2031
- await_persist: true
2032
- });
2033
- return processed;
2034
- } catch (e) {
2035
- const err = new Collection.SaveError({
2036
- message: "Replace succeeded but post-load processing failed.",
2037
- query: query_op,
2038
- reason: "post_process_failed",
2039
- cause: e
2040
- });
2041
- if (throw_errors)
2042
- throw err;
2043
- return err;
2044
- }
2045
- }
2046
- let write;
2047
- try {
2048
- write = await this._with_retry(() => this._col.updateOne(query_op, pipeline, this.get_operation_options({
2049
- upsert,
2050
- ...typeof opts?.timeout === "number" ? { maxTimeMS: opts.timeout } : {}
2051
- })), retry);
2052
- } catch (e) {
2053
- const err = new Collection.SaveError({
2054
- message: "Replace failed due to an unexpected error.",
2055
- query: query_op,
2056
- reason: this._should_retry_error(e) ? Collection.Retry.get_attempts(retry) > 1 ? "retries_exhausted" : "retryable" : "unknown",
2057
- cause: e
2058
- });
2059
- if (throw_errors)
2060
- throw err;
2061
- return err;
2062
- }
2063
- if (!write.acknowledged || write.matchedCount === 0 && write.upsertedCount === 0) {
2064
- const err = new Collection.SaveError({
2065
- message: !write.acknowledged ? "Document write was not acknowledged." : "No document matched the filter and no upsert occurred.",
2066
- query: query_op,
2067
- reason: !write.acknowledged ? "not_acknowledged" : "no_match"
2068
- });
2069
- if (throw_errors)
2070
- throw err;
2071
- return err;
2072
- }
2073
- return write;
2074
- }
2075
- /**
2076
- * Replace multiple documents matched by `query`.
2077
- * Accepts a **replacement document only** (no update operators or pipelines).
2078
- *
2079
- * Internally uses an aggregation pipeline to emulate a full replacement while preserving `_id`
2080
- * for matched documents and applying record-version/TTL semantics consistently.
2081
- *
2082
- * @param query The match filter.
2083
- * @param replacement The replacement document, no `$` operators.
2084
- * @param opts Options, see {@link Collection.ReplaceManyOpts}.
2085
- *
2086
- * @note The `opts.throw` option defaults to `true`.
2087
- * @note The `opts.upsert` option defaults to `false` (unlike {@link replace}, which defaults to `true`).
2088
- * @note When `opts.return` is truthy, this performs a **follow-up** {@link list} with the same `query`
2089
- * to return the (post-update) documents. This is **less efficient** than `replace(..., { return: true })`
2090
- * because it requires an additional list query after the write.
2091
- * @note TTL semantics:
2092
- * - When `opts.apply_ttl === false` (or TTL is disabled), the existing TTL is preserved for matched docs.
2093
- * - With sliding TTL, `__ttl_timestamp` is refreshed on every write.
2094
- * - With static TTL, matched docs keep their original TTL; upserts receive a fresh timestamp.
2095
- *
2096
- * @warning The `_id` field is handled with special care:
2097
- * - Any `_id` present in the `replacement` is **ignored/stripped** for `replace_many`.
2098
- * This prevents attempts to change immutable ids across multiple documents.
2099
- * - For matched documents, the existing `_id` is always preserved.
2100
- * - For true upserts (`opts.upsert === true` when no match occurs), the server will
2101
- * generate a new `_id`. If you need to upsert with a caller-chosen `_id`, use
2102
- * {@link replace} (single-document) instead.
2103
- *
2104
- * @returns
2105
- * - When `opts.bulk === true`: an unexecuted bulk operation (`{ updateMany: ... }`).
2106
- * - When `opts.return` is falsy: {@link mongodb.UpdateResult} on success; or a
2107
- * {@link Collection.SaveError} when `throw:false` and a write failure occurs.
2108
- * - When `opts.return` is truthy: the matched/updated docs (via a follow-up {@link list});
2109
- * or a {@link Collection.SaveError} / {@link Collection.ListError} when `throw:false`.
2110
- *
2111
- * @throws {Collection.SaveError} Only when `opts.throw !== false` and the write fails.
2112
- * @throws {Collection.ListError} Only when `opts.throw !== false` and the follow-up list fails.
2113
- * @throws {InvalidUsageError} (always) When arguments are invalid or the collection was misused.
2114
- *
2115
- * @docs
2116
- */
2117
- async replace_many(query, replacement, opts) {
2118
- if (!this.initialized) {
2119
- await this.init();
2120
- }
2121
- this.assert_init();
2122
- this.assert_not_finalized();
2123
- if (this._is_operator_update_or_pipeline(replacement)) {
2124
- throw new import_errors.InvalidUsageError({
2125
- message: "The 'replace_many()' method accepts a replacement document only (no update operators or pipelines).",
2126
- reason: "invalid_replacement_document",
2127
- field: "replacement"
2128
- });
2129
- }
2130
- const query_op = this._init_query(query, false, "query");
2131
- const throw_errors = opts?.throw ?? true;
2132
- const retry = opts?.retry;
2133
- const upsert = opts?.upsert ?? false;
2134
- const apply_ttl = this.ttl_enabled && opts?.apply_ttl !== false;
2135
- const base_replacement = { ...replacement };
2136
- delete base_replacement._id;
2137
- const pipeline = this._build_replace_pipeline(base_replacement, upsert, apply_ttl);
2138
- if (opts?.bulk) {
2139
- const b_op = {
2140
- updateMany: {
2141
- filter: query_op,
2142
- update: pipeline,
2143
- upsert
2144
- }
2145
- };
2146
- return b_op;
2147
- }
2148
- let write;
2149
- try {
2150
- write = await this._with_retry(() => this._col.updateMany(query_op, pipeline, this.get_operation_options({
2151
- upsert,
2152
- ...typeof opts?.timeout === "number" ? { maxTimeMS: opts.timeout } : {}
2153
- })), retry);
2154
- } catch (e) {
2155
- const err = new Collection.SaveError({
2156
- message: "Replace-many failed due to an unexpected error.",
2157
- query: query_op,
2158
- reason: this._should_retry_error(e) ? Collection.Retry.get_attempts(retry) > 1 ? "retries_exhausted" : "retryable" : "unknown",
2159
- cause: e
2160
- });
2161
- if (throw_errors)
2162
- throw err;
2163
- return err;
2164
- }
2165
- if (!write.acknowledged || write.matchedCount === 0 && write.upsertedCount === 0) {
2166
- const err = new Collection.SaveError({
2167
- message: !write.acknowledged ? "Document write was not acknowledged." : "No document matched the filter and no upsert occurred.",
2168
- query: query_op,
2169
- reason: !write.acknowledged ? "not_acknowledged" : "no_match"
2170
- });
2171
- if (throw_errors)
2172
- throw err;
2173
- return err;
2174
- }
2175
- if (!opts?.return) {
2176
- return write;
2177
- }
2178
- const follow = typeof opts.return === "object" ? opts.return : {};
2179
- const out = await this.list(query, {
2180
- ...follow,
2181
- throw: opts.throw,
2182
- retry: opts.retry,
2183
- timeout: opts.timeout
2184
- });
2185
- return out;
2186
- }
2187
- /**
2188
- * Delete a document of the collection.
2189
- *
2190
- * @param query The database query to the document.
2191
- * @param opts Additional options, see {@link Collection.DeleteOpts}.
2192
- *
2193
- * @note The `opts.throw` option defaults to `true`.
2194
- *
2195
- * @returns
2196
- * - An unexecuted bulk operation object if `bulk === true`.
2197
- * - A {@link Collection.DeleteError} when occurred and `opts.throw === false`.
2198
- * - A {@link mongodb.DeleteResult}.
2199
- *
2200
- * @throws {Collection.DeleteError} When `opts.throw !== false` and if the deletion was not acknowledged, this does not check against the deleted document count.
2201
- * @throws {InvalidUsageError} (always) When the provided argument(s) are invalid or if the collection was not used properly.
2202
- *
2203
- * @docs
2204
- */
2205
- async delete(query, opts) {
2206
- if (!this.initialized) {
2207
- await this.init();
2208
- }
2209
- this.assert_init();
2210
- this.assert_not_finalized();
2211
- const throw_errors = opts?.throw ?? true;
2212
- const query_op = this._init_query(query, false, "query");
2213
- if (opts != null && opts.bulk) {
2214
- const b_op = {
2215
- deleteOne: {
2216
- filter: query_op
2217
- }
2218
- };
2219
- return b_op;
2220
- } else {
2221
- let res;
2222
- try {
2223
- res = await this._with_retry(() => this._col.deleteOne(query_op, this.get_operation_options(typeof opts?.timeout === "number" ? { maxTimeMS: opts.timeout } : {})), opts?.retry);
2224
- } catch (e) {
2225
- const err = new Collection.DeleteError({
2226
- message: `Failed to delete document(s) in collection "${this.name}".`,
2227
- query: query_op,
2228
- reason: this._should_retry_error(e) ? Collection.Retry.get_attempts(opts?.retry) > 1 ? "retries_exhausted" : "retryable" : "unknown",
2229
- cause: e
2230
- });
2231
- if (throw_errors)
2232
- throw err;
2233
- return err;
2234
- }
2235
- if (!res.acknowledged) {
2236
- const err = new Collection.DeleteError({
2237
- message: `Failed to delete document(s) in collection "${this.name}".`,
2238
- query: query_op,
2239
- reason: "not_acknowledged"
2240
- });
2241
- if (throw_errors)
2242
- throw err;
2243
- return err;
2244
- }
2245
- return res;
2246
- }
2247
- }
2248
- /**
2249
- * Delete multiple documents matching the query.
2250
- *
2251
- * @param query The database query to the document(s).
2252
- * @param opts Additional options, see {@link Collection.DeleteOpts}.
2253
- * @param allow_empty_query When `true`, allows an empty query (i.e. `{}`) to be passed, which would otherwise throw an error.
2254
- *
2255
- * @note The `opts.throw` option defaults to `true`.
2256
- *
2257
- * @returns
2258
- * - An unexecuted bulk operation object if `bulk === true`.
2259
- * - A {@link Collection.DeleteError} when occurred and `opts.throw == false`.
2260
- * - A {@link mongodb.DeleteResult}.
2261
- *
2262
- * @throws {Collection.DeleteError} When `opts.throw !== false` and if the deletion was not acknowledged, this does not check against the deleted document count.
2263
- * @throws {InvalidUsageError} (always) When the provided argument(s) are invalid or if the collection was not used properly.
2264
- *
2265
- * @docs
2266
- */
2267
- async delete_many(query, opts, allow_empty_query = false) {
2268
- if (!this.initialized) {
2269
- await this.init();
2270
- }
2271
- this.assert_init();
2272
- this.assert_not_finalized();
2273
- const throw_errors = opts?.throw ?? true;
2274
- const query_op = this._init_query(query, allow_empty_query, "query");
2275
- if (opts != null && opts.bulk) {
2276
- const b_op = {
2277
- deleteMany: {
2278
- filter: query_op
2279
- }
2280
- };
2281
- return b_op;
2282
- } else {
2283
- let res;
2284
- try {
2285
- res = await this._with_retry(() => this._col.deleteMany(query_op, this.get_operation_options(typeof opts?.timeout === "number" ? { maxTimeMS: opts.timeout } : {})), opts?.retry);
2286
- } catch (e) {
2287
- const err = new Collection.DeleteError({
2288
- message: `Failed to delete document(s) in collection "${this.name}".`,
2289
- query: query_op,
2290
- reason: this._should_retry_error(e) ? Collection.Retry.get_attempts(opts?.retry) > 1 ? "retries_exhausted" : "retryable" : "unknown",
2291
- cause: e
2292
- });
2293
- if (throw_errors)
2294
- throw err;
2295
- return err;
2296
- }
2297
- if (!res.acknowledged) {
2298
- const err = new Collection.DeleteError({
2299
- message: `Failed to delete document(s) in collection "${this.name}".`,
2300
- query: query_op,
2301
- reason: "not_acknowledged"
2302
- });
2303
- if (throw_errors)
2304
- throw err;
2305
- return err;
2306
- }
2307
- return res;
2308
- }
2309
- }
2310
- /**
2311
- * Delete all documents in the collection.
2312
- *
2313
- * @param opts Additional options, see {@link Collection.DeleteOpts}.
2314
- *
2315
- * @note The `opts.throw` option defaults to `true`.
2316
- *
2317
- * @returns
2318
- * - An unexecuted bulk operation object if `bulk === true`.
2319
- * - A {@link Collection.DeleteError} when occurred and `opts.throw == false`.
2320
- * - A {@link mongodb.DeleteResult}.
2321
- *
2322
- * @throws {Collection.DeleteError} When `opts.throw !== false` and if the deletion was not acknowledged, this does not check against the deleted document count.
2323
- * @throws {InvalidUsageError} (always) When the provided argument(s) are invalid or if the collection was not used properly.
2324
- *
2325
- * @docs
2326
- */
2327
- async delete_all(opts) {
2328
- return this.delete_many({}, opts, true);
2329
- }
2330
- /**
2331
- * Delete all documents from the collection and drop the collection.
2332
- *
2333
- * @note This function is not supported for transaction based collections.
2334
- *
2335
- * @param opts Additional options, see {@link Collection.DeleteOpts}.
2336
- *
2337
- * @note The `opts.throw` option defaults to `true`.
2338
- *
2339
- * @returns
2340
- * - A {@link Collection.DeleteError} when occurred and `opts.throw === false`.
2341
- * - Undefined upon success.
2342
- *
2343
- * @throws {Collection.DeleteError} When `opts.throw !== false` and if the deletion was not acknowledged, this does not check against the deleted document count.
2344
- * @throws {InvalidUsageError} (always) When the provided argument(s) are invalid or if the collection was not used properly.
2345
- *
2346
- * @docs
2347
- */
2348
- async delete_collection(opts) {
2349
- if (!this.initialized) {
2350
- await this.init();
2351
- }
2352
- this.assert_init();
2353
- this.assert_not_finalized();
2354
- this.assert_not_transaction_based();
2355
- const throw_errors = opts?.throw ?? true;
2356
- let res;
2357
- try {
2358
- res = await this._with_retry(() => this._col.drop(this.get_operation_options(typeof opts?.timeout === "number" ? { maxTimeMS: opts.timeout } : {})), opts?.retry);
2359
- } catch (e) {
2360
- if (e && typeof e === "object" && (e?.code === 26 || e?.codeName === "NamespaceNotFound")) {
2361
- return void 0;
2362
- }
2363
- const err = new Collection.DeleteError({
2364
- message: `Failed to drop collection "${this.name}".`,
2365
- query: {},
2366
- reason: this._should_retry_error(e) ? Collection.Retry.get_attempts(opts?.retry) > 1 ? "retries_exhausted" : "retryable" : "unknown",
2367
- cause: e
2368
- });
2369
- if (throw_errors)
2370
- throw err;
2371
- return err;
2372
- }
2373
- if (!res) {
2374
- const err = new Collection.DeleteError({
2375
- message: `Failed to drop collection "${this.name}", detected by a falsy return.`,
2376
- query: {},
2377
- reason: "not_acknowledged"
2378
- });
2379
- if (throw_errors)
2380
- throw err;
2381
- return err;
2382
- }
2383
- }
2384
- // /**
2385
- // * @todo implement
2386
- // * Enhanced bulk operations with retry logic for failed operations
2387
- // * @param operations - Array of bulk write operations
2388
- // * @param retries - Number of retry attempts for failed operations. Set to -1 to disable retries. Default is 3.
2389
- // * @returns Simplified BulkWriteResult with aggregated counts from all attempts
2390
- // */
2391
- // async bulk_operations(
2392
- // operations: any[] = [],
2393
- // retries: number = 3
2394
- // ): Promise<{
2395
- // ok: boolean;
2396
- // inserted_count: number;
2397
- // matched_count: number;
2398
- // modified_count: number;
2399
- // deleted_count: number;
2400
- // upserted_count: number;
2401
- // upserted_ids: { [key: number]: any };
2402
- // inserted_ids: { [key: number]: any };
2403
- // failed_operations: number[];
2404
- // errors?: any[];
2405
- // }> {
2406
- // if (!this.initialized) { await this.init(); }
2407
- // this.assert_init();
2408
- // // Validate operations
2409
- // if (!Array.isArray(operations)) {
2410
- // throw new TypeError('Operations must be an array');
2411
- // }
2412
- // // Return early for empty operations
2413
- // if (operations.length === 0) {
2414
- // return {
2415
- // ok: true,
2416
- // inserted_count: 0,
2417
- // matched_count: 0,
2418
- // modified_count: 0,
2419
- // deleted_count: 0,
2420
- // upserted_count: 0,
2421
- // upserted_ids: {},
2422
- // inserted_ids: {},
2423
- // failed_operations: []
2424
- // };
2425
- // }
2426
- // // MongoDB bulk write limit
2427
- // const MAX_BATCH_SIZE = 100000;
2428
- // if (operations.length > MAX_BATCH_SIZE) {
2429
- // throw new Error(`Bulk operations exceed MongoDB limit of ${MAX_BATCH_SIZE}. Please batch your operations.`);
2430
- // }
2431
- // // Initialize aggregated results
2432
- // const aggregated_result = {
2433
- // ok: true,
2434
- // inserted_count: 0,
2435
- // matched_count: 0,
2436
- // modified_count: 0,
2437
- // deleted_count: 0,
2438
- // upserted_count: 0,
2439
- // upserted_ids: {} as { [key: number]: any },
2440
- // inserted_ids: {} as { [key: number]: any },
2441
- // failed_operations: [] as number[],
2442
- // errors: [] as any[]
2443
- // };
2444
- // // Track operation status (true = succeeded, false = failed/pending)
2445
- // const operation_status: Map<number, boolean> = new Map();
2446
- // operations.forEach((_, index) => operation_status.set(index, false));
2447
- // // Track latest errors for each operation (will be cleared if operation succeeds)
2448
- // const latest_errors: Map<number, any> = new Map();
2449
- // // Track operations that need to be executed
2450
- // let pending_operations = operations.map((op, index) => ({ op, original_index: index }));
2451
- // let attempt_count = 0;
2452
- // const max_attempts = retries < 0 ? 1 : retries + 1;
2453
- // while (pending_operations.length > 0 && attempt_count < max_attempts) {
2454
- // attempt_count++;
2455
- // try {
2456
- // // Execute bulk operations
2457
- // const result = await this._col.bulkWrite(
2458
- // pending_operations.map(item => item.op),
2459
- // { ordered: false } // Use unordered for better error handling
2460
- // );
2461
- // // Track which operations succeeded in this attempt
2462
- // const succeeded_in_this_attempt = new Set<number>();
2463
- // // Aggregate successful results
2464
- // aggregated_result.inserted_count += result.insertedCount;
2465
- // aggregated_result.matched_count += result.matchedCount;
2466
- // aggregated_result.modified_count += result.modifiedCount;
2467
- // aggregated_result.deleted_count += result.deletedCount;
2468
- // aggregated_result.upserted_count += result.upsertedCount;
2469
- // // Map inserted/upserted IDs back to original indices
2470
- // if (result.insertedIds && typeof result.insertedIds === 'object') {
2471
- // for (const [key, value] of Object.entries(result.insertedIds)) {
2472
- // const idx = parseInt(key);
2473
- // if (!isNaN(idx) && pending_operations[idx]) {
2474
- // const original_index = pending_operations[idx].original_index;
2475
- // aggregated_result.inserted_ids[original_index] = value;
2476
- // succeeded_in_this_attempt.add(original_index);
2477
- // }
2478
- // }
2479
- // }
2480
- // if (result.upsertedIds && typeof result.upsertedIds === 'object') {
2481
- // for (const [key, value] of Object.entries(result.upsertedIds)) {
2482
- // const idx = parseInt(key);
2483
- // if (!isNaN(idx) && pending_operations[idx]) {
2484
- // const original_index = pending_operations[idx].original_index;
2485
- // aggregated_result.upserted_ids[original_index] = value;
2486
- // succeeded_in_this_attempt.add(original_index);
2487
- // }
2488
- // }
2489
- // }
2490
- // // Check for write errors
2491
- // const write_errors = result.hasWriteErrors?.() ? result.getWriteErrors() : [];
2492
- // if (write_errors.length > 0) {
2493
- // aggregated_result.ok = false;
2494
- // // Track failed operations by their indices in current batch
2495
- // const failed_indices_in_batch = new Set(write_errors.map(err => err.index));
2496
- // // Update errors for failed operations
2497
- // for (const error of write_errors) {
2498
- // if (error.index < pending_operations.length) {
2499
- // const original_index = pending_operations[error.index].original_index;
2500
- // latest_errors.set(original_index, {
2501
- // ...error,
2502
- // index: original_index,
2503
- // attempt: attempt_count,
2504
- // timestamp: new Date().toISOString()
2505
- // });
2506
- // }
2507
- // }
2508
- // // Mark operations as succeeded if they weren't in the error list
2509
- // pending_operations.forEach((item, batch_index) => {
2510
- // if (!failed_indices_in_batch.has(batch_index)) {
2511
- // const original_index = item.original_index;
2512
- // operation_status.set(original_index, true);
2513
- // succeeded_in_this_attempt.add(original_index);
2514
- // // Clear any previous errors for this operation
2515
- // latest_errors.delete(original_index);
2516
- // }
2517
- // });
2518
- // // Filter pending operations to only include failed ones
2519
- // if (retries >= 0 && attempt_count < max_attempts) {
2520
- // pending_operations = pending_operations.filter((_, index) => failed_indices_in_batch.has(index));
2521
- // // Add exponential backoff for retries
2522
- // if (pending_operations.length > 0) {
2523
- // const delay = Math.min(1000 * Math.pow(2, attempt_count - 1), 5000);
2524
- // await new Promise(resolve => setTimeout(resolve, delay));
2525
- // }
2526
- // } else {
2527
- // // No more retries, exit
2528
- // break;
2529
- // }
2530
- // } else {
2531
- // // All operations in this batch succeeded
2532
- // pending_operations.forEach(item => {
2533
- // operation_status.set(item.original_index, true);
2534
- // succeeded_in_this_attempt.add(item.original_index);
2535
- // // Clear any previous errors for these operations
2536
- // latest_errors.delete(item.original_index);
2537
- // });
2538
- // pending_operations = [];
2539
- // }
2540
- // // Log successful recoveries for monitoring
2541
- // if (attempt_count > 1 && succeeded_in_this_attempt.size > 0) {
2542
- // console.log(`[BulkOps] Recovered ${succeeded_in_this_attempt.size} operations on attempt ${attempt_count}`);
2543
- // }
2544
- // } catch (error: any) {
2545
- // aggregated_result.ok = false;
2546
- // // Track error for all pending operations
2547
- // const affected_indices = pending_operations.map(item => item.original_index);
2548
- // for (const original_index of affected_indices) {
2549
- // latest_errors.set(original_index, {
2550
- // message: error.message || 'Unknown error',
2551
- // code: error.code,
2552
- // attempt: attempt_count,
2553
- // index: original_index,
2554
- // timestamp: new Date().toISOString(),
2555
- // type: 'batch_error'
2556
- // });
2557
- // }
2558
- // // If retries are disabled or we've exhausted retries, throw
2559
- // if (retries < 0 || attempt_count >= max_attempts) {
2560
- // break;
2561
- // }
2562
- // // Add exponential backoff before retry
2563
- // const delay = Math.min(1000 * Math.pow(2, attempt_count - 1), 5000);
2564
- // await new Promise(resolve => setTimeout(resolve, delay));
2565
- // }
2566
- // }
2567
- // // Final reconciliation: determine which operations ultimately failed
2568
- // aggregated_result.failed_operations = [];
2569
- // aggregated_result.errors = [];
2570
- // for (const [index, succeeded] of operation_status.entries()) {
2571
- // if (!succeeded) {
2572
- // aggregated_result.failed_operations.push(index);
2573
- // const error = latest_errors.get(index);
2574
- // if (error) {
2575
- // aggregated_result.errors.push(error);
2576
- // }
2577
- // }
2578
- // }
2579
- // // Sort failed operations for consistency
2580
- // aggregated_result.failed_operations.sort((a, b) => a - b);
2581
- // // Clean up errors array if empty
2582
- // if (aggregated_result.errors.length === 0) {
2583
- // delete (aggregated_result as any).errors;
2584
- // }
2585
- // // If we still have failed operations after all retries, include detailed error
2586
- // if (aggregated_result.failed_operations.length > 0) {
2587
- // const error = new Error(
2588
- // `Bulk operations partially failed: ${aggregated_result.failed_operations.length} of ${operations.length} operations could not be completed after ${attempt_count} attempts. ` +
2589
- // `Successfully processed: ${operations.length - aggregated_result.failed_operations.length} operations.`
2590
- // );
2591
- // (error as any).aggregated_result = aggregated_result;
2592
- // (error as any).retry_attempts = attempt_count;
2593
- // (error as any).success_rate = ((operations.length - aggregated_result.failed_operations.length) / operations.length * 100).toFixed(2) + '%';
2594
- // // Only throw if all operations failed
2595
- // if (aggregated_result.failed_operations.length === operations.length) {
2596
- // throw error;
2597
- // }
2598
- // // Log partial failure for monitoring
2599
- // console.warn(`[BulkOps] Partial failure:`, (error as any).success_rate, 'success rate');
2600
- // } else {
2601
- // // Clean up failed operations array.
2602
- // delete (aggregated_result as any).failed_operations;
2603
- // }
2604
- // return aggregated_result;
2605
- // }
2606
- /**
2607
- * Execute bulk write operations.
2608
- *
2609
- * @param operations Array of bulk write operations.
2610
- * @param opts Additional options, see {@link Collection.BulkOpts}
2611
- *
2612
- * @note The `opts.throw` option defaults to `true`.
2613
- *
2614
- * @returns
2615
- * - A {@link Collection.BulkError} if occurred and `opts.throw === false`.
2616
- * - A {@link mongodb.BulkWriteResult}.
2617
- *
2618
- * @throws {Collection.BulkError} When `opts.throw !== false` and if the bulk operation failed, this does not check against the bulk write result (this may change in the future).
2619
- * @throws {InvalidUsageError} (always) When the provided argument(s) are invalid or if the collection was not used properly.
2620
- *
2621
- * @docs
2622
- */
2623
- async bulk_operations(operations, opts) {
2624
- if (!this.initialized) {
2625
- await this.init();
2626
- }
2627
- this.assert_init();
2628
- this.assert_not_finalized();
2629
- if (!Array.isArray(operations)) {
2630
- throw new TypeError("Operations must be an array");
2631
- }
2632
- if (operations.length > 1e5) {
2633
- throw new import_errors.InvalidUsageError({
2634
- message: "Bulk operations exceed MongoDB limit of 100000",
2635
- reason: "invalid_operations_length"
2636
- });
2637
- }
2638
- const throw_errors = opts?.throw ?? true;
2639
- if (this.ttl_enabled || this.record_version != null) {
2640
- const now = /* @__PURE__ */ new Date();
2641
- for (const op of operations) {
2642
- if (this.record_version != null) {
2643
- const rv = this.record_version;
2644
- if (op.insertOne?.document && typeof op.insertOne.document === "object") {
2645
- const d = op.insertOne.document;
2646
- if (d.__record_version == null) {
2647
- d.__record_version = rv;
2648
- }
2649
- } else if (op.replaceOne?.replacement && typeof op.replaceOne.replacement === "object") {
2650
- if (op.replaceOne.upsert) {
2651
- const d = op.replaceOne.replacement;
2652
- if (d.__record_version == null) {
2653
- d.__record_version = rv;
2654
- }
2655
- }
2656
- } else if (op.updateOne?.update) {
2657
- if (op.updateOne.upsert)
2658
- this._apply_record_version_to_operation(op.updateOne.update, true);
2659
- } else if (op.updateMany?.update) {
2660
- if (op.updateMany.upsert)
2661
- this._apply_record_version_to_operation(op.updateMany.update, true);
2662
- }
2663
- }
2664
- if (!this.ttl_enabled)
2665
- continue;
2666
- if (op.insertOne?.document && typeof op.insertOne.document === "object") {
2667
- if (this.sliding_ttl || op.insertOne.document.__ttl_timestamp == null) {
2668
- op.insertOne.document.__ttl_timestamp = now;
2669
- }
2670
- continue;
2671
- }
2672
- if (op.replaceOne?.replacement && typeof op.replaceOne.replacement === "object") {
2673
- if (this.sliding_ttl) {
2674
- op.replaceOne.replacement.__ttl_timestamp = now;
2675
- } else if (op.replaceOne.upsert && op.replaceOne.replacement.__ttl_timestamp == null) {
2676
- op.replaceOne.replacement.__ttl_timestamp = now;
2677
- }
2678
- continue;
2679
- }
2680
- if (op.updateOne?.update) {
2681
- this._apply_ttl_to_operation(op.updateOne.update, op.updateOne.upsert);
2682
- continue;
2683
- }
2684
- if (op.updateMany?.update) {
2685
- this._apply_ttl_to_operation(op.updateMany.update, op.updateMany.upsert);
2686
- continue;
2687
- }
2688
- }
2689
- }
2690
- try {
2691
- return await this._with_retry(() => this._col.bulkWrite(operations, this.get_operation_options({
2692
- ordered: true,
2693
- ...typeof opts?.timeout === "number" ? { maxTimeMS: opts.timeout } : {}
2694
- })), opts?.retry);
2695
- } catch (e) {
2696
- const err = new Collection.BulkError({
2697
- message: "Bulk operations failed due to an unexpected error.",
2698
- query: {},
2699
- reason: this._should_retry_error(e) ? Collection.Retry.get_attempts(opts?.retry) > 1 ? "retries_exhausted" : "retryable" : "unknown",
2700
- cause: e
2701
- });
2702
- if (throw_errors)
2703
- throw err;
2704
- return err;
2705
- }
2706
- }
2707
- /**
2708
- * Execute an aggregation pipeline.
2709
- *
2710
- * @param pipeline MongoDB aggregation pipeline stages.
2711
- * @param opts Aggregation options, see {@link Collection.AggregateOpts}
2712
- *
2713
- * @note The `opts.throw` option defaults to `true`.
2714
- * @note This method does not execute the {@link Collection.Opts.on_load}
2715
- * and {@link Collection.Opts.on_transform_version} callbacks.
2716
- *
2717
- * @returns
2718
- * - A {@link Collection.AggregateError} if occurred and `opts.throw === false`.
2719
- * - An {@link mongodb.AggregationCursor} if `opts.cursor === true`.
2720
- * - An array of document results.
2721
- *
2722
- * @throws {Collection.AggregateError} When `opts.throw !== false` and if the aggregate operation failed, this does not check against the aggregate result (this may change in the future).
2723
- * @throws {InvalidUsageError} (always) When the provided argument(s) are invalid or if the collection was not used properly.
2724
- *
2725
- * @docs
2726
- */
2727
- async aggregate(pipeline, opts) {
2728
- if (!this.initialized) {
2729
- await this.init();
2730
- }
2731
- this.assert_init();
2732
- this.assert_not_finalized();
2733
- const throw_errors = opts?.throw ?? true;
2734
- try {
2735
- const cursor = await this._with_retry(() => this._col.aggregate(pipeline, this.get_operation_options(typeof opts?.timeout === "number" ? { maxTimeMS: opts.timeout } : {})), opts?.retry);
2736
- if (typeof opts?.timeout === "number" && typeof cursor.maxTimeMS === "function") {
2737
- cursor.maxTimeMS(opts.timeout);
2738
- }
2739
- if (opts?.cursor)
2740
- return cursor;
2741
- const arr = await this._with_retry(() => cursor.toArray(), opts?.retry);
2742
- return arr;
2743
- } catch (e) {
2744
- const err = new Collection.AggregateError({
2745
- message: "Aggregate operation failed due to an unexpected error.",
2746
- query: {},
2747
- reason: this._should_retry_error(e) ? Collection.Retry.get_attempts(opts?.retry) > 1 ? "retries_exhausted" : "retryable" : "unknown",
2748
- cause: e
2749
- });
2750
- if (throw_errors)
2751
- throw err;
2752
- return err;
2753
- }
2754
- }
2755
- /**
2756
- * Clean a document from all default system attributes.
2757
- * @param doc The document to clean.
2758
- * @returns The cleaned document without system attributes.
2759
- *
2760
- * @docs
2761
- */
2762
- clean(doc) {
2763
- if (doc == null) {
2764
- return doc;
2765
- }
2766
- if (typeof doc === "object") {
2767
- const out = { ...doc };
2768
- delete out._id;
2769
- delete out._path;
2770
- if (out.__ttl_timestamp != null) {
2771
- delete out.__ttl_timestamp;
2772
- }
2773
- if (out.__record_version != null) {
2774
- delete out.__record_version;
2775
- }
2776
- return out;
2777
- }
2778
- return doc;
2779
- }
2780
- // ---------------------------------------------------------
2781
- // Sessions & transactions.
2782
- // ---------------------------------------------------------
2783
- /**
2784
- * Start a new transaction by creating a TransactionCollection instance.
2785
- * @returns A new TransactionCollection instance with transaction capabilities.
2786
- *
2787
- * @docs
2788
- */
2789
- async start_transaction() {
2790
- if (!this.db.client) {
2791
- throw new import_errors.InvalidUsageError({
2792
- message: "Database client is not initialized, ensure the parent 'volt.Server' is initialized.",
2793
- reason: "client_not_connected"
2794
- });
2795
- }
2796
- if (!this.initialized) {
2797
- await this.init();
2798
- }
2799
- this.assert_init();
2800
- return new TransactionCollection({
2801
- derived_collection: this,
2802
- transaction_based: true
2803
- });
2804
- }
2805
- // ------------------- DEPRECATED -------------------------
2806
- /** Prepare a _path based regex operation. @deprecated */
2807
- prepare_path_regex_filter(path) {
2808
- while (path.length > 0 && path.charAt(path.length - 1) === "/") {
2809
- path = path.substring(0, path.length - 1);
2810
- }
2811
- if (path.length == 0) {
2812
- throw new import_errors.InvalidUsageError({
2813
- message: `Invalid path '${path}'`,
2814
- reason: "invalid_path"
2815
- });
2816
- }
2817
- if (path.length > 1e3) {
2818
- throw new import_errors.InvalidUsageError({
2819
- message: `Path too long (${path.length})`,
2820
- reason: "invalid_path"
2821
- });
2822
- }
2823
- const escapeRegExp = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2824
- const filter = {
2825
- _path: {
2826
- $regex: `^${escapeRegExp(path)}/`
2827
- // $options: 'i' // Case insensitive for consistency
2828
- }
2829
- };
2830
- return filter;
2831
- }
2832
- }
2833
- (function(Collection2) {
2834
- let Retry;
2835
- (function(Retry2) {
2836
- function get_attempts(retry) {
2837
- return Math.max(1, Math.min(100, typeof retry === "number" ? retry : !retry ? 1 : retry.attempts));
2838
- }
2839
- Retry2.get_attempts = get_attempts;
2840
- function normalize(retry) {
2841
- const base = typeof retry === "number" ? { attempts: retry } : typeof retry === "object" ? retry ?? { attempts: 1 } : { attempts: 1 };
2842
- let attempts = Number(base.attempts);
2843
- if (!Number.isFinite(attempts))
2844
- attempts = 1;
2845
- attempts = Math.max(1, Math.min(100, attempts));
2846
- const initial_delay = base.initial_delay ?? 100;
2847
- const max_delay = base.max_delay ?? 1e3;
2848
- const backoff_factor = base.backoff_factor ?? 2;
2849
- const jitter_ratio = 0.2;
2850
- return {
2851
- attempts,
2852
- initial_delay,
2853
- max_delay,
2854
- backoff_factor,
2855
- jitter_ratio
2856
- };
2857
- }
2858
- Retry2.normalize = normalize;
2859
- function compute_backoff_delay(attempt_index, params) {
2860
- const base = Math.min(params.max_delay, (params.initial_delay <= 0 ? 0 : params.initial_delay) * Math.pow(Math.max(1, params.backoff_factor), attempt_index));
2861
- if (base <= 0)
2862
- return 0;
2863
- const jitter = (Math.random() * 2 - 1) * (params.jitter_ratio * base);
2864
- const delay = Math.max(0, Math.min(params.max_delay, base + jitter));
2865
- return Math.floor(delay);
2866
- }
2867
- Retry2.compute_backoff_delay = compute_backoff_delay;
2868
- })(Retry = Collection2.Retry || (Collection2.Retry = {}));
2869
- class OperationError extends Error {
2870
- /** The error message. */
2871
- message;
2872
- query;
2873
- reason;
2874
- /** An optional error that caused this error. */
2875
- cause;
2876
- /** Construct a not found error. */
2877
- constructor(opts) {
2878
- super(opts.message);
2879
- this.message = opts.message;
2880
- this.name = "OperationError";
2881
- this.query = opts.query;
2882
- this.reason = opts.reason;
2883
- this.cause = opts.cause;
2884
- Object.setPrototypeOf(this, new.target.prototype);
2885
- }
2886
- }
2887
- Collection2.OperationError = OperationError;
2888
- class NotFoundError extends OperationError {
2889
- /**
2890
- * Constructor method.
2891
- * @param opts The error options, see {@link OperationError.Opts}.
2892
- */
2893
- constructor(opts) {
2894
- super(opts);
2895
- this.name = "NotFoundError";
2896
- Object.setPrototypeOf(this, new.target.prototype);
2897
- }
2898
- }
2899
- Collection2.NotFoundError = NotFoundError;
2900
- class OnTransformError extends OperationError {
2901
- /**
2902
- * Constructor method.
2903
- * @param opts The error options, see {@link OperationError.Opts}.
2904
- */
2905
- constructor(opts) {
2906
- super(opts);
2907
- this.name = "OnTransformError";
2908
- Object.setPrototypeOf(this, new.target.prototype);
2909
- }
2910
- }
2911
- Collection2.OnTransformError = OnTransformError;
2912
- class OnLoadError extends OperationError {
2913
- /**
2914
- * Constructor method.
2915
- * @param opts The error options, see {@link OperationError.Opts}.
2916
- */
2917
- constructor(opts) {
2918
- super(opts);
2919
- this.name = "OnLoadError";
2920
- Object.setPrototypeOf(this, new.target.prototype);
2921
- }
2922
- }
2923
- Collection2.OnLoadError = OnLoadError;
2924
- class CountError extends OperationError {
2925
- /**
2926
- * Construct a {@link CountError}.
2927
- * @param opts The error options, see {@link OperationError.Opts}.
2928
- */
2929
- constructor(opts) {
2930
- super(opts);
2931
- this.name = "CountError";
2932
- Object.setPrototypeOf(this, new.target.prototype);
2933
- }
2934
- }
2935
- Collection2.CountError = CountError;
2936
- class ListError extends OperationError {
2937
- /**
2938
- * Constructor method.
2939
- * @param opts The error options, see {@link OperationError.Opts}.
2940
- */
2941
- constructor(opts) {
2942
- super(opts);
2943
- this.name = "ListError";
2944
- Object.setPrototypeOf(this, new.target.prototype);
2945
- }
2946
- }
2947
- Collection2.ListError = ListError;
2948
- class ExistsError extends OperationError {
2949
- /**
2950
- * Constructor method.
2951
- * @param opts The error options, see {@link OperationError.Opts}.
2952
- */
2953
- constructor(opts) {
2954
- super(opts);
2955
- this.name = "ExistsError";
2956
- Object.setPrototypeOf(this, new.target.prototype);
2957
- }
2958
- }
2959
- Collection2.ExistsError = ExistsError;
2960
- class LoadError extends OperationError {
2961
- /**
2962
- * Constructor method.
2963
- * @param opts The error options, see {@link OperationError.Opts}.
2964
- */
2965
- constructor(opts) {
2966
- super(opts);
2967
- this.name = "LoadError";
2968
- Object.setPrototypeOf(this, new.target.prototype);
2969
- }
2970
- }
2971
- Collection2.LoadError = LoadError;
2972
- class SaveError extends OperationError {
2973
- /**
2974
- * Constructor method.
2975
- * @param opts The error options, see {@link OperationError.Opts}.
2976
- */
2977
- constructor(opts) {
2978
- super(opts);
2979
- this.name = "SaveError";
2980
- Object.setPrototypeOf(this, new.target.prototype);
2981
- }
2982
- }
2983
- Collection2.SaveError = SaveError;
2984
- class DeleteError extends OperationError {
2985
- /**
2986
- * Constructor method.
2987
- * @param opts The error options, see {@link OperationError.Opts}.
2988
- */
2989
- constructor(opts) {
2990
- super(opts);
2991
- this.name = "DeleteError";
2992
- Object.setPrototypeOf(this, new.target.prototype);
2993
- }
2994
- }
2995
- Collection2.DeleteError = DeleteError;
2996
- class BulkError extends OperationError {
2997
- /**
2998
- * Constructor method.
2999
- * @param opts The error options, see {@link OperationError.Opts}.
3000
- */
3001
- constructor(opts) {
3002
- super(opts);
3003
- this.name = "BulkError";
3004
- Object.setPrototypeOf(this, new.target.prototype);
3005
- }
3006
- }
3007
- Collection2.BulkError = BulkError;
3008
- class AggregateError extends OperationError {
3009
- /**
3010
- * Constructor method.
3011
- * @param opts The error options, see {@link OperationError.Opts}.
3012
- */
3013
- constructor(opts) {
3014
- super(opts);
3015
- this.name = "AggregateError";
3016
- Object.setPrototypeOf(this, new.target.prototype);
3017
- }
3018
- }
3019
- Collection2.AggregateError = AggregateError;
3020
- let Projection;
3021
- (function(Projection2) {
3022
- function init(projection) {
3023
- if (Array.isArray(projection)) {
3024
- const p = {};
3025
- for (let i = 0; i < projection.length; i++) {
3026
- p[projection[i]] = 1;
3027
- }
3028
- return p;
3029
- } else {
3030
- const p = projection;
3031
- let has_include = false;
3032
- let has_exclude = false;
3033
- for (const [k, v] of Object.entries(p)) {
3034
- if (v === 1 || v === true) {
3035
- if (k !== "_id")
3036
- has_include = true;
3037
- } else if (v === 0 || v === false) {
3038
- if (k !== "_id")
3039
- has_exclude = true;
3040
- } else {
3041
- throw new import_errors.InvalidUsageError({
3042
- message: `Invalid projection value for "${k}": expected 0, 1, true or false.`,
3043
- reason: "invalid_projection"
3044
- });
3045
- }
3046
- if (has_include && has_exclude) {
3047
- throw new import_errors.InvalidUsageError({
3048
- message: "Invalid projection: cannot mix inclusion and exclusion (except for _id).",
3049
- reason: "invalid_projection"
3050
- });
3051
- }
3052
- }
3053
- return p;
3054
- }
3055
- }
3056
- Projection2.init = init;
3057
- })(Projection = Collection2.Projection || (Collection2.Projection = {}));
3058
- {
3059
- }
3060
- })(Collection || (Collection = {}));
3061
- class TransactionCollection extends Collection {
3062
- /**
3063
- * Commit the current transaction.
3064
- * Implements retry logic for transient errors and unknown commit results.
3065
- * @throws {InvalidUsageError} If there is no active session or if the transaction has already been finalized.
3066
- * @throws {Error} If the commit fails after retries or encounters a non-retryable error.
3067
- *
3068
- * @docs
3069
- */
3070
- async commit() {
3071
- const session = this._session;
3072
- if (!session) {
3073
- throw new import_errors.InvalidUsageError({
3074
- message: "No active session for this transaction.",
3075
- reason: "no_session"
3076
- });
3077
- }
3078
- if (this.is_finalized_transaction) {
3079
- throw new import_errors.InvalidUsageError({
3080
- message: "Transaction has already been finalized.",
3081
- reason: "transaction_finalized"
3082
- });
3083
- }
3084
- const max_retries_unknown = 10;
3085
- const base_delay_ms = 20;
3086
- const max_delay_ms = 1e3;
3087
- for (let attempt = 0; attempt <= max_retries_unknown; attempt++) {
3088
- try {
3089
- await session.commitTransaction();
3090
- this.is_finalized_transaction = true;
3091
- try {
3092
- await session.endSession();
3093
- } finally {
3094
- this._session = void 0;
3095
- }
3096
- return;
3097
- } catch (err) {
3098
- const has_label = (label) => {
3099
- if (!err || typeof err !== "object") {
3100
- return false;
3101
- }
3102
- if (typeof err?.hasErrorLabel === "function") {
3103
- try {
3104
- return !!err.hasErrorLabel(label);
3105
- } catch {
3106
- }
3107
- }
3108
- return Array.isArray(err?.errorLabels) && err.errorLabels.includes(label);
3109
- };
3110
- const unknown_commit = has_label("UnknownTransactionCommitResult");
3111
- const transient = has_label("TransientTransactionError");
3112
- const is_networkish = err?.name === "MongoNetworkError" || err?.name === "MongoNetworkTimeoutError";
3113
- if ((unknown_commit || is_networkish) && attempt < max_retries_unknown) {
3114
- const delay = Math.min(max_delay_ms, base_delay_ms * Math.pow(2, attempt));
3115
- await new Promise((res) => setTimeout(res, delay));
3116
- continue;
3117
- }
3118
- if (transient) {
3119
- try {
3120
- await session.abortTransaction();
3121
- } catch {
3122
- }
3123
- this.is_finalized_transaction = true;
3124
- try {
3125
- await session.endSession();
3126
- } finally {
3127
- this._session = void 0;
3128
- }
3129
- const e = new Error(`TransientTransactionError during commit; transaction aborted. Retry the entire transaction. ${err?.message ?? ""}`);
3130
- e.codeName = err?.codeName;
3131
- e.errorLabels = err?.errorLabels;
3132
- throw e;
3133
- }
3134
- if ((unknown_commit || is_networkish) && attempt >= max_retries_unknown) {
3135
- this.is_finalized_transaction = true;
3136
- try {
3137
- await session.endSession();
3138
- } finally {
3139
- this._session = void 0;
3140
- }
3141
- const e = new Error(`Commit failed after ${attempt + 1} attempt(s) with unknown outcome; last error: ${err?.message ?? err}`);
3142
- e.codeName = err?.codeName;
3143
- e.errorLabels = err?.errorLabels;
3144
- throw e;
3145
- }
3146
- this.is_finalized_transaction = true;
3147
- try {
3148
- await session.endSession();
3149
- } finally {
3150
- this._session = void 0;
3151
- }
3152
- throw err;
3153
- }
3154
- }
3155
- }
3156
- /**
3157
- * Abort the current transaction.
3158
- * Implements retry logic for transient errors.
3159
- * @throws {InvalidUsageError} If there is no active session or if the transaction has already been finalized.
3160
- * @throws {Error} If the abort fails after retries or encounters a non-retryable error.
3161
- *
3162
- * @docs
3163
- */
3164
- async abort() {
3165
- const session = this._session;
3166
- if (!session) {
3167
- throw new import_errors.InvalidUsageError({
3168
- message: "No active session for this transaction.",
3169
- reason: "no_session"
3170
- });
3171
- }
3172
- if (this.is_finalized_transaction) {
3173
- throw new import_errors.InvalidUsageError({
3174
- message: "Transaction has already been finalized.",
3175
- reason: "transaction_finalized"
3176
- });
3177
- }
3178
- const max_retries = 5;
3179
- const base_delay_ms = 20;
3180
- const max_delay_ms = 500;
3181
- for (let attempt = 0; attempt <= max_retries; attempt++) {
3182
- try {
3183
- await session.abortTransaction();
3184
- this.is_finalized_transaction = true;
3185
- try {
3186
- await session.endSession();
3187
- } finally {
3188
- this._session = void 0;
3189
- }
3190
- return;
3191
- } catch (err) {
3192
- if (err?.codeName === "NoSuchTransaction") {
3193
- this.is_finalized_transaction = true;
3194
- try {
3195
- await session.endSession();
3196
- } finally {
3197
- this._session = void 0;
3198
- }
3199
- return;
3200
- }
3201
- const has_label = (label) => {
3202
- if (!err || typeof err !== "object") {
3203
- return false;
3204
- }
3205
- if (typeof err?.hasErrorLabel === "function") {
3206
- try {
3207
- return !!err.hasErrorLabel(label);
3208
- } catch {
3209
- }
3210
- }
3211
- return Array.isArray(err?.errorLabels) && err.errorLabels.includes(label);
3212
- };
3213
- const transient = has_label("TransientTransactionError");
3214
- const is_networkish = err?.name === "MongoNetworkError" || err?.name === "MongoNetworkTimeoutError";
3215
- if ((transient || is_networkish) && attempt < max_retries) {
3216
- const delay = Math.min(max_delay_ms, base_delay_ms * Math.pow(2, attempt));
3217
- await new Promise((res) => setTimeout(res, delay));
3218
- continue;
3219
- }
3220
- this.is_finalized_transaction = true;
3221
- try {
3222
- await session.endSession();
3223
- } finally {
3224
- this._session = void 0;
3225
- }
3226
- throw err;
3227
- }
3228
- }
3229
- }
3230
- /**
3231
- * Cleanup method for proper resource management
3232
- * Can be called manually or via async disposal
3233
- *
3234
- * @warning This method aborts the transaction if it is still active.
3235
- * @docs
3236
- */
3237
- async cleanup() {
3238
- if (this._session && !this.is_finalized_transaction) {
3239
- try {
3240
- await this.abort();
3241
- } catch (error) {
3242
- console.error("Failed to abort transaction during cleanup:", error);
3243
- if (this._session) {
3244
- try {
3245
- await this._session.endSession();
3246
- } catch (endError) {
3247
- console.error("Failed to end session during cleanup:", endError);
3248
- }
3249
- }
3250
- } finally {
3251
- this.is_finalized_transaction = true;
3252
- }
3253
- }
3254
- }
3255
- // Support for async disposal (TC39 proposal)
3256
- async [Symbol.asyncDispose]() {
3257
- await this.cleanup();
3258
- }
3259
- /**
3260
- * Check if the transaction is still active (not finalized).
3261
- * @returns True if the transaction is active, false otherwise.
3262
- * @docs
3263
- */
3264
- is_active() {
3265
- return this.is_transaction && !this.is_finalized_transaction && this._session != null;
3266
- }
3267
- }
3268
- async function test_save() {
3269
- const res = void await test_col.save(
3270
- { uid: "" },
3271
- // @ts-ignore
3272
- { uid: "" },
3273
- { return: true }
3274
- );
3275
- const res_no_throw = await test_col.save(
3276
- { uid: "" },
3277
- // @ts-ignore
3278
- { uid: "" },
3279
- { return: true, throw: false, bulk: false }
3280
- );
3281
- function init_save_opts(opts) {
3282
- return opts;
3283
- }
3284
- const a = init_save_opts({ bulk: true, upsert: true });
3285
- const b = init_save_opts({ return: false, upsert: true });
3286
- const b2 = init_save_opts({ return: false, throw: true });
3287
- const c = init_save_opts({ return: true, upsert: false, throw: false });
3288
- const e = init_save_opts({ return: true, upsert: true, bulk: true });
3289
- const res_bulk_op = await test_col.save({ uid: "" }, { uid: "" }, { bulk: true });
3290
- const res_undef = await test_col.save({ uid: "" }, { uid: "" });
3291
- const res_doc = await test_col.save({ uid: "" }, { uid: "" }, { return: true });
3292
- const res_doc_or_undef = await test_col.save({ uid: "" }, { uid: "" }, { return: true, throw: false, upsert: false });
3293
- async function save_wrapper(doc, bulk) {
3294
- return await test_col.save({ id: "test" }, { $set: doc }, { bulk });
3295
- }
3296
- }
3297
- // Annotate the CommonJS export names for ESM import in node:
3298
- 0 && (module.exports = {
3299
- Collection,
3300
- TransactionCollection
3301
- });