@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,1100 @@
1
+ import type { BSONSerializeOptions, Document } from '../bson';
2
+ import type { MongoCredentials } from '../cmap/auth/mongo_credentials';
3
+ import type { ConnectionEvents } from '../cmap/connection';
4
+ import type { ConnectionPoolEvents } from '../cmap/connection_pool';
5
+ import type { ClientMetadata } from '../cmap/handshake/client_metadata';
6
+ import { DEFAULT_OPTIONS } from '../connection_string';
7
+ import {
8
+ CLOSE,
9
+ CONNECT,
10
+ ERROR,
11
+ LOCAL_SERVER_EVENTS,
12
+ OPEN,
13
+ SERVER_CLOSED,
14
+ SERVER_DESCRIPTION_CHANGED,
15
+ SERVER_OPENING,
16
+ SERVER_RELAY_EVENTS,
17
+ TIMEOUT,
18
+ TOPOLOGY_CLOSED,
19
+ TOPOLOGY_DESCRIPTION_CHANGED,
20
+ TOPOLOGY_OPENING
21
+ } from '../constants';
22
+ import {
23
+ MongoCompatibilityError,
24
+ type MongoDriverError,
25
+ MongoError,
26
+ MongoErrorLabel,
27
+ MongoOperationTimeoutError,
28
+ MongoRuntimeError,
29
+ MongoServerSelectionError,
30
+ MongoTopologyClosedError
31
+ } from '../error';
32
+ import type { MongoClient, ServerApi } from '../mongo_client';
33
+ import { MongoLoggableComponent, type MongoLogger, SeverityLevel } from '../mongo_logger';
34
+ import { type Abortable, TypedEventEmitter } from '../mongo_types';
35
+ import { ReadPreference, type ReadPreferenceLike } from '../read_preference';
36
+ import type { ClientSession } from '../sessions';
37
+ import { Timeout, TimeoutContext, TimeoutError } from '../timeout';
38
+ import type { Transaction } from '../transactions';
39
+ import {
40
+ addAbortListener,
41
+ type Callback,
42
+ type EventEmitterWithState,
43
+ HostAddress,
44
+ kDispose,
45
+ List,
46
+ makeStateMachine,
47
+ noop,
48
+ processTimeMS,
49
+ promiseWithResolvers,
50
+ shuffle
51
+ } from '../utils';
52
+ import {
53
+ _advanceClusterTime,
54
+ type ClusterTime,
55
+ ServerType,
56
+ STATE_CLOSED,
57
+ STATE_CLOSING,
58
+ STATE_CONNECTED,
59
+ STATE_CONNECTING,
60
+ TopologyType
61
+ } from './common';
62
+ import {
63
+ ServerClosedEvent,
64
+ ServerDescriptionChangedEvent,
65
+ ServerOpeningEvent,
66
+ TopologyClosedEvent,
67
+ TopologyDescriptionChangedEvent,
68
+ TopologyOpeningEvent
69
+ } from './events';
70
+ import type { ServerMonitoringMode } from './monitor';
71
+ import { Server, type ServerEvents, type ServerOptions } from './server';
72
+ import { compareTopologyVersion, ServerDescription } from './server_description';
73
+ import {
74
+ DeprioritizedServers,
75
+ readPreferenceServerSelector,
76
+ type ServerSelector
77
+ } from './server_selection';
78
+ import {
79
+ ServerSelectionFailedEvent,
80
+ ServerSelectionStartedEvent,
81
+ ServerSelectionSucceededEvent,
82
+ WaitingForSuitableServerEvent
83
+ } from './server_selection_events';
84
+ import { SrvPoller, type SrvPollingEvent } from './srv_polling';
85
+ import { TopologyDescription } from './topology_description';
86
+
87
+ // Global state
88
+ let globalTopologyCounter = 0;
89
+
90
+ const stateTransition = makeStateMachine({
91
+ [STATE_CLOSED]: [STATE_CLOSED, STATE_CONNECTING],
92
+ [STATE_CONNECTING]: [STATE_CONNECTING, STATE_CLOSING, STATE_CONNECTED, STATE_CLOSED],
93
+ [STATE_CONNECTED]: [STATE_CONNECTED, STATE_CLOSING, STATE_CLOSED],
94
+ [STATE_CLOSING]: [STATE_CLOSING, STATE_CLOSED]
95
+ });
96
+
97
+ /** @internal */
98
+ export type ServerSelectionCallback = Callback<Server>;
99
+
100
+ /** @internal */
101
+ export interface ServerSelectionRequest {
102
+ serverSelector: ServerSelector;
103
+ topologyDescription: TopologyDescription;
104
+ mongoLogger: MongoLogger | undefined;
105
+ transaction?: Transaction;
106
+ startTime: number;
107
+ resolve: (server: Server) => void;
108
+ reject: (error: MongoError) => void;
109
+ cancelled: boolean;
110
+ operationName: string;
111
+ waitingLogged: boolean;
112
+ deprioritizedServers: DeprioritizedServers;
113
+ }
114
+
115
+ /** @internal */
116
+ export interface TopologyPrivate {
117
+ /** the id of this topology */
118
+ id: number;
119
+ /** passed in options */
120
+ options: TopologyOptions;
121
+ /** initial seedlist of servers to connect to */
122
+ seedlist: HostAddress[];
123
+ /** initial state */
124
+ state: string;
125
+ /** the topology description */
126
+ description: TopologyDescription;
127
+ serverSelectionTimeoutMS: number;
128
+ heartbeatFrequencyMS: number;
129
+ minHeartbeatFrequencyMS: number;
130
+ /** A map of server instances to normalized addresses */
131
+ servers: Map<string, Server>;
132
+ credentials?: MongoCredentials;
133
+ clusterTime?: ClusterTime;
134
+
135
+ /** related to srv polling */
136
+ srvPoller?: SrvPoller;
137
+ detectShardedTopology: (event: TopologyDescriptionChangedEvent) => void;
138
+ detectSrvRecords: (event: SrvPollingEvent) => void;
139
+ }
140
+
141
+ /** @internal */
142
+ export interface TopologyOptions extends BSONSerializeOptions, ServerOptions {
143
+ srvMaxHosts: number;
144
+ srvServiceName: string;
145
+ hosts: HostAddress[];
146
+ retryWrites: boolean;
147
+ retryReads: boolean;
148
+ /** How long to block for server selection before throwing an error */
149
+ serverSelectionTimeoutMS: number;
150
+ /** The name of the replica set to connect to */
151
+ replicaSet?: string;
152
+ srvHost?: string;
153
+ srvPoller?: SrvPoller;
154
+ /** Indicates that a client should directly connect to a node without attempting to discover its topology type */
155
+ directConnection: boolean;
156
+ loadBalanced: boolean;
157
+ metadata: Promise<ClientMetadata>;
158
+ serverMonitoringMode: ServerMonitoringMode;
159
+ /** MongoDB server API version */
160
+ serverApi?: ServerApi;
161
+ __skipPingOnConnect?: boolean;
162
+ }
163
+
164
+ /** @public */
165
+ export interface ConnectOptions {
166
+ readPreference?: ReadPreference;
167
+ }
168
+
169
+ /** @public */
170
+ export interface SelectServerOptions {
171
+ readPreference?: ReadPreferenceLike;
172
+ /** How long to block for server selection before throwing an error */
173
+ serverSelectionTimeoutMS?: number;
174
+ session?: ClientSession;
175
+ operationName: string;
176
+
177
+ /** @internal */
178
+ deprioritizedServers: DeprioritizedServers;
179
+ /**
180
+ * @internal
181
+ * TODO(NODE-6496): Make this required by making ChangeStream use LegacyTimeoutContext
182
+ * */
183
+ timeoutContext?: TimeoutContext;
184
+ }
185
+
186
+ /** @public */
187
+ export type TopologyEvents = {
188
+ /** Top level MongoClient doesn't emit this so it is marked: @internal */
189
+ connect(topology: Topology): void;
190
+ serverOpening(event: ServerOpeningEvent): void;
191
+ serverClosed(event: ServerClosedEvent): void;
192
+ serverDescriptionChanged(event: ServerDescriptionChangedEvent): void;
193
+ topologyClosed(event: TopologyClosedEvent): void;
194
+ topologyOpening(event: TopologyOpeningEvent): void;
195
+ topologyDescriptionChanged(event: TopologyDescriptionChangedEvent): void;
196
+ error(error: Error): void;
197
+ /** @internal */
198
+ open(topology: Topology): void;
199
+ close(): void;
200
+ timeout(): void;
201
+ } & Omit<ServerEvents, 'connect'> &
202
+ ConnectionPoolEvents &
203
+ ConnectionEvents &
204
+ EventEmitterWithState;
205
+ /**
206
+ * A container of server instances representing a connection to a MongoDB topology.
207
+ * @internal
208
+ */
209
+ export class Topology extends TypedEventEmitter<TopologyEvents> {
210
+ /** @internal */
211
+ s: TopologyPrivate;
212
+ /** @internal */
213
+ waitQueue: List<ServerSelectionRequest>;
214
+ /** @internal */
215
+ hello?: Document;
216
+ /** @internal */
217
+ _type?: string;
218
+
219
+ client!: MongoClient;
220
+
221
+ /** @internal */
222
+ private connectionLock?: Promise<Topology>;
223
+
224
+ /** @event */
225
+ static readonly SERVER_OPENING = SERVER_OPENING;
226
+ /** @event */
227
+ static readonly SERVER_CLOSED = SERVER_CLOSED;
228
+ /** @event */
229
+ static readonly SERVER_DESCRIPTION_CHANGED = SERVER_DESCRIPTION_CHANGED;
230
+ /** @event */
231
+ static readonly TOPOLOGY_OPENING = TOPOLOGY_OPENING;
232
+ /** @event */
233
+ static readonly TOPOLOGY_CLOSED = TOPOLOGY_CLOSED;
234
+ /** @event */
235
+ static readonly TOPOLOGY_DESCRIPTION_CHANGED = TOPOLOGY_DESCRIPTION_CHANGED;
236
+ /** @event */
237
+ static readonly ERROR = ERROR;
238
+ /** @event */
239
+ static readonly OPEN = OPEN;
240
+ /** @event */
241
+ static readonly CONNECT = CONNECT;
242
+ /** @event */
243
+ static readonly CLOSE = CLOSE;
244
+ /** @event */
245
+ static readonly TIMEOUT = TIMEOUT;
246
+
247
+ /**
248
+ * @param seedlist - a list of HostAddress instances to connect to
249
+ */
250
+ constructor(
251
+ client: MongoClient,
252
+ seeds: string | string[] | HostAddress | HostAddress[],
253
+ options: TopologyOptions
254
+ ) {
255
+ super();
256
+ this.on('error', noop);
257
+
258
+ this.client = client;
259
+ // Options should only be undefined in tests, MongoClient will always have defined options
260
+ options = options ?? {
261
+ hosts: [HostAddress.fromString('localhost:27017')],
262
+ ...Object.fromEntries(DEFAULT_OPTIONS.entries())
263
+ };
264
+
265
+ if (typeof seeds === 'string') {
266
+ seeds = [HostAddress.fromString(seeds)];
267
+ } else if (!Array.isArray(seeds)) {
268
+ seeds = [seeds];
269
+ }
270
+
271
+ const seedlist: HostAddress[] = [];
272
+ for (const seed of seeds) {
273
+ if (typeof seed === 'string') {
274
+ seedlist.push(HostAddress.fromString(seed));
275
+ } else if (seed instanceof HostAddress) {
276
+ seedlist.push(seed);
277
+ } else {
278
+ // FIXME(NODE-3483): May need to be a MongoParseError
279
+ throw new MongoRuntimeError(`Topology cannot be constructed from ${JSON.stringify(seed)}`);
280
+ }
281
+ }
282
+
283
+ const topologyType = topologyTypeFromOptions(options);
284
+ const topologyId = globalTopologyCounter++;
285
+
286
+ const selectedHosts =
287
+ options.srvMaxHosts == null ||
288
+ options.srvMaxHosts === 0 ||
289
+ options.srvMaxHosts >= seedlist.length
290
+ ? seedlist
291
+ : shuffle(seedlist, options.srvMaxHosts);
292
+
293
+ const serverDescriptions = new Map();
294
+ for (const hostAddress of selectedHosts) {
295
+ serverDescriptions.set(hostAddress.toString(), new ServerDescription(hostAddress));
296
+ }
297
+
298
+ this.waitQueue = new List();
299
+ this.s = {
300
+ // the id of this topology
301
+ id: topologyId,
302
+ // passed in options
303
+ options,
304
+ // initial seedlist of servers to connect to
305
+ seedlist,
306
+ // initial state
307
+ state: STATE_CLOSED,
308
+ // the topology description
309
+ description: new TopologyDescription(
310
+ topologyType,
311
+ serverDescriptions,
312
+ options.replicaSet,
313
+ undefined,
314
+ undefined,
315
+ undefined,
316
+ options
317
+ ),
318
+ serverSelectionTimeoutMS: options.serverSelectionTimeoutMS,
319
+ heartbeatFrequencyMS: options.heartbeatFrequencyMS,
320
+ minHeartbeatFrequencyMS: options.minHeartbeatFrequencyMS,
321
+ // a map of server instances to normalized addresses
322
+ servers: new Map(),
323
+ credentials: options?.credentials,
324
+ clusterTime: undefined,
325
+
326
+ detectShardedTopology: ev => this.detectShardedTopology(ev),
327
+ detectSrvRecords: ev => this.detectSrvRecords(ev)
328
+ };
329
+
330
+ this.mongoLogger = client.mongoLogger;
331
+ this.component = 'topology';
332
+
333
+ if (options.srvHost && !options.loadBalanced) {
334
+ this.s.srvPoller =
335
+ options.srvPoller ??
336
+ new SrvPoller({
337
+ heartbeatFrequencyMS: this.s.heartbeatFrequencyMS,
338
+ srvHost: options.srvHost,
339
+ srvMaxHosts: options.srvMaxHosts,
340
+ srvServiceName: options.srvServiceName
341
+ });
342
+
343
+ this.on(Topology.TOPOLOGY_DESCRIPTION_CHANGED, this.s.detectShardedTopology);
344
+ }
345
+ this.connectionLock = undefined;
346
+ }
347
+
348
+ private detectShardedTopology(event: TopologyDescriptionChangedEvent) {
349
+ const previousType = event.previousDescription.type;
350
+ const newType = event.newDescription.type;
351
+
352
+ const transitionToSharded =
353
+ previousType !== TopologyType.Sharded && newType === TopologyType.Sharded;
354
+ const srvListeners = this.s.srvPoller?.listeners(SrvPoller.SRV_RECORD_DISCOVERY);
355
+ const listeningToSrvPolling = !!srvListeners?.includes(this.s.detectSrvRecords);
356
+
357
+ if (transitionToSharded && !listeningToSrvPolling) {
358
+ this.s.srvPoller?.on(SrvPoller.SRV_RECORD_DISCOVERY, this.s.detectSrvRecords);
359
+ this.s.srvPoller?.start();
360
+ }
361
+ }
362
+
363
+ private detectSrvRecords(ev: SrvPollingEvent) {
364
+ const previousTopologyDescription = this.s.description;
365
+ this.s.description = this.s.description.updateFromSrvPollingEvent(
366
+ ev,
367
+ this.s.options.srvMaxHosts
368
+ );
369
+ if (this.s.description === previousTopologyDescription) {
370
+ // Nothing changed, so return
371
+ return;
372
+ }
373
+
374
+ updateServers(this);
375
+
376
+ this.emitAndLog(
377
+ Topology.TOPOLOGY_DESCRIPTION_CHANGED,
378
+ new TopologyDescriptionChangedEvent(
379
+ this.s.id,
380
+ previousTopologyDescription,
381
+ this.s.description
382
+ )
383
+ );
384
+ }
385
+
386
+ /**
387
+ * @returns A `TopologyDescription` for this topology
388
+ */
389
+ get description(): TopologyDescription {
390
+ return this.s.description;
391
+ }
392
+
393
+ get loadBalanced(): boolean {
394
+ return this.s.options.loadBalanced;
395
+ }
396
+
397
+ get serverApi(): ServerApi | undefined {
398
+ return this.s.options.serverApi;
399
+ }
400
+
401
+ /** Initiate server connect */
402
+ async connect(options?: ConnectOptions): Promise<Topology> {
403
+ this.connectionLock ??= this._connect(options);
404
+ try {
405
+ await this.connectionLock;
406
+ return this;
407
+ } finally {
408
+ this.connectionLock = undefined;
409
+ }
410
+ }
411
+
412
+ private async _connect(options?: ConnectOptions): Promise<Topology> {
413
+ options = options ?? {};
414
+ if (this.s.state === STATE_CONNECTED) {
415
+ return this;
416
+ }
417
+
418
+ stateTransition(this, STATE_CONNECTING);
419
+
420
+ // emit SDAM monitoring events
421
+ this.emitAndLog(Topology.TOPOLOGY_OPENING, new TopologyOpeningEvent(this.s.id));
422
+
423
+ // emit an event for the topology change
424
+ this.emitAndLog(
425
+ Topology.TOPOLOGY_DESCRIPTION_CHANGED,
426
+ new TopologyDescriptionChangedEvent(
427
+ this.s.id,
428
+ new TopologyDescription(TopologyType.Unknown), // initial is always Unknown
429
+ this.s.description
430
+ )
431
+ );
432
+
433
+ // connect all known servers, then attempt server selection to connect
434
+ const serverDescriptions = Array.from(this.s.description.servers.values());
435
+ this.s.servers = new Map(
436
+ serverDescriptions.map(serverDescription => [
437
+ serverDescription.address,
438
+ createAndConnectServer(this, serverDescription)
439
+ ])
440
+ );
441
+
442
+ // In load balancer mode we need to fake a server description getting
443
+ // emitted from the monitor, since the monitor doesn't exist.
444
+ if (this.s.options.loadBalanced) {
445
+ for (const description of serverDescriptions) {
446
+ const newDescription = new ServerDescription(description.hostAddress, undefined, {
447
+ loadBalanced: this.s.options.loadBalanced
448
+ });
449
+ this.serverUpdateHandler(newDescription);
450
+ }
451
+ }
452
+
453
+ const serverSelectionTimeoutMS = this.client.s.options.serverSelectionTimeoutMS;
454
+ const readPreference = options.readPreference ?? ReadPreference.primary;
455
+ const timeoutContext = TimeoutContext.create({
456
+ // TODO(NODE-6448): auto-connect ignores timeoutMS; potential future feature
457
+ timeoutMS: undefined,
458
+ serverSelectionTimeoutMS,
459
+ waitQueueTimeoutMS: this.client.s.options.waitQueueTimeoutMS
460
+ });
461
+ const selectServerOptions = {
462
+ operationName: 'handshake',
463
+ ...options,
464
+ timeoutContext,
465
+ deprioritizedServers: new DeprioritizedServers()
466
+ };
467
+
468
+ try {
469
+ const server = await this.selectServer(
470
+ readPreferenceServerSelector(readPreference),
471
+ selectServerOptions
472
+ );
473
+
474
+ const skipPingOnConnect = this.s.options.__skipPingOnConnect === true;
475
+ if (!skipPingOnConnect) {
476
+ const connection = await server.pool.checkOut({ timeoutContext: timeoutContext });
477
+ server.pool.checkIn(connection);
478
+ stateTransition(this, STATE_CONNECTED);
479
+ this.emit(Topology.OPEN, this);
480
+ this.emit(Topology.CONNECT, this);
481
+
482
+ return this;
483
+ }
484
+
485
+ stateTransition(this, STATE_CONNECTED);
486
+ this.emit(Topology.OPEN, this);
487
+ this.emit(Topology.CONNECT, this);
488
+
489
+ return this;
490
+ } catch (error) {
491
+ this.close();
492
+ throw error;
493
+ }
494
+ }
495
+
496
+ closeCheckedOutConnections() {
497
+ for (const server of this.s.servers.values()) {
498
+ return server.closeCheckedOutConnections();
499
+ }
500
+ }
501
+
502
+ /** Close this topology */
503
+ close(): void {
504
+ if (this.s.state === STATE_CLOSED || this.s.state === STATE_CLOSING) {
505
+ return;
506
+ }
507
+
508
+ for (const server of this.s.servers.values()) {
509
+ closeServer(server, this);
510
+ }
511
+
512
+ this.s.servers.clear();
513
+
514
+ stateTransition(this, STATE_CLOSING);
515
+
516
+ drainWaitQueue(this.waitQueue, new MongoTopologyClosedError());
517
+
518
+ if (this.s.srvPoller) {
519
+ this.s.srvPoller.stop();
520
+ this.s.srvPoller.removeListener(SrvPoller.SRV_RECORD_DISCOVERY, this.s.detectSrvRecords);
521
+ }
522
+
523
+ this.removeListener(Topology.TOPOLOGY_DESCRIPTION_CHANGED, this.s.detectShardedTopology);
524
+
525
+ stateTransition(this, STATE_CLOSED);
526
+
527
+ // emit an event for close
528
+ this.emitAndLog(Topology.TOPOLOGY_CLOSED, new TopologyClosedEvent(this.s.id));
529
+ }
530
+
531
+ /**
532
+ * Selects a server according to the selection predicate provided
533
+ *
534
+ * @param selector - An optional selector to select servers by, defaults to a random selection within a latency window
535
+ * @param options - Optional settings related to server selection
536
+ * @param callback - The callback used to indicate success or failure
537
+ * @returns An instance of a `Server` meeting the criteria of the predicate provided
538
+ */
539
+ async selectServer(
540
+ selector: string | ReadPreference | ServerSelector,
541
+ options: SelectServerOptions & Abortable
542
+ ): Promise<Server> {
543
+ let serverSelector;
544
+ if (typeof selector !== 'function') {
545
+ if (typeof selector === 'string') {
546
+ serverSelector = readPreferenceServerSelector(ReadPreference.fromString(selector));
547
+ } else {
548
+ let readPreference;
549
+ if (selector instanceof ReadPreference) {
550
+ readPreference = selector;
551
+ } else {
552
+ ReadPreference.translate(options);
553
+ readPreference = options.readPreference || ReadPreference.primary;
554
+ }
555
+
556
+ serverSelector = readPreferenceServerSelector(readPreference as ReadPreference);
557
+ }
558
+ } else {
559
+ serverSelector = selector;
560
+ }
561
+
562
+ options = { serverSelectionTimeoutMS: this.s.serverSelectionTimeoutMS, ...options };
563
+ if (
564
+ this.client.mongoLogger?.willLog(MongoLoggableComponent.SERVER_SELECTION, SeverityLevel.DEBUG)
565
+ ) {
566
+ this.client.mongoLogger?.debug(
567
+ MongoLoggableComponent.SERVER_SELECTION,
568
+ new ServerSelectionStartedEvent(selector, this.description, options.operationName)
569
+ );
570
+ }
571
+ let timeout;
572
+ if (options.timeoutContext) timeout = options.timeoutContext.serverSelectionTimeout;
573
+ else {
574
+ timeout = Timeout.expires(options.serverSelectionTimeoutMS ?? 0);
575
+ }
576
+
577
+ const isSharded = this.description.type === TopologyType.Sharded;
578
+ const session = options.session;
579
+ const transaction = session && session.transaction;
580
+
581
+ if (isSharded && transaction && transaction.server) {
582
+ if (
583
+ this.client.mongoLogger?.willLog(
584
+ MongoLoggableComponent.SERVER_SELECTION,
585
+ SeverityLevel.DEBUG
586
+ )
587
+ ) {
588
+ this.client.mongoLogger?.debug(
589
+ MongoLoggableComponent.SERVER_SELECTION,
590
+ new ServerSelectionSucceededEvent(
591
+ selector,
592
+ this.description,
593
+ transaction.server.pool.address,
594
+ options.operationName
595
+ )
596
+ );
597
+ }
598
+ if (options.timeoutContext?.clearServerSelectionTimeout) timeout?.clear();
599
+ return transaction.server;
600
+ }
601
+
602
+ const { promise: serverPromise, resolve, reject } = promiseWithResolvers<Server>();
603
+
604
+ const waitQueueMember: ServerSelectionRequest = {
605
+ serverSelector,
606
+ topologyDescription: this.description,
607
+ mongoLogger: this.client.mongoLogger,
608
+ transaction,
609
+ resolve,
610
+ reject,
611
+ cancelled: false,
612
+ startTime: processTimeMS(),
613
+ operationName: options.operationName,
614
+ waitingLogged: false,
615
+ deprioritizedServers: options.deprioritizedServers
616
+ };
617
+
618
+ const abortListener = addAbortListener(options.signal, function () {
619
+ waitQueueMember.cancelled = true;
620
+ reject(this.reason);
621
+ });
622
+
623
+ this.waitQueue.push(waitQueueMember);
624
+ processWaitQueue(this);
625
+
626
+ try {
627
+ timeout?.throwIfExpired();
628
+ const server = await (timeout ? Promise.race([serverPromise, timeout]) : serverPromise);
629
+ if (options.timeoutContext?.csotEnabled() && server.description.minRoundTripTime !== 0) {
630
+ options.timeoutContext.minRoundTripTime = server.description.minRoundTripTime;
631
+ }
632
+ return server;
633
+ } catch (error) {
634
+ if (TimeoutError.is(error)) {
635
+ // Timeout
636
+ waitQueueMember.cancelled = true;
637
+ const timeoutError = new MongoServerSelectionError(
638
+ `Server selection timed out after ${timeout?.duration} ms`,
639
+ this.description
640
+ );
641
+ if (
642
+ this.client.mongoLogger?.willLog(
643
+ MongoLoggableComponent.SERVER_SELECTION,
644
+ SeverityLevel.DEBUG
645
+ )
646
+ ) {
647
+ this.client.mongoLogger?.debug(
648
+ MongoLoggableComponent.SERVER_SELECTION,
649
+ new ServerSelectionFailedEvent(
650
+ selector,
651
+ this.description,
652
+ timeoutError,
653
+ options.operationName
654
+ )
655
+ );
656
+ }
657
+
658
+ if (options.timeoutContext?.csotEnabled()) {
659
+ throw new MongoOperationTimeoutError('Timed out during server selection', {
660
+ cause: timeoutError
661
+ });
662
+ }
663
+ throw timeoutError;
664
+ }
665
+ // Other server selection error
666
+ throw error;
667
+ } finally {
668
+ abortListener?.[kDispose]();
669
+ if (options.timeoutContext?.clearServerSelectionTimeout) timeout?.clear();
670
+ }
671
+ }
672
+ /**
673
+ * Update the internal TopologyDescription with a ServerDescription
674
+ *
675
+ * @param serverDescription - The server to update in the internal list of server descriptions
676
+ */
677
+ serverUpdateHandler(serverDescription: ServerDescription): void {
678
+ if (!this.s.description.hasServer(serverDescription.address)) {
679
+ return;
680
+ }
681
+
682
+ // ignore this server update if its from an outdated topologyVersion
683
+ if (isStaleServerDescription(this.s.description, serverDescription)) {
684
+ return;
685
+ }
686
+
687
+ // these will be used for monitoring events later
688
+ const previousTopologyDescription = this.s.description;
689
+ const previousServerDescription = this.s.description.servers.get(serverDescription.address);
690
+ if (!previousServerDescription) {
691
+ return;
692
+ }
693
+
694
+ // Driver Sessions Spec: "Whenever a driver receives a cluster time from
695
+ // a server it MUST compare it to the current highest seen cluster time
696
+ // for the deployment. If the new cluster time is higher than the
697
+ // highest seen cluster time it MUST become the new highest seen cluster
698
+ // time. Two cluster times are compared using only the BsonTimestamp
699
+ // value of the clusterTime embedded field."
700
+ const clusterTime = serverDescription.$clusterTime;
701
+ if (clusterTime) {
702
+ _advanceClusterTime(this, clusterTime);
703
+ }
704
+
705
+ // If we already know all the information contained in this updated description, then
706
+ // we don't need to emit SDAM events, but still need to update the description, in order
707
+ // to keep client-tracked attributes like last update time and round trip time up to date
708
+ const equalDescriptions =
709
+ previousServerDescription && previousServerDescription.equals(serverDescription);
710
+
711
+ // first update the TopologyDescription
712
+ this.s.description = this.s.description.update(serverDescription);
713
+ if (this.s.description.compatibilityError) {
714
+ this.emit(Topology.ERROR, new MongoCompatibilityError(this.s.description.compatibilityError));
715
+ return;
716
+ }
717
+
718
+ // emit monitoring events for this change
719
+ if (!equalDescriptions) {
720
+ const newDescription = this.s.description.servers.get(serverDescription.address);
721
+ if (newDescription) {
722
+ this.emit(
723
+ Topology.SERVER_DESCRIPTION_CHANGED,
724
+ new ServerDescriptionChangedEvent(
725
+ this.s.id,
726
+ serverDescription.address,
727
+ previousServerDescription,
728
+ newDescription
729
+ )
730
+ );
731
+ }
732
+ }
733
+
734
+ // update server list from updated descriptions
735
+ updateServers(this, serverDescription);
736
+
737
+ // attempt to resolve any outstanding server selection attempts
738
+ if (this.waitQueue.length > 0) {
739
+ processWaitQueue(this);
740
+ }
741
+
742
+ if (!equalDescriptions) {
743
+ this.emitAndLog(
744
+ Topology.TOPOLOGY_DESCRIPTION_CHANGED,
745
+ new TopologyDescriptionChangedEvent(
746
+ this.s.id,
747
+ previousTopologyDescription,
748
+ this.s.description
749
+ )
750
+ );
751
+ }
752
+ }
753
+
754
+ auth(credentials?: MongoCredentials, callback?: Callback): void {
755
+ if (typeof credentials === 'function') ((callback = credentials), (credentials = undefined));
756
+ if (typeof callback === 'function') callback(undefined, true);
757
+ }
758
+
759
+ isConnected(): boolean {
760
+ return this.s.state === STATE_CONNECTED;
761
+ }
762
+
763
+ isDestroyed(): boolean {
764
+ return this.s.state === STATE_CLOSED;
765
+ }
766
+
767
+ // NOTE: There are many places in code where we explicitly check the last hello
768
+ // to do feature support detection. This should be done any other way, but for
769
+ // now we will just return the first hello seen, which should suffice.
770
+ lastHello(): Document {
771
+ const serverDescriptions = Array.from(this.description.servers.values());
772
+ if (serverDescriptions.length === 0) return {};
773
+ const sd = serverDescriptions.filter(
774
+ (sd: ServerDescription) => sd.type !== ServerType.Unknown
775
+ )[0];
776
+
777
+ const result = sd || { maxWireVersion: this.description.commonWireVersion };
778
+ return result;
779
+ }
780
+
781
+ get commonWireVersion(): number {
782
+ return this.description.commonWireVersion;
783
+ }
784
+
785
+ get logicalSessionTimeoutMinutes(): number | null {
786
+ return this.description.logicalSessionTimeoutMinutes;
787
+ }
788
+
789
+ get clusterTime(): ClusterTime | undefined {
790
+ return this.s.clusterTime;
791
+ }
792
+
793
+ set clusterTime(clusterTime: ClusterTime | undefined) {
794
+ this.s.clusterTime = clusterTime;
795
+ }
796
+ }
797
+
798
+ /** Destroys a server, and removes all event listeners from the instance */
799
+ function closeServer(server: Server, topology: Topology) {
800
+ for (const event of LOCAL_SERVER_EVENTS) {
801
+ server.removeAllListeners(event);
802
+ }
803
+
804
+ server.close();
805
+ topology.emitAndLog(
806
+ Topology.SERVER_CLOSED,
807
+ new ServerClosedEvent(topology.s.id, server.description.address)
808
+ );
809
+
810
+ for (const event of SERVER_RELAY_EVENTS) {
811
+ server.removeAllListeners(event);
812
+ }
813
+ }
814
+
815
+ /** Predicts the TopologyType from options */
816
+ function topologyTypeFromOptions(options?: TopologyOptions) {
817
+ if (options?.directConnection) {
818
+ return TopologyType.Single;
819
+ }
820
+
821
+ if (options?.replicaSet) {
822
+ return TopologyType.ReplicaSetNoPrimary;
823
+ }
824
+
825
+ if (options?.loadBalanced) {
826
+ return TopologyType.LoadBalanced;
827
+ }
828
+
829
+ return TopologyType.Unknown;
830
+ }
831
+
832
+ /**
833
+ * Creates new server instances and attempts to connect them
834
+ *
835
+ * @param topology - The topology that this server belongs to
836
+ * @param serverDescription - The description for the server to initialize and connect to
837
+ */
838
+ function createAndConnectServer(topology: Topology, serverDescription: ServerDescription) {
839
+ topology.emitAndLog(
840
+ Topology.SERVER_OPENING,
841
+ new ServerOpeningEvent(topology.s.id, serverDescription.address)
842
+ );
843
+
844
+ const server = new Server(topology, serverDescription, topology.s.options);
845
+ for (const event of SERVER_RELAY_EVENTS) {
846
+ server.on(event, (e: any) => topology.emit(event, e));
847
+ }
848
+
849
+ server.on(Server.DESCRIPTION_RECEIVED, description => topology.serverUpdateHandler(description));
850
+
851
+ server.connect();
852
+ return server;
853
+ }
854
+
855
+ /**
856
+ * @param topology - Topology to update.
857
+ * @param incomingServerDescription - New server description.
858
+ */
859
+ function updateServers(topology: Topology, incomingServerDescription?: ServerDescription) {
860
+ // update the internal server's description
861
+ if (incomingServerDescription && topology.s.servers.has(incomingServerDescription.address)) {
862
+ const server = topology.s.servers.get(incomingServerDescription.address);
863
+ if (server) {
864
+ server.s.description = incomingServerDescription;
865
+ if (
866
+ incomingServerDescription.error instanceof MongoError &&
867
+ incomingServerDescription.error.hasErrorLabel(MongoErrorLabel.ResetPool)
868
+ ) {
869
+ const interruptInUseConnections = incomingServerDescription.error.hasErrorLabel(
870
+ MongoErrorLabel.InterruptInUseConnections
871
+ );
872
+
873
+ server.pool.clear({ interruptInUseConnections });
874
+ } else if (incomingServerDescription.error == null) {
875
+ const newTopologyType = topology.s.description.type;
876
+ const shouldMarkPoolReady =
877
+ incomingServerDescription.isDataBearing ||
878
+ (incomingServerDescription.type !== ServerType.Unknown &&
879
+ newTopologyType === TopologyType.Single);
880
+ if (shouldMarkPoolReady) {
881
+ server.pool.ready();
882
+ }
883
+ }
884
+ }
885
+ }
886
+
887
+ // add new servers for all descriptions we currently don't know about locally
888
+ for (const serverDescription of topology.description.servers.values()) {
889
+ if (!topology.s.servers.has(serverDescription.address)) {
890
+ const server = createAndConnectServer(topology, serverDescription);
891
+ topology.s.servers.set(serverDescription.address, server);
892
+ }
893
+ }
894
+
895
+ // for all servers no longer known, remove their descriptions and destroy their instances
896
+ for (const entry of topology.s.servers) {
897
+ const serverAddress = entry[0];
898
+ if (topology.description.hasServer(serverAddress)) {
899
+ continue;
900
+ }
901
+
902
+ if (!topology.s.servers.has(serverAddress)) {
903
+ continue;
904
+ }
905
+
906
+ const server = topology.s.servers.get(serverAddress);
907
+ topology.s.servers.delete(serverAddress);
908
+
909
+ // prepare server for garbage collection
910
+ if (server) {
911
+ closeServer(server, topology);
912
+ }
913
+ }
914
+ }
915
+
916
+ function drainWaitQueue(queue: List<ServerSelectionRequest>, drainError: MongoDriverError) {
917
+ while (queue.length) {
918
+ const waitQueueMember = queue.shift();
919
+ if (!waitQueueMember) {
920
+ continue;
921
+ }
922
+
923
+ if (!waitQueueMember.cancelled) {
924
+ if (
925
+ waitQueueMember.mongoLogger?.willLog(
926
+ MongoLoggableComponent.SERVER_SELECTION,
927
+ SeverityLevel.DEBUG
928
+ )
929
+ ) {
930
+ waitQueueMember.mongoLogger?.debug(
931
+ MongoLoggableComponent.SERVER_SELECTION,
932
+ new ServerSelectionFailedEvent(
933
+ waitQueueMember.serverSelector,
934
+ waitQueueMember.topologyDescription,
935
+ drainError,
936
+ waitQueueMember.operationName
937
+ )
938
+ );
939
+ }
940
+ waitQueueMember.reject(drainError);
941
+ }
942
+ }
943
+ }
944
+
945
+ function processWaitQueue(topology: Topology) {
946
+ if (topology.s.state === STATE_CLOSED) {
947
+ drainWaitQueue(topology.waitQueue, new MongoTopologyClosedError());
948
+ return;
949
+ }
950
+
951
+ const isSharded = topology.description.type === TopologyType.Sharded;
952
+ const serverDescriptions = Array.from(topology.description.servers.values());
953
+ const membersToProcess = topology.waitQueue.length;
954
+ for (let i = 0; i < membersToProcess; ++i) {
955
+ const waitQueueMember = topology.waitQueue.shift();
956
+ if (!waitQueueMember) {
957
+ continue;
958
+ }
959
+
960
+ if (waitQueueMember.cancelled) {
961
+ continue;
962
+ }
963
+
964
+ let selectedDescriptions;
965
+ try {
966
+ const serverSelector = waitQueueMember.serverSelector;
967
+ const deprioritizedServers = waitQueueMember.deprioritizedServers;
968
+ selectedDescriptions = serverSelector
969
+ ? serverSelector(topology.description, serverDescriptions, deprioritizedServers)
970
+ : serverDescriptions;
971
+ } catch (selectorError) {
972
+ if (
973
+ topology.client.mongoLogger?.willLog(
974
+ MongoLoggableComponent.SERVER_SELECTION,
975
+ SeverityLevel.DEBUG
976
+ )
977
+ ) {
978
+ topology.client.mongoLogger?.debug(
979
+ MongoLoggableComponent.SERVER_SELECTION,
980
+ new ServerSelectionFailedEvent(
981
+ waitQueueMember.serverSelector,
982
+ topology.description,
983
+ selectorError,
984
+ waitQueueMember.operationName
985
+ )
986
+ );
987
+ }
988
+ waitQueueMember.reject(selectorError);
989
+ continue;
990
+ }
991
+
992
+ let selectedServer: Server | undefined;
993
+ if (selectedDescriptions.length === 0) {
994
+ if (!waitQueueMember.waitingLogged) {
995
+ if (
996
+ topology.client.mongoLogger?.willLog(
997
+ MongoLoggableComponent.SERVER_SELECTION,
998
+ SeverityLevel.INFORMATIONAL
999
+ )
1000
+ ) {
1001
+ topology.client.mongoLogger?.info(
1002
+ MongoLoggableComponent.SERVER_SELECTION,
1003
+ new WaitingForSuitableServerEvent(
1004
+ waitQueueMember.serverSelector,
1005
+ topology.description,
1006
+ topology.s.serverSelectionTimeoutMS !== 0
1007
+ ? topology.s.serverSelectionTimeoutMS -
1008
+ (processTimeMS() - waitQueueMember.startTime)
1009
+ : -1,
1010
+ waitQueueMember.operationName
1011
+ )
1012
+ );
1013
+ }
1014
+ waitQueueMember.waitingLogged = true;
1015
+ }
1016
+ topology.waitQueue.push(waitQueueMember);
1017
+ continue;
1018
+ } else if (selectedDescriptions.length === 1) {
1019
+ selectedServer = topology.s.servers.get(selectedDescriptions[0].address);
1020
+ } else {
1021
+ const descriptions = shuffle(selectedDescriptions, 2);
1022
+ const server1 = topology.s.servers.get(descriptions[0].address);
1023
+ const server2 = topology.s.servers.get(descriptions[1].address);
1024
+
1025
+ selectedServer =
1026
+ server1 && server2 && server1.s.operationCount < server2.s.operationCount
1027
+ ? server1
1028
+ : server2;
1029
+ }
1030
+
1031
+ if (!selectedServer) {
1032
+ const serverSelectionError = new MongoServerSelectionError(
1033
+ 'server selection returned a server description but the server was not found in the topology',
1034
+ topology.description
1035
+ );
1036
+ if (
1037
+ topology.client.mongoLogger?.willLog(
1038
+ MongoLoggableComponent.SERVER_SELECTION,
1039
+ SeverityLevel.DEBUG
1040
+ )
1041
+ ) {
1042
+ topology.client.mongoLogger?.debug(
1043
+ MongoLoggableComponent.SERVER_SELECTION,
1044
+ new ServerSelectionFailedEvent(
1045
+ waitQueueMember.serverSelector,
1046
+ topology.description,
1047
+ serverSelectionError,
1048
+ waitQueueMember.operationName
1049
+ )
1050
+ );
1051
+ }
1052
+ waitQueueMember.reject(serverSelectionError);
1053
+ return;
1054
+ }
1055
+ const transaction = waitQueueMember.transaction;
1056
+ if (isSharded && transaction && transaction.isActive && selectedServer) {
1057
+ transaction.pinServer(selectedServer);
1058
+ }
1059
+
1060
+ if (
1061
+ topology.client.mongoLogger?.willLog(
1062
+ MongoLoggableComponent.SERVER_SELECTION,
1063
+ SeverityLevel.DEBUG
1064
+ )
1065
+ ) {
1066
+ topology.client.mongoLogger?.debug(
1067
+ MongoLoggableComponent.SERVER_SELECTION,
1068
+ new ServerSelectionSucceededEvent(
1069
+ waitQueueMember.serverSelector,
1070
+ waitQueueMember.topologyDescription,
1071
+ selectedServer.pool.address,
1072
+ waitQueueMember.operationName
1073
+ )
1074
+ );
1075
+ }
1076
+ waitQueueMember.resolve(selectedServer);
1077
+ }
1078
+
1079
+ if (topology.waitQueue.length > 0) {
1080
+ // ensure all server monitors attempt monitoring soon
1081
+ for (const [, server] of topology.s.servers) {
1082
+ queueMicrotask(function scheduleServerCheck() {
1083
+ return server.requestCheck();
1084
+ });
1085
+ }
1086
+ }
1087
+ }
1088
+
1089
+ function isStaleServerDescription(
1090
+ topologyDescription: TopologyDescription,
1091
+ incomingServerDescription: ServerDescription
1092
+ ) {
1093
+ const currentServerDescription = topologyDescription.servers.get(
1094
+ incomingServerDescription.address
1095
+ );
1096
+ const currentTopologyVersion = currentServerDescription?.topologyVersion;
1097
+ return (
1098
+ compareTopologyVersion(currentTopologyVersion, incomingServerDescription.topologyVersion) > 0
1099
+ );
1100
+ }