@depup/mongodb 7.1.0-depup.0

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 (396) hide show
  1. package/LICENSE.md +201 -0
  2. package/README.md +33 -0
  3. package/etc/prepare.js +12 -0
  4. package/lib/admin.js +136 -0
  5. package/lib/admin.js.map +1 -0
  6. package/lib/bson.js +85 -0
  7. package/lib/bson.js.map +1 -0
  8. package/lib/bulk/common.js +835 -0
  9. package/lib/bulk/common.js.map +1 -0
  10. package/lib/bulk/ordered.js +67 -0
  11. package/lib/bulk/ordered.js.map +1 -0
  12. package/lib/bulk/unordered.js +92 -0
  13. package/lib/bulk/unordered.js.map +1 -0
  14. package/lib/change_stream.js +513 -0
  15. package/lib/change_stream.js.map +1 -0
  16. package/lib/client-side-encryption/auto_encrypter.js +272 -0
  17. package/lib/client-side-encryption/auto_encrypter.js.map +1 -0
  18. package/lib/client-side-encryption/client_encryption.js +609 -0
  19. package/lib/client-side-encryption/client_encryption.js.map +1 -0
  20. package/lib/client-side-encryption/errors.js +138 -0
  21. package/lib/client-side-encryption/errors.js.map +1 -0
  22. package/lib/client-side-encryption/mongocryptd_manager.js +85 -0
  23. package/lib/client-side-encryption/mongocryptd_manager.js.map +1 -0
  24. package/lib/client-side-encryption/providers/aws.js +23 -0
  25. package/lib/client-side-encryption/providers/aws.js.map +1 -0
  26. package/lib/client-side-encryption/providers/azure.js +132 -0
  27. package/lib/client-side-encryption/providers/azure.js.map +1 -0
  28. package/lib/client-side-encryption/providers/gcp.js +16 -0
  29. package/lib/client-side-encryption/providers/gcp.js.map +1 -0
  30. package/lib/client-side-encryption/providers/index.js +43 -0
  31. package/lib/client-side-encryption/providers/index.js.map +1 -0
  32. package/lib/client-side-encryption/state_machine.js +427 -0
  33. package/lib/client-side-encryption/state_machine.js.map +1 -0
  34. package/lib/cmap/auth/auth_provider.js +51 -0
  35. package/lib/cmap/auth/auth_provider.js.map +1 -0
  36. package/lib/cmap/auth/aws4.js +161 -0
  37. package/lib/cmap/auth/aws4.js.map +1 -0
  38. package/lib/cmap/auth/aws_temporary_credentials.js +103 -0
  39. package/lib/cmap/auth/aws_temporary_credentials.js.map +1 -0
  40. package/lib/cmap/auth/gssapi.js +155 -0
  41. package/lib/cmap/auth/gssapi.js.map +1 -0
  42. package/lib/cmap/auth/mongo_credentials.js +169 -0
  43. package/lib/cmap/auth/mongo_credentials.js.map +1 -0
  44. package/lib/cmap/auth/mongodb_aws.js +128 -0
  45. package/lib/cmap/auth/mongodb_aws.js.map +1 -0
  46. package/lib/cmap/auth/mongodb_oidc/automated_callback_workflow.js +84 -0
  47. package/lib/cmap/auth/mongodb_oidc/automated_callback_workflow.js.map +1 -0
  48. package/lib/cmap/auth/mongodb_oidc/azure_machine_workflow.js +62 -0
  49. package/lib/cmap/auth/mongodb_oidc/azure_machine_workflow.js.map +1 -0
  50. package/lib/cmap/auth/mongodb_oidc/callback_workflow.js +141 -0
  51. package/lib/cmap/auth/mongodb_oidc/callback_workflow.js.map +1 -0
  52. package/lib/cmap/auth/mongodb_oidc/command_builders.js +44 -0
  53. package/lib/cmap/auth/mongodb_oidc/command_builders.js.map +1 -0
  54. package/lib/cmap/auth/mongodb_oidc/gcp_machine_workflow.js +39 -0
  55. package/lib/cmap/auth/mongodb_oidc/gcp_machine_workflow.js.map +1 -0
  56. package/lib/cmap/auth/mongodb_oidc/human_callback_workflow.js +122 -0
  57. package/lib/cmap/auth/mongodb_oidc/human_callback_workflow.js.map +1 -0
  58. package/lib/cmap/auth/mongodb_oidc/k8s_machine_workflow.js +32 -0
  59. package/lib/cmap/auth/mongodb_oidc/k8s_machine_workflow.js.map +1 -0
  60. package/lib/cmap/auth/mongodb_oidc/token_cache.js +52 -0
  61. package/lib/cmap/auth/mongodb_oidc/token_cache.js.map +1 -0
  62. package/lib/cmap/auth/mongodb_oidc/token_machine_workflow.js +23 -0
  63. package/lib/cmap/auth/mongodb_oidc/token_machine_workflow.js.map +1 -0
  64. package/lib/cmap/auth/mongodb_oidc.js +73 -0
  65. package/lib/cmap/auth/mongodb_oidc.js.map +1 -0
  66. package/lib/cmap/auth/plain.js +26 -0
  67. package/lib/cmap/auth/plain.js.map +1 -0
  68. package/lib/cmap/auth/providers.js +22 -0
  69. package/lib/cmap/auth/providers.js.map +1 -0
  70. package/lib/cmap/auth/scram.js +254 -0
  71. package/lib/cmap/auth/scram.js.map +1 -0
  72. package/lib/cmap/auth/x509.js +36 -0
  73. package/lib/cmap/auth/x509.js.map +1 -0
  74. package/lib/cmap/command_monitoring_events.js +223 -0
  75. package/lib/cmap/command_monitoring_events.js.map +1 -0
  76. package/lib/cmap/commands.js +535 -0
  77. package/lib/cmap/commands.js.map +1 -0
  78. package/lib/cmap/connect.js +381 -0
  79. package/lib/cmap/connect.js.map +1 -0
  80. package/lib/cmap/connection.js +571 -0
  81. package/lib/cmap/connection.js.map +1 -0
  82. package/lib/cmap/connection_pool.js +558 -0
  83. package/lib/cmap/connection_pool.js.map +1 -0
  84. package/lib/cmap/connection_pool_events.js +190 -0
  85. package/lib/cmap/connection_pool_events.js.map +1 -0
  86. package/lib/cmap/errors.js +108 -0
  87. package/lib/cmap/errors.js.map +1 -0
  88. package/lib/cmap/handshake/client_metadata.js +242 -0
  89. package/lib/cmap/handshake/client_metadata.js.map +1 -0
  90. package/lib/cmap/metrics.js +62 -0
  91. package/lib/cmap/metrics.js.map +1 -0
  92. package/lib/cmap/stream_description.js +70 -0
  93. package/lib/cmap/stream_description.js.map +1 -0
  94. package/lib/cmap/wire_protocol/compression.js +178 -0
  95. package/lib/cmap/wire_protocol/compression.js.map +1 -0
  96. package/lib/cmap/wire_protocol/constants.js +21 -0
  97. package/lib/cmap/wire_protocol/constants.js.map +1 -0
  98. package/lib/cmap/wire_protocol/on_data.js +111 -0
  99. package/lib/cmap/wire_protocol/on_data.js.map +1 -0
  100. package/lib/cmap/wire_protocol/on_demand/document.js +222 -0
  101. package/lib/cmap/wire_protocol/on_demand/document.js.map +1 -0
  102. package/lib/cmap/wire_protocol/responses.js +315 -0
  103. package/lib/cmap/wire_protocol/responses.js.map +1 -0
  104. package/lib/cmap/wire_protocol/shared.js +35 -0
  105. package/lib/cmap/wire_protocol/shared.js.map +1 -0
  106. package/lib/collection.js +751 -0
  107. package/lib/collection.js.map +1 -0
  108. package/lib/connection_string.js +1090 -0
  109. package/lib/connection_string.js.map +1 -0
  110. package/lib/constants.js +170 -0
  111. package/lib/constants.js.map +1 -0
  112. package/lib/cursor/abstract_cursor.js +924 -0
  113. package/lib/cursor/abstract_cursor.js.map +1 -0
  114. package/lib/cursor/aggregation_cursor.js +164 -0
  115. package/lib/cursor/aggregation_cursor.js.map +1 -0
  116. package/lib/cursor/change_stream_cursor.js +104 -0
  117. package/lib/cursor/change_stream_cursor.js.map +1 -0
  118. package/lib/cursor/client_bulk_write_cursor.js +52 -0
  119. package/lib/cursor/client_bulk_write_cursor.js.map +1 -0
  120. package/lib/cursor/explainable_cursor.js +36 -0
  121. package/lib/cursor/explainable_cursor.js.map +1 -0
  122. package/lib/cursor/find_cursor.js +399 -0
  123. package/lib/cursor/find_cursor.js.map +1 -0
  124. package/lib/cursor/list_collections_cursor.js +34 -0
  125. package/lib/cursor/list_collections_cursor.js.map +1 -0
  126. package/lib/cursor/list_indexes_cursor.js +32 -0
  127. package/lib/cursor/list_indexes_cursor.js.map +1 -0
  128. package/lib/cursor/list_search_indexes_cursor.js +14 -0
  129. package/lib/cursor/list_search_indexes_cursor.js.map +1 -0
  130. package/lib/cursor/run_command_cursor.js +94 -0
  131. package/lib/cursor/run_command_cursor.js.map +1 -0
  132. package/lib/db.js +419 -0
  133. package/lib/db.js.map +1 -0
  134. package/lib/deps.js +112 -0
  135. package/lib/deps.js.map +1 -0
  136. package/lib/encrypter.js +106 -0
  137. package/lib/encrypter.js.map +1 -0
  138. package/lib/error.js +1380 -0
  139. package/lib/error.js.map +1 -0
  140. package/lib/explain.js +59 -0
  141. package/lib/explain.js.map +1 -0
  142. package/lib/gridfs/download.js +305 -0
  143. package/lib/gridfs/download.js.map +1 -0
  144. package/lib/gridfs/index.js +164 -0
  145. package/lib/gridfs/index.js.map +1 -0
  146. package/lib/gridfs/upload.js +358 -0
  147. package/lib/gridfs/upload.js.map +1 -0
  148. package/lib/index.js +193 -0
  149. package/lib/index.js.map +1 -0
  150. package/lib/mongo_client.js +557 -0
  151. package/lib/mongo_client.js.map +1 -0
  152. package/lib/mongo_client_auth_providers.js +80 -0
  153. package/lib/mongo_client_auth_providers.js.map +1 -0
  154. package/lib/mongo_logger.js +655 -0
  155. package/lib/mongo_logger.js.map +1 -0
  156. package/lib/mongo_types.js +56 -0
  157. package/lib/mongo_types.js.map +1 -0
  158. package/lib/operations/aggregate.js +90 -0
  159. package/lib/operations/aggregate.js.map +1 -0
  160. package/lib/operations/client_bulk_write/client_bulk_write.js +51 -0
  161. package/lib/operations/client_bulk_write/client_bulk_write.js.map +1 -0
  162. package/lib/operations/client_bulk_write/command_builder.js +340 -0
  163. package/lib/operations/client_bulk_write/command_builder.js.map +1 -0
  164. package/lib/operations/client_bulk_write/common.js +3 -0
  165. package/lib/operations/client_bulk_write/common.js.map +1 -0
  166. package/lib/operations/client_bulk_write/executor.js +120 -0
  167. package/lib/operations/client_bulk_write/executor.js.map +1 -0
  168. package/lib/operations/client_bulk_write/results_merger.js +204 -0
  169. package/lib/operations/client_bulk_write/results_merger.js.map +1 -0
  170. package/lib/operations/command.js +83 -0
  171. package/lib/operations/command.js.map +1 -0
  172. package/lib/operations/count.js +45 -0
  173. package/lib/operations/count.js.map +1 -0
  174. package/lib/operations/create_collection.js +109 -0
  175. package/lib/operations/create_collection.js.map +1 -0
  176. package/lib/operations/delete.js +125 -0
  177. package/lib/operations/delete.js.map +1 -0
  178. package/lib/operations/distinct.js +61 -0
  179. package/lib/operations/distinct.js.map +1 -0
  180. package/lib/operations/drop.js +93 -0
  181. package/lib/operations/drop.js.map +1 -0
  182. package/lib/operations/end_sessions.js +34 -0
  183. package/lib/operations/end_sessions.js.map +1 -0
  184. package/lib/operations/estimated_document_count.js +41 -0
  185. package/lib/operations/estimated_document_count.js.map +1 -0
  186. package/lib/operations/execute_operation.js +239 -0
  187. package/lib/operations/execute_operation.js.map +1 -0
  188. package/lib/operations/find.js +148 -0
  189. package/lib/operations/find.js.map +1 -0
  190. package/lib/operations/find_and_modify.js +158 -0
  191. package/lib/operations/find_and_modify.js.map +1 -0
  192. package/lib/operations/get_more.js +62 -0
  193. package/lib/operations/get_more.js.map +1 -0
  194. package/lib/operations/indexes.js +186 -0
  195. package/lib/operations/indexes.js.map +1 -0
  196. package/lib/operations/insert.js +70 -0
  197. package/lib/operations/insert.js.map +1 -0
  198. package/lib/operations/kill_cursors.js +43 -0
  199. package/lib/operations/kill_cursors.js.map +1 -0
  200. package/lib/operations/list_collections.js +53 -0
  201. package/lib/operations/list_collections.js.map +1 -0
  202. package/lib/operations/list_databases.js +40 -0
  203. package/lib/operations/list_databases.js.map +1 -0
  204. package/lib/operations/operation.js +102 -0
  205. package/lib/operations/operation.js.map +1 -0
  206. package/lib/operations/profiling_level.js +43 -0
  207. package/lib/operations/profiling_level.js.map +1 -0
  208. package/lib/operations/remove_user.js +27 -0
  209. package/lib/operations/remove_user.js.map +1 -0
  210. package/lib/operations/rename.js +38 -0
  211. package/lib/operations/rename.js.map +1 -0
  212. package/lib/operations/run_command.js +47 -0
  213. package/lib/operations/run_command.js.map +1 -0
  214. package/lib/operations/search_indexes/create.js +33 -0
  215. package/lib/operations/search_indexes/create.js.map +1 -0
  216. package/lib/operations/search_indexes/drop.js +43 -0
  217. package/lib/operations/search_indexes/drop.js.map +1 -0
  218. package/lib/operations/search_indexes/update.js +35 -0
  219. package/lib/operations/search_indexes/update.js.map +1 -0
  220. package/lib/operations/set_profiling_level.js +53 -0
  221. package/lib/operations/set_profiling_level.js.map +1 -0
  222. package/lib/operations/stats.js +27 -0
  223. package/lib/operations/stats.js.map +1 -0
  224. package/lib/operations/update.js +188 -0
  225. package/lib/operations/update.js.map +1 -0
  226. package/lib/operations/validate_collection.js +37 -0
  227. package/lib/operations/validate_collection.js.map +1 -0
  228. package/lib/read_concern.js +73 -0
  229. package/lib/read_concern.js.map +1 -0
  230. package/lib/read_preference.js +191 -0
  231. package/lib/read_preference.js.map +1 -0
  232. package/lib/sdam/common.js +49 -0
  233. package/lib/sdam/common.js.map +1 -0
  234. package/lib/sdam/events.js +146 -0
  235. package/lib/sdam/events.js.map +1 -0
  236. package/lib/sdam/monitor.js +544 -0
  237. package/lib/sdam/monitor.js.map +1 -0
  238. package/lib/sdam/server.js +404 -0
  239. package/lib/sdam/server.js.map +1 -0
  240. package/lib/sdam/server_description.js +204 -0
  241. package/lib/sdam/server_description.js.map +1 -0
  242. package/lib/sdam/server_selection.js +294 -0
  243. package/lib/sdam/server_selection.js.map +1 -0
  244. package/lib/sdam/server_selection_events.js +85 -0
  245. package/lib/sdam/server_selection_events.js.map +1 -0
  246. package/lib/sdam/srv_polling.js +108 -0
  247. package/lib/sdam/srv_polling.js.map +1 -0
  248. package/lib/sdam/topology.js +652 -0
  249. package/lib/sdam/topology.js.map +1 -0
  250. package/lib/sdam/topology_description.js +383 -0
  251. package/lib/sdam/topology_description.js.map +1 -0
  252. package/lib/sessions.js +892 -0
  253. package/lib/sessions.js.map +1 -0
  254. package/lib/sort.js +103 -0
  255. package/lib/sort.js.map +1 -0
  256. package/lib/timeout.js +296 -0
  257. package/lib/timeout.js.map +1 -0
  258. package/lib/transactions.js +135 -0
  259. package/lib/transactions.js.map +1 -0
  260. package/lib/utils.js +1163 -0
  261. package/lib/utils.js.map +1 -0
  262. package/lib/write_concern.js +100 -0
  263. package/lib/write_concern.js.map +1 -0
  264. package/mongodb.d.ts +9018 -0
  265. package/package.json +197 -0
  266. package/src/admin.ts +173 -0
  267. package/src/bson.ts +149 -0
  268. package/src/bulk/common.ts +1251 -0
  269. package/src/bulk/ordered.ts +83 -0
  270. package/src/bulk/unordered.ts +115 -0
  271. package/src/change_stream.ts +1160 -0
  272. package/src/client-side-encryption/auto_encrypter.ts +469 -0
  273. package/src/client-side-encryption/client_encryption.ts +1150 -0
  274. package/src/client-side-encryption/errors.ts +144 -0
  275. package/src/client-side-encryption/mongocryptd_manager.ts +100 -0
  276. package/src/client-side-encryption/providers/aws.ts +33 -0
  277. package/src/client-side-encryption/providers/azure.ts +181 -0
  278. package/src/client-side-encryption/providers/gcp.ts +16 -0
  279. package/src/client-side-encryption/providers/index.ts +207 -0
  280. package/src/client-side-encryption/state_machine.ts +651 -0
  281. package/src/cmap/auth/auth_provider.ts +77 -0
  282. package/src/cmap/auth/aws4.ts +207 -0
  283. package/src/cmap/auth/aws_temporary_credentials.ts +129 -0
  284. package/src/cmap/auth/gssapi.ts +203 -0
  285. package/src/cmap/auth/mongo_credentials.ts +292 -0
  286. package/src/cmap/auth/mongodb_aws.ts +179 -0
  287. package/src/cmap/auth/mongodb_oidc/automated_callback_workflow.ts +88 -0
  288. package/src/cmap/auth/mongodb_oidc/azure_machine_workflow.ts +73 -0
  289. package/src/cmap/auth/mongodb_oidc/callback_workflow.ts +188 -0
  290. package/src/cmap/auth/mongodb_oidc/command_builders.ts +53 -0
  291. package/src/cmap/auth/mongodb_oidc/gcp_machine_workflow.ts +46 -0
  292. package/src/cmap/auth/mongodb_oidc/human_callback_workflow.ts +141 -0
  293. package/src/cmap/auth/mongodb_oidc/k8s_machine_workflow.ts +31 -0
  294. package/src/cmap/auth/mongodb_oidc/token_cache.ts +62 -0
  295. package/src/cmap/auth/mongodb_oidc/token_machine_workflow.ts +22 -0
  296. package/src/cmap/auth/mongodb_oidc.ts +185 -0
  297. package/src/cmap/auth/plain.ts +25 -0
  298. package/src/cmap/auth/providers.ts +22 -0
  299. package/src/cmap/auth/scram.ts +344 -0
  300. package/src/cmap/auth/x509.ts +43 -0
  301. package/src/cmap/command_monitoring_events.ts +316 -0
  302. package/src/cmap/commands.ts +788 -0
  303. package/src/cmap/connect.ts +518 -0
  304. package/src/cmap/connection.ts +931 -0
  305. package/src/cmap/connection_pool.ts +831 -0
  306. package/src/cmap/connection_pool_events.ts +300 -0
  307. package/src/cmap/errors.ts +119 -0
  308. package/src/cmap/handshake/client_metadata.ts +353 -0
  309. package/src/cmap/metrics.ts +58 -0
  310. package/src/cmap/stream_description.ts +96 -0
  311. package/src/cmap/wire_protocol/compression.ts +211 -0
  312. package/src/cmap/wire_protocol/constants.ts +17 -0
  313. package/src/cmap/wire_protocol/on_data.ts +139 -0
  314. package/src/cmap/wire_protocol/on_demand/document.ts +358 -0
  315. package/src/cmap/wire_protocol/responses.ts +393 -0
  316. package/src/cmap/wire_protocol/shared.ts +48 -0
  317. package/src/collection.ts +1314 -0
  318. package/src/connection_string.ts +1297 -0
  319. package/src/constants.ts +176 -0
  320. package/src/cursor/abstract_cursor.ts +1247 -0
  321. package/src/cursor/aggregation_cursor.ts +245 -0
  322. package/src/cursor/change_stream_cursor.ts +171 -0
  323. package/src/cursor/client_bulk_write_cursor.ts +83 -0
  324. package/src/cursor/explainable_cursor.ts +51 -0
  325. package/src/cursor/find_cursor.ts +497 -0
  326. package/src/cursor/list_collections_cursor.ts +50 -0
  327. package/src/cursor/list_indexes_cursor.ts +37 -0
  328. package/src/cursor/list_search_indexes_cursor.ts +20 -0
  329. package/src/cursor/run_command_cursor.ts +178 -0
  330. package/src/db.ts +621 -0
  331. package/src/deps.ts +227 -0
  332. package/src/encrypter.ts +127 -0
  333. package/src/error.ts +1567 -0
  334. package/src/explain.ts +124 -0
  335. package/src/gridfs/download.ts +483 -0
  336. package/src/gridfs/index.ts +264 -0
  337. package/src/gridfs/upload.ts +537 -0
  338. package/src/index.ts +633 -0
  339. package/src/mongo_client.ts +1155 -0
  340. package/src/mongo_client_auth_providers.ts +87 -0
  341. package/src/mongo_logger.ts +1081 -0
  342. package/src/mongo_types.ts +678 -0
  343. package/src/operations/aggregate.ts +153 -0
  344. package/src/operations/client_bulk_write/client_bulk_write.ts +72 -0
  345. package/src/operations/client_bulk_write/command_builder.ts +487 -0
  346. package/src/operations/client_bulk_write/common.ts +276 -0
  347. package/src/operations/client_bulk_write/executor.ts +149 -0
  348. package/src/operations/client_bulk_write/results_merger.ts +260 -0
  349. package/src/operations/command.ts +171 -0
  350. package/src/operations/count.ts +74 -0
  351. package/src/operations/create_collection.ts +218 -0
  352. package/src/operations/delete.ts +183 -0
  353. package/src/operations/distinct.ts +92 -0
  354. package/src/operations/drop.ts +130 -0
  355. package/src/operations/end_sessions.ts +44 -0
  356. package/src/operations/estimated_document_count.ts +61 -0
  357. package/src/operations/execute_operation.ts +319 -0
  358. package/src/operations/find.ts +254 -0
  359. package/src/operations/find_and_modify.ts +319 -0
  360. package/src/operations/get_more.ts +108 -0
  361. package/src/operations/indexes.ts +418 -0
  362. package/src/operations/insert.ts +108 -0
  363. package/src/operations/kill_cursors.ts +64 -0
  364. package/src/operations/list_collections.ts +108 -0
  365. package/src/operations/list_databases.ts +68 -0
  366. package/src/operations/operation.ts +181 -0
  367. package/src/operations/profiling_level.ts +46 -0
  368. package/src/operations/remove_user.ts +36 -0
  369. package/src/operations/rename.ts +60 -0
  370. package/src/operations/run_command.ts +79 -0
  371. package/src/operations/search_indexes/create.ts +56 -0
  372. package/src/operations/search_indexes/drop.ts +58 -0
  373. package/src/operations/search_indexes/update.ts +45 -0
  374. package/src/operations/set_profiling_level.ts +74 -0
  375. package/src/operations/stats.ts +37 -0
  376. package/src/operations/update.ts +318 -0
  377. package/src/operations/validate_collection.ts +50 -0
  378. package/src/read_concern.ts +88 -0
  379. package/src/read_preference.ts +256 -0
  380. package/src/sdam/common.ts +74 -0
  381. package/src/sdam/events.ts +219 -0
  382. package/src/sdam/monitor.ts +771 -0
  383. package/src/sdam/server.ts +595 -0
  384. package/src/sdam/server_description.ts +297 -0
  385. package/src/sdam/server_selection.ts +415 -0
  386. package/src/sdam/server_selection_events.ts +142 -0
  387. package/src/sdam/srv_polling.ts +146 -0
  388. package/src/sdam/topology.ts +1100 -0
  389. package/src/sdam/topology_description.ts +548 -0
  390. package/src/sessions.ts +1244 -0
  391. package/src/sort.ts +141 -0
  392. package/src/timeout.ts +405 -0
  393. package/src/transactions.ts +181 -0
  394. package/src/utils.ts +1434 -0
  395. package/src/write_concern.ts +183 -0
  396. package/tsconfig.json +46 -0
@@ -0,0 +1,931 @@
1
+ import { type Readable, Transform, type TransformCallback } from 'stream';
2
+ import { clearTimeout, setTimeout } from 'timers';
3
+
4
+ import {
5
+ type BSONSerializeOptions,
6
+ deserialize,
7
+ type DeserializeOptions,
8
+ type Document,
9
+ type ObjectId
10
+ } from '../bson';
11
+ import { type AutoEncrypter } from '../client-side-encryption/auto_encrypter';
12
+ import {
13
+ CLOSE,
14
+ CLUSTER_TIME_RECEIVED,
15
+ COMMAND_FAILED,
16
+ COMMAND_STARTED,
17
+ COMMAND_SUCCEEDED,
18
+ kDecorateResult,
19
+ PINNED,
20
+ UNPINNED
21
+ } from '../constants';
22
+ import {
23
+ MongoCompatibilityError,
24
+ MONGODB_ERROR_CODES,
25
+ MongoNetworkError,
26
+ MongoNetworkTimeoutError,
27
+ MongoOperationTimeoutError,
28
+ MongoParseError,
29
+ MongoRuntimeError,
30
+ MongoServerError,
31
+ MongoUnexpectedServerResponseError
32
+ } from '../error';
33
+ import type { ServerApi, SupportedNodeConnectionOptions } from '../mongo_client';
34
+ import { type MongoClientAuthProviders } from '../mongo_client_auth_providers';
35
+ import { MongoLoggableComponent, type MongoLogger, SeverityLevel } from '../mongo_logger';
36
+ import { type Abortable, type CancellationToken, TypedEventEmitter } from '../mongo_types';
37
+ import { ReadPreference, type ReadPreferenceLike } from '../read_preference';
38
+ import { ServerType } from '../sdam/common';
39
+ import { applySession, type ClientSession, updateSessionFromResponse } from '../sessions';
40
+ import { type TimeoutContext, TimeoutError } from '../timeout';
41
+ import {
42
+ BufferPool,
43
+ calculateDurationInMs,
44
+ type Callback,
45
+ decorateDecryptionResult,
46
+ HostAddress,
47
+ maxWireVersion,
48
+ type MongoDBNamespace,
49
+ noop,
50
+ once,
51
+ processTimeMS,
52
+ squashError,
53
+ uuidV4
54
+ } from '../utils';
55
+ import type { WriteConcern } from '../write_concern';
56
+ import type { AuthContext } from './auth/auth_provider';
57
+ import type { MongoCredentials } from './auth/mongo_credentials';
58
+ import {
59
+ CommandFailedEvent,
60
+ CommandStartedEvent,
61
+ CommandSucceededEvent
62
+ } from './command_monitoring_events';
63
+ import {
64
+ OpCompressedRequest,
65
+ OpMsgRequest,
66
+ type OpMsgResponse,
67
+ OpQueryRequest,
68
+ type OpReply,
69
+ type WriteProtocolMessageType
70
+ } from './commands';
71
+ import type { Stream } from './connect';
72
+ import type { ClientMetadata } from './handshake/client_metadata';
73
+ import { StreamDescription, type StreamDescriptionOptions } from './stream_description';
74
+ import { type CompressorName, decompressResponse } from './wire_protocol/compression';
75
+ import { onData } from './wire_protocol/on_data';
76
+ import {
77
+ CursorResponse,
78
+ MongoDBResponse,
79
+ type MongoDBResponseConstructor
80
+ } from './wire_protocol/responses';
81
+ import { getReadPreference, isSharded } from './wire_protocol/shared';
82
+
83
+ /** @internal */
84
+ export interface CommandOptions extends BSONSerializeOptions {
85
+ secondaryOk?: boolean;
86
+ /** Specify read preference if command supports it */
87
+ readPreference?: ReadPreferenceLike;
88
+ monitoring?: boolean;
89
+ socketTimeoutMS?: number;
90
+ /** Session to use for the operation */
91
+ session?: ClientSession;
92
+ documentsReturnedIn?: string;
93
+ omitMaxTimeMS?: boolean;
94
+
95
+ // TODO(NODE-2802): Currently the CommandOptions take a property willRetryWrite which is a hint
96
+ // from executeOperation that the txnNum should be applied to this command.
97
+ // Applying a session to a command should happen as part of command construction,
98
+ // most likely in the CommandOperation#executeCommand method, where we have access to
99
+ // the details we need to determine if a txnNum should also be applied.
100
+ willRetryWrite?: boolean;
101
+
102
+ writeConcern?: WriteConcern;
103
+
104
+ directConnection?: boolean;
105
+
106
+ /** @internal */
107
+ timeoutContext?: TimeoutContext;
108
+ }
109
+
110
+ /** @public */
111
+ export interface ProxyOptions {
112
+ proxyHost?: string;
113
+ proxyPort?: number;
114
+ proxyUsername?: string;
115
+ proxyPassword?: string;
116
+ }
117
+
118
+ /** @public */
119
+ export interface ConnectionOptions
120
+ extends SupportedNodeConnectionOptions,
121
+ StreamDescriptionOptions,
122
+ ProxyOptions {
123
+ // Internal creation info
124
+ id: number | '<monitor>';
125
+ generation: number;
126
+ hostAddress: HostAddress;
127
+ /** @internal */
128
+ autoEncrypter?: AutoEncrypter;
129
+ serverApi?: ServerApi;
130
+ monitorCommands: boolean;
131
+ /** @internal */
132
+ connectionType?: any;
133
+ credentials?: MongoCredentials;
134
+ /** @internal */
135
+ authProviders: MongoClientAuthProviders;
136
+ connectTimeoutMS?: number;
137
+ tls: boolean;
138
+ noDelay?: boolean;
139
+ socketTimeoutMS?: number;
140
+ /** @internal */
141
+ cancellationToken?: CancellationToken;
142
+ /** @internal */
143
+ metadata: Promise<ClientMetadata>;
144
+ /** @internal */
145
+ mongoLogger?: MongoLogger | undefined;
146
+ }
147
+
148
+ /** @public */
149
+ export type ConnectionEvents = {
150
+ commandStarted(event: CommandStartedEvent): void;
151
+ commandSucceeded(event: CommandSucceededEvent): void;
152
+ commandFailed(event: CommandFailedEvent): void;
153
+ clusterTimeReceived(clusterTime: Document): void;
154
+ close(): void;
155
+ pinned(pinType: string): void;
156
+ unpinned(pinType: string): void;
157
+ };
158
+
159
+ /** @internal */
160
+ export function hasSessionSupport(conn: Connection): boolean {
161
+ const description = conn.description;
162
+ return description.logicalSessionTimeoutMinutes != null;
163
+ }
164
+
165
+ function streamIdentifier(stream: Stream, options: ConnectionOptions): string {
166
+ if (options.proxyHost) {
167
+ // If proxy options are specified, the properties of `stream` itself
168
+ // will not accurately reflect what endpoint this is connected to.
169
+ return options.hostAddress.toString();
170
+ }
171
+
172
+ const { remoteAddress, remotePort } = stream;
173
+ if (typeof remoteAddress === 'string' && typeof remotePort === 'number') {
174
+ return HostAddress.fromHostPort(remoteAddress, remotePort).toString();
175
+ }
176
+
177
+ return uuidV4().toString('hex');
178
+ }
179
+
180
+ /** @internal */
181
+ export class Connection extends TypedEventEmitter<ConnectionEvents> {
182
+ public id: number | '<monitor>';
183
+ public address: string;
184
+ public lastHelloMS = -1;
185
+ public serverApi?: ServerApi;
186
+ public helloOk = false;
187
+ public authContext?: AuthContext;
188
+ public delayedTimeoutId: NodeJS.Timeout | null = null;
189
+ public generation: number;
190
+ public accessToken?: string;
191
+ public readonly description: Readonly<StreamDescription>;
192
+ /**
193
+ * Represents if the connection has been established:
194
+ * - TCP handshake
195
+ * - TLS negotiated
196
+ * - mongodb handshake (saslStart, saslContinue), includes authentication
197
+ *
198
+ * Once connection is established, command logging can log events (if enabled)
199
+ */
200
+ public established: boolean;
201
+ /** Indicates that the connection (including underlying TCP socket) has been closed. */
202
+ public closed = false;
203
+
204
+ private lastUseTime: number;
205
+ private clusterTime: Document | null = null;
206
+ private error: Error | null = null;
207
+ private dataEvents: AsyncGenerator<Buffer, void, void> | null = null;
208
+
209
+ private readonly socketTimeoutMS: number;
210
+ private readonly monitorCommands: boolean;
211
+ private readonly socket: Stream;
212
+ private readonly messageStream: Readable;
213
+
214
+ /** @event */
215
+ static readonly COMMAND_STARTED = COMMAND_STARTED;
216
+ /** @event */
217
+ static readonly COMMAND_SUCCEEDED = COMMAND_SUCCEEDED;
218
+ /** @event */
219
+ static readonly COMMAND_FAILED = COMMAND_FAILED;
220
+ /** @event */
221
+ static readonly CLUSTER_TIME_RECEIVED = CLUSTER_TIME_RECEIVED;
222
+ /** @event */
223
+ static readonly CLOSE = CLOSE;
224
+ /** @event */
225
+ static readonly PINNED = PINNED;
226
+ /** @event */
227
+ static readonly UNPINNED = UNPINNED;
228
+
229
+ constructor(stream: Stream, options: ConnectionOptions) {
230
+ super();
231
+ this.on('error', noop);
232
+
233
+ this.socket = stream;
234
+ this.id = options.id;
235
+ this.address = streamIdentifier(stream, options);
236
+ this.socketTimeoutMS = options.socketTimeoutMS ?? 0;
237
+ this.monitorCommands = options.monitorCommands;
238
+ this.serverApi = options.serverApi;
239
+ this.mongoLogger = options.mongoLogger;
240
+ this.established = false;
241
+
242
+ this.description = new StreamDescription(this.address, options);
243
+ this.generation = options.generation;
244
+ this.lastUseTime = processTimeMS();
245
+
246
+ this.messageStream = this.socket
247
+ .on('error', this.onSocketError.bind(this))
248
+ .pipe(new SizedMessageTransform({ connection: this }))
249
+ .on('error', this.onTransformError.bind(this));
250
+ this.socket.on('close', this.onClose.bind(this));
251
+ this.socket.on('timeout', this.onTimeout.bind(this));
252
+
253
+ this.messageStream.pause();
254
+ }
255
+
256
+ public get hello() {
257
+ return this.description.hello;
258
+ }
259
+
260
+ // the `connect` method stores the result of the handshake hello on the connection
261
+ public set hello(response: Document | null) {
262
+ this.description.receiveResponse(response);
263
+ Object.freeze(this.description);
264
+ }
265
+
266
+ public get serviceId(): ObjectId | undefined {
267
+ return this.hello?.serviceId;
268
+ }
269
+
270
+ public get loadBalanced(): boolean {
271
+ return this.description.loadBalanced;
272
+ }
273
+
274
+ public get idleTime(): number {
275
+ return calculateDurationInMs(this.lastUseTime);
276
+ }
277
+
278
+ private get hasSessionSupport(): boolean {
279
+ return this.description.logicalSessionTimeoutMinutes != null;
280
+ }
281
+
282
+ private get supportsOpMsg(): boolean {
283
+ return (
284
+ this.description != null &&
285
+ // TODO(NODE-6672,NODE-6287): This guard is primarily for maxWireVersion = 0
286
+ maxWireVersion(this) >= 6 &&
287
+ !this.description.__nodejs_mock_server__
288
+ );
289
+ }
290
+
291
+ private get shouldEmitAndLogCommand(): boolean {
292
+ return (
293
+ (this.monitorCommands ||
294
+ (this.established &&
295
+ !this.authContext?.reauthenticating &&
296
+ this.mongoLogger?.willLog(MongoLoggableComponent.COMMAND, SeverityLevel.DEBUG))) ??
297
+ false
298
+ );
299
+ }
300
+
301
+ public markAvailable(): void {
302
+ this.lastUseTime = processTimeMS();
303
+ }
304
+
305
+ private onSocketError(cause: Error) {
306
+ this.onError(new MongoNetworkError(cause.message, { cause }));
307
+ }
308
+
309
+ private onTransformError(error: Error) {
310
+ this.onError(error);
311
+ }
312
+
313
+ public onError(error: Error) {
314
+ this.cleanup(error);
315
+ }
316
+
317
+ private onClose() {
318
+ const message = `connection ${this.id} to ${this.address} closed`;
319
+ this.cleanup(new MongoNetworkError(message));
320
+ }
321
+
322
+ private onTimeout() {
323
+ this.delayedTimeoutId = setTimeout(() => {
324
+ const message = `connection ${this.id} to ${this.address} timed out`;
325
+ const beforeHandshake = this.hello == null;
326
+ this.cleanup(new MongoNetworkTimeoutError(message, { beforeHandshake }));
327
+ }, 1).unref(); // No need for this timer to hold the event loop open
328
+ }
329
+
330
+ public destroy(): void {
331
+ if (this.closed) {
332
+ return;
333
+ }
334
+
335
+ // load balanced mode requires that these listeners remain on the connection
336
+ // after cleanup on timeouts, errors or close so we remove them before calling
337
+ // cleanup.
338
+ this.removeAllListeners(Connection.PINNED);
339
+ this.removeAllListeners(Connection.UNPINNED);
340
+ const message = `connection ${this.id} to ${this.address} closed`;
341
+ this.cleanup(new MongoNetworkError(message));
342
+ }
343
+
344
+ /**
345
+ * A method that cleans up the connection. When `force` is true, this method
346
+ * forcibly destroys the socket.
347
+ *
348
+ * If an error is provided, any in-flight operations will be closed with the error.
349
+ *
350
+ * This method does nothing if the connection is already closed.
351
+ */
352
+ private cleanup(error: Error): void {
353
+ if (this.closed) {
354
+ return;
355
+ }
356
+
357
+ this.socket.destroy();
358
+ this.error = error;
359
+
360
+ this.dataEvents?.throw(error).then(undefined, squashError);
361
+ this.closed = true;
362
+ this.emit(Connection.CLOSE);
363
+ }
364
+
365
+ private prepareCommand(db: string, command: Document, options: CommandOptions) {
366
+ let cmd = { ...command };
367
+
368
+ const readPreference = getReadPreference(options);
369
+ const session = options?.session;
370
+
371
+ let clusterTime = this.clusterTime;
372
+
373
+ if (this.serverApi) {
374
+ const { version, strict, deprecationErrors } = this.serverApi;
375
+ cmd.apiVersion = version;
376
+ if (strict != null) cmd.apiStrict = strict;
377
+ if (deprecationErrors != null) cmd.apiDeprecationErrors = deprecationErrors;
378
+ }
379
+
380
+ if (this.hasSessionSupport && session) {
381
+ if (
382
+ session.clusterTime &&
383
+ clusterTime &&
384
+ session.clusterTime.clusterTime.greaterThan(clusterTime.clusterTime)
385
+ ) {
386
+ clusterTime = session.clusterTime;
387
+ }
388
+
389
+ const sessionError = applySession(session, cmd, options);
390
+ if (sessionError) throw sessionError;
391
+ } else if (session?.explicit) {
392
+ throw new MongoCompatibilityError('Current topology does not support sessions');
393
+ }
394
+
395
+ // if we have a known cluster time, gossip it
396
+ if (clusterTime) {
397
+ cmd.$clusterTime = clusterTime;
398
+ }
399
+
400
+ // For standalone, drivers MUST NOT set $readPreference.
401
+ if (this.description.type !== ServerType.Standalone) {
402
+ if (
403
+ !isSharded(this) &&
404
+ !this.description.loadBalanced &&
405
+ this.supportsOpMsg &&
406
+ options.directConnection === true &&
407
+ readPreference?.mode === 'primary'
408
+ ) {
409
+ // For mongos and load balancers with 'primary' mode, drivers MUST NOT set $readPreference.
410
+ // For all other types with a direct connection, if the read preference is 'primary'
411
+ // (driver sets 'primary' as default if no read preference is configured),
412
+ // the $readPreference MUST be set to 'primaryPreferred'
413
+ // to ensure that any server type can handle the request.
414
+ cmd.$readPreference = ReadPreference.primaryPreferred.toJSON();
415
+ } else if (isSharded(this) && !this.supportsOpMsg && readPreference?.mode !== 'primary') {
416
+ // When sending a read operation via OP_QUERY and the $readPreference modifier,
417
+ // the query MUST be provided using the $query modifier.
418
+ cmd = {
419
+ $query: cmd,
420
+ $readPreference: readPreference.toJSON()
421
+ };
422
+ } else if (readPreference?.mode !== 'primary') {
423
+ // For mode 'primary', drivers MUST NOT set $readPreference.
424
+ // For all other read preference modes (i.e. 'secondary', 'primaryPreferred', ...),
425
+ // drivers MUST set $readPreference
426
+ cmd.$readPreference = readPreference.toJSON();
427
+ }
428
+ }
429
+
430
+ const commandOptions = {
431
+ numberToSkip: 0,
432
+ numberToReturn: -1,
433
+ checkKeys: false,
434
+ // This value is not overridable
435
+ secondaryOk: readPreference.secondaryOk(),
436
+ ...options
437
+ };
438
+
439
+ options.timeoutContext?.addMaxTimeMSToCommand(cmd, options);
440
+
441
+ const message = this.supportsOpMsg
442
+ ? new OpMsgRequest(db, cmd, commandOptions)
443
+ : new OpQueryRequest(db, cmd, commandOptions);
444
+
445
+ return message;
446
+ }
447
+
448
+ private async *sendWire(
449
+ message: WriteProtocolMessageType,
450
+ options: CommandOptions & Abortable,
451
+ responseType?: MongoDBResponseConstructor
452
+ ): AsyncGenerator<MongoDBResponse> {
453
+ this.throwIfAborted();
454
+
455
+ const timeout =
456
+ options.socketTimeoutMS ??
457
+ options?.timeoutContext?.getSocketTimeoutMS() ??
458
+ this.socketTimeoutMS;
459
+ this.socket.setTimeout(timeout);
460
+
461
+ try {
462
+ await this.writeCommand(message, {
463
+ agreedCompressor: this.description.compressor ?? 'none',
464
+ zlibCompressionLevel: this.description.zlibCompressionLevel,
465
+ timeoutContext: options.timeoutContext,
466
+ signal: options.signal
467
+ });
468
+
469
+ if (message.moreToCome) {
470
+ yield MongoDBResponse.empty;
471
+ return;
472
+ }
473
+
474
+ this.throwIfAborted();
475
+
476
+ if (
477
+ options.timeoutContext?.csotEnabled() &&
478
+ options.timeoutContext.minRoundTripTime != null &&
479
+ options.timeoutContext.remainingTimeMS < options.timeoutContext.minRoundTripTime
480
+ ) {
481
+ throw new MongoOperationTimeoutError(
482
+ 'Server roundtrip time is greater than the time remaining'
483
+ );
484
+ }
485
+
486
+ for await (const response of this.readMany(options)) {
487
+ this.socket.setTimeout(0);
488
+ const bson = response.parse();
489
+
490
+ const document = (responseType ?? MongoDBResponse).make(bson);
491
+
492
+ yield document;
493
+ this.throwIfAborted();
494
+
495
+ this.socket.setTimeout(timeout);
496
+ }
497
+ } finally {
498
+ this.socket.setTimeout(0);
499
+ }
500
+ }
501
+
502
+ private async *sendCommand(
503
+ ns: MongoDBNamespace,
504
+ command: Document,
505
+ options: CommandOptions & Abortable,
506
+ responseType?: MongoDBResponseConstructor
507
+ ) {
508
+ options?.signal?.throwIfAborted();
509
+
510
+ const message = this.prepareCommand(ns.db, command, options);
511
+ let started = 0;
512
+ if (this.shouldEmitAndLogCommand) {
513
+ started = processTimeMS();
514
+ this.emitAndLogCommand(
515
+ this.monitorCommands,
516
+ Connection.COMMAND_STARTED,
517
+ message.databaseName,
518
+ this.established,
519
+ new CommandStartedEvent(this, message, this.description.serverConnectionId)
520
+ );
521
+ }
522
+
523
+ // If `documentsReturnedIn` not set or raw is not enabled, use input bson options
524
+ // Otherwise, support raw flag. Raw only works for cursors that hardcode firstBatch/nextBatch fields
525
+ const bsonOptions: DeserializeOptions =
526
+ options.documentsReturnedIn == null || !options.raw
527
+ ? options
528
+ : {
529
+ ...options,
530
+ raw: false,
531
+ fieldsAsRaw: { [options.documentsReturnedIn]: true }
532
+ };
533
+
534
+ /** MongoDBResponse instance or subclass */
535
+ let document: MongoDBResponse | undefined = undefined;
536
+ /** Cached result of a toObject call */
537
+ let object: Document | undefined = undefined;
538
+ try {
539
+ this.throwIfAborted();
540
+ for await (document of this.sendWire(message, options, responseType)) {
541
+ object = undefined;
542
+ if (options.session != null) {
543
+ updateSessionFromResponse(options.session, document);
544
+ }
545
+
546
+ if (document.$clusterTime) {
547
+ this.clusterTime = document.$clusterTime;
548
+ this.emit(Connection.CLUSTER_TIME_RECEIVED, document.$clusterTime);
549
+ }
550
+
551
+ if (document.ok === 0) {
552
+ if (options.timeoutContext?.csotEnabled() && document.isMaxTimeExpiredError) {
553
+ throw new MongoOperationTimeoutError('Server reported a timeout error', {
554
+ cause: new MongoServerError((object ??= document.toObject(bsonOptions)))
555
+ });
556
+ }
557
+ throw new MongoServerError((object ??= document.toObject(bsonOptions)));
558
+ }
559
+
560
+ if (this.shouldEmitAndLogCommand) {
561
+ this.emitAndLogCommand(
562
+ this.monitorCommands,
563
+ Connection.COMMAND_SUCCEEDED,
564
+ message.databaseName,
565
+ this.established,
566
+ new CommandSucceededEvent(
567
+ this,
568
+ message,
569
+ message.moreToCome ? { ok: 1 } : (object ??= document.toObject(bsonOptions)),
570
+ started,
571
+ this.description.serverConnectionId
572
+ )
573
+ );
574
+ }
575
+
576
+ if (responseType == null) {
577
+ yield (object ??= document.toObject(bsonOptions));
578
+ } else {
579
+ yield document;
580
+ }
581
+
582
+ this.throwIfAborted();
583
+ }
584
+ } catch (error) {
585
+ if (this.shouldEmitAndLogCommand) {
586
+ this.emitAndLogCommand(
587
+ this.monitorCommands,
588
+ Connection.COMMAND_FAILED,
589
+ message.databaseName,
590
+ this.established,
591
+ new CommandFailedEvent(this, message, error, started, this.description.serverConnectionId)
592
+ );
593
+ }
594
+ throw error;
595
+ }
596
+ }
597
+
598
+ public async command<T extends MongoDBResponseConstructor>(
599
+ ns: MongoDBNamespace,
600
+ command: Document,
601
+ options: CommandOptions | undefined,
602
+ responseType: T
603
+ ): Promise<InstanceType<T>>;
604
+
605
+ public async command<T extends MongoDBResponseConstructor>(
606
+ ns: MongoDBNamespace,
607
+ command: Document,
608
+ options: CommandOptions | undefined,
609
+ responseType: T | undefined
610
+ ): Promise<typeof responseType extends undefined ? Document : InstanceType<T>>;
611
+
612
+ public async command(
613
+ ns: MongoDBNamespace,
614
+ command: Document,
615
+ options?: CommandOptions
616
+ ): Promise<Document>;
617
+
618
+ public async command(
619
+ ns: MongoDBNamespace,
620
+ command: Document,
621
+ options: CommandOptions & Abortable = {},
622
+ responseType?: MongoDBResponseConstructor
623
+ ): Promise<Document> {
624
+ this.throwIfAborted();
625
+ options.signal?.throwIfAborted();
626
+
627
+ for await (const document of this.sendCommand(ns, command, options, responseType)) {
628
+ if (options.timeoutContext?.csotEnabled()) {
629
+ if (MongoDBResponse.is(document)) {
630
+ if (document.isMaxTimeExpiredError) {
631
+ throw new MongoOperationTimeoutError('Server reported a timeout error', {
632
+ cause: new MongoServerError(document.toObject())
633
+ });
634
+ }
635
+ } else {
636
+ if (
637
+ (Array.isArray(document?.writeErrors) &&
638
+ document.writeErrors.some(
639
+ error => error?.code === MONGODB_ERROR_CODES.MaxTimeMSExpired
640
+ )) ||
641
+ document?.writeConcernError?.code === MONGODB_ERROR_CODES.MaxTimeMSExpired
642
+ ) {
643
+ throw new MongoOperationTimeoutError('Server reported a timeout error', {
644
+ cause: new MongoServerError(document)
645
+ });
646
+ }
647
+ }
648
+ }
649
+
650
+ return document;
651
+ }
652
+ throw new MongoUnexpectedServerResponseError('Unable to get response from server');
653
+ }
654
+
655
+ public exhaustCommand(
656
+ ns: MongoDBNamespace,
657
+ command: Document,
658
+ options: CommandOptions,
659
+ replyListener: Callback
660
+ ) {
661
+ const exhaustLoop = async () => {
662
+ this.throwIfAborted();
663
+ for await (const reply of this.sendCommand(ns, command, options)) {
664
+ replyListener(undefined, reply);
665
+ this.throwIfAborted();
666
+ }
667
+ throw new MongoUnexpectedServerResponseError('Server ended moreToCome unexpectedly');
668
+ };
669
+
670
+ exhaustLoop().then(undefined, replyListener);
671
+ }
672
+
673
+ private throwIfAborted() {
674
+ if (this.error) throw this.error;
675
+ }
676
+
677
+ /**
678
+ * @internal
679
+ *
680
+ * Writes an OP_MSG or OP_QUERY request to the socket, optionally compressing the command. This method
681
+ * waits until the socket's buffer has emptied (the Nodejs socket `drain` event has fired).
682
+ */
683
+ private async writeCommand(
684
+ command: WriteProtocolMessageType,
685
+ options: {
686
+ agreedCompressor?: CompressorName;
687
+ zlibCompressionLevel?: number;
688
+ timeoutContext?: TimeoutContext;
689
+ } & Abortable
690
+ ): Promise<void> {
691
+ const finalCommand =
692
+ options.agreedCompressor === 'none' || !OpCompressedRequest.canCompress(command)
693
+ ? command
694
+ : new OpCompressedRequest(command, {
695
+ agreedCompressor: options.agreedCompressor ?? 'none',
696
+ zlibCompressionLevel: options.zlibCompressionLevel ?? 0
697
+ });
698
+
699
+ const buffer = Buffer.concat(await finalCommand.toBin());
700
+
701
+ if (options.timeoutContext?.csotEnabled()) {
702
+ if (
703
+ options.timeoutContext.minRoundTripTime != null &&
704
+ options.timeoutContext.remainingTimeMS < options.timeoutContext.minRoundTripTime
705
+ ) {
706
+ throw new MongoOperationTimeoutError(
707
+ 'Server roundtrip time is greater than the time remaining'
708
+ );
709
+ }
710
+ }
711
+
712
+ try {
713
+ if (this.socket.write(buffer)) return;
714
+ } catch (writeError) {
715
+ const networkError = new MongoNetworkError('unexpected error writing to socket', {
716
+ cause: writeError
717
+ });
718
+ this.onError(networkError);
719
+ throw networkError;
720
+ }
721
+
722
+ const drainEvent = once<void>(this.socket, 'drain', options);
723
+ const timeout = options?.timeoutContext?.timeoutForSocketWrite;
724
+ const drained = timeout ? Promise.race([drainEvent, timeout]) : drainEvent;
725
+ try {
726
+ return await drained;
727
+ } catch (writeError) {
728
+ if (TimeoutError.is(writeError)) {
729
+ const timeoutError = new MongoOperationTimeoutError('Timed out at socket write');
730
+ this.onError(timeoutError);
731
+ throw timeoutError;
732
+ } else if (writeError === options.signal?.reason) {
733
+ this.onError(writeError);
734
+ }
735
+ throw writeError;
736
+ } finally {
737
+ timeout?.clear();
738
+ }
739
+ }
740
+
741
+ /**
742
+ * @internal
743
+ *
744
+ * Returns an async generator that yields full wire protocol messages from the underlying socket. This function
745
+ * yields messages until `moreToCome` is false or not present in a response, or the caller cancels the request
746
+ * by calling `return` on the generator.
747
+ *
748
+ * Note that `for-await` loops call `return` automatically when the loop is exited.
749
+ */
750
+ private async *readMany(
751
+ options: {
752
+ timeoutContext?: TimeoutContext;
753
+ } & Abortable
754
+ ): AsyncGenerator<OpMsgResponse | OpReply> {
755
+ try {
756
+ this.dataEvents = onData(this.messageStream, options);
757
+ this.messageStream.resume();
758
+
759
+ for await (const message of this.dataEvents) {
760
+ const response = await decompressResponse(message);
761
+ yield response;
762
+
763
+ if (!response.moreToCome) {
764
+ return;
765
+ }
766
+ }
767
+ } catch (readError) {
768
+ if (TimeoutError.is(readError)) {
769
+ const timeoutError = new MongoOperationTimeoutError(
770
+ `Timed out during socket read (${readError.duration}ms)`
771
+ );
772
+ this.dataEvents = null;
773
+ this.onError(timeoutError);
774
+ throw timeoutError;
775
+ } else if (readError === options.signal?.reason) {
776
+ this.onError(readError);
777
+ }
778
+ throw readError;
779
+ } finally {
780
+ this.dataEvents = null;
781
+ this.messageStream.pause();
782
+ }
783
+ }
784
+ }
785
+
786
+ /** @internal */
787
+ export class SizedMessageTransform extends Transform {
788
+ bufferPool: BufferPool;
789
+ connection: Connection;
790
+
791
+ constructor({ connection }: { connection: Connection }) {
792
+ super({ writableObjectMode: false, readableObjectMode: true });
793
+ this.bufferPool = new BufferPool();
794
+ this.connection = connection;
795
+ }
796
+
797
+ override _transform(chunk: Buffer, encoding: unknown, callback: TransformCallback): void {
798
+ if (this.connection.delayedTimeoutId != null) {
799
+ clearTimeout(this.connection.delayedTimeoutId);
800
+ this.connection.delayedTimeoutId = null;
801
+ }
802
+
803
+ this.bufferPool.append(chunk);
804
+
805
+ while (this.bufferPool.length) {
806
+ // While there are any bytes in the buffer
807
+
808
+ // Try to fetch a size from the top 4 bytes
809
+ const sizeOfMessage = this.bufferPool.getInt32();
810
+
811
+ if (sizeOfMessage == null) {
812
+ // Not even an int32 worth of data. Stop the loop, we need more chunks.
813
+ break;
814
+ }
815
+
816
+ if (sizeOfMessage < 0) {
817
+ // The size in the message has a negative value, this is probably corruption, throw:
818
+ return callback(new MongoParseError(`Message size cannot be negative: ${sizeOfMessage}`));
819
+ }
820
+
821
+ if (sizeOfMessage > this.bufferPool.length) {
822
+ // We do not have enough bytes to make a sizeOfMessage chunk
823
+ break;
824
+ }
825
+
826
+ // Add a message to the stream
827
+ const message = this.bufferPool.read(sizeOfMessage);
828
+
829
+ if (!this.push(message)) {
830
+ // We only subscribe to data events so we should never get backpressure
831
+ // if we do, we do not have the handling for it.
832
+ return callback(
833
+ new MongoRuntimeError(`SizedMessageTransform does not support backpressure`)
834
+ );
835
+ }
836
+ }
837
+
838
+ callback();
839
+ }
840
+ }
841
+
842
+ /** @internal */
843
+ export class CryptoConnection extends Connection {
844
+ /** @internal */
845
+ autoEncrypter?: AutoEncrypter;
846
+
847
+ constructor(stream: Stream, options: ConnectionOptions) {
848
+ super(stream, options);
849
+ this.autoEncrypter = options.autoEncrypter;
850
+ }
851
+
852
+ public override async command<T extends MongoDBResponseConstructor>(
853
+ ns: MongoDBNamespace,
854
+ command: Document,
855
+ options: CommandOptions | undefined,
856
+ responseType: T
857
+ ): Promise<InstanceType<T>>;
858
+
859
+ public override async command(
860
+ ns: MongoDBNamespace,
861
+ command: Document,
862
+ options?: CommandOptions
863
+ ): Promise<Document>;
864
+
865
+ override async command<T extends MongoDBResponseConstructor>(
866
+ ns: MongoDBNamespace,
867
+ cmd: Document,
868
+ options?: CommandOptions,
869
+ responseType?: T
870
+ ): Promise<Document> {
871
+ const { autoEncrypter } = this;
872
+ if (!autoEncrypter) {
873
+ throw new MongoRuntimeError('No AutoEncrypter available for encryption');
874
+ }
875
+
876
+ const serverWireVersion = maxWireVersion(this);
877
+ if (serverWireVersion === 0) {
878
+ // This means the initial handshake hasn't happened yet
879
+ return await super.command<T>(ns, cmd, options, responseType);
880
+ }
881
+
882
+ // Save sort or indexKeys based on the command being run
883
+ // the encrypt API serializes our JS objects to BSON to pass to the native code layer
884
+ // and then deserializes the encrypted result, the protocol level components
885
+ // of the command (ex. sort) are then converted to JS objects potentially losing
886
+ // import key order information. These fields are never encrypted so we can save the values
887
+ // from before the encryption and replace them after encryption has been performed
888
+ const sort: Map<string, number> | null = cmd.find || cmd.findAndModify ? cmd.sort : null;
889
+ const indexKeys: Map<string, number>[] | null = cmd.createIndexes
890
+ ? cmd.indexes.map((index: { key: Map<string, number> }) => index.key)
891
+ : null;
892
+
893
+ const encrypted = await autoEncrypter.encrypt(ns.toString(), cmd, options);
894
+
895
+ // Replace the saved values
896
+ if (sort != null && (cmd.find || cmd.findAndModify)) {
897
+ encrypted.sort = sort;
898
+ }
899
+
900
+ if (indexKeys != null && cmd.createIndexes) {
901
+ for (const [offset, index] of indexKeys.entries()) {
902
+ // @ts-expect-error `encrypted` is a generic "command", but we've narrowed for only `createIndexes` commands here
903
+ encrypted.indexes[offset].key = index;
904
+ }
905
+ }
906
+
907
+ const encryptedResponse = await super.command(
908
+ ns,
909
+ encrypted,
910
+ options,
911
+ // Eventually we want to require `responseType` which means we would satisfy `T` as the return type.
912
+ // In the meantime, we want encryptedResponse to always be _at least_ a MongoDBResponse if not a more specific subclass
913
+ // So that we can ensure we have access to the on-demand APIs for decorate response
914
+ responseType ?? MongoDBResponse
915
+ );
916
+
917
+ const result = await autoEncrypter.decrypt(encryptedResponse.toBytes(), options);
918
+
919
+ const decryptedResponse = responseType?.make(result) ?? deserialize(result, options);
920
+
921
+ if (autoEncrypter[kDecorateResult]) {
922
+ if (responseType == null) {
923
+ decorateDecryptionResult(decryptedResponse, encryptedResponse.toObject(), true);
924
+ } else if (decryptedResponse instanceof CursorResponse) {
925
+ decryptedResponse.encryptedResponse = encryptedResponse;
926
+ }
927
+ }
928
+
929
+ return decryptedResponse;
930
+ }
931
+ }