@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,297 @@
1
+ import { type Document, Long, type ObjectId } from '../bson';
2
+ import { type MongoError, MongoRuntimeError } from '../error';
3
+ import {
4
+ arrayStrictEqual,
5
+ compareObjectId,
6
+ errorStrictEqual,
7
+ HostAddress,
8
+ processTimeMS
9
+ } from '../utils';
10
+ import { type ClusterTime, ServerType } from './common';
11
+
12
+ const WRITABLE_SERVER_TYPES = new Set<ServerType>([
13
+ ServerType.RSPrimary,
14
+ ServerType.Standalone,
15
+ ServerType.Mongos,
16
+ ServerType.LoadBalancer
17
+ ]);
18
+
19
+ const DATA_BEARING_SERVER_TYPES = new Set<ServerType>([
20
+ ServerType.RSPrimary,
21
+ ServerType.RSSecondary,
22
+ ServerType.Mongos,
23
+ ServerType.Standalone,
24
+ ServerType.LoadBalancer
25
+ ]);
26
+
27
+ /** @public */
28
+ export interface TopologyVersion {
29
+ processId: ObjectId;
30
+ counter: Long;
31
+ }
32
+
33
+ /** @public */
34
+ export type TagSet = { [key: string]: string };
35
+
36
+ /** @internal */
37
+ export interface ServerDescriptionOptions {
38
+ /** An Error used for better reporting debugging */
39
+ error?: MongoError;
40
+
41
+ /** The average round trip time to ping this server (in ms) */
42
+ roundTripTime?: number;
43
+ /** The minimum round trip time to ping this server over the past 10 samples(in ms) */
44
+ minRoundTripTime?: number;
45
+
46
+ /** If the client is in load balancing mode. */
47
+ loadBalanced?: boolean;
48
+ }
49
+
50
+ /**
51
+ * The client's view of a single server, based on the most recent hello outcome.
52
+ *
53
+ * Internal type, not meant to be directly instantiated
54
+ * @public
55
+ */
56
+ export class ServerDescription {
57
+ address: string;
58
+ type: ServerType;
59
+ hosts: string[];
60
+ passives: string[];
61
+ arbiters: string[];
62
+ tags: TagSet;
63
+ error: MongoError | null;
64
+ topologyVersion: TopologyVersion | null;
65
+ minWireVersion: number;
66
+ maxWireVersion: number;
67
+ roundTripTime: number;
68
+ /** The minimum measurement of the last 10 measurements of roundTripTime that have been collected */
69
+ minRoundTripTime: number;
70
+ lastUpdateTime: number;
71
+ lastWriteDate: number;
72
+ me: string | null;
73
+ primary: string | null;
74
+ setName: string | null;
75
+ setVersion: number | null;
76
+ electionId: ObjectId | null;
77
+ logicalSessionTimeoutMinutes: number | null;
78
+ /** The max message size in bytes for the server. */
79
+ maxMessageSizeBytes: number | null;
80
+ /** The max number of writes in a bulk write command. */
81
+ maxWriteBatchSize: number | null;
82
+ /** The max bson object size. */
83
+ maxBsonObjectSize: number | null;
84
+ /** Indicates server is a mongocryptd instance. */
85
+ iscryptd: boolean;
86
+
87
+ // NOTE: does this belong here? It seems we should gossip the cluster time at the CMAP level
88
+ $clusterTime?: ClusterTime;
89
+
90
+ /**
91
+ * Create a ServerDescription
92
+ * @internal
93
+ *
94
+ * @param address - The address of the server
95
+ * @param hello - An optional hello response for this server
96
+ */
97
+ constructor(
98
+ address: HostAddress | string,
99
+ hello?: Document,
100
+ options: ServerDescriptionOptions = {}
101
+ ) {
102
+ if (address == null || address === '') {
103
+ throw new MongoRuntimeError('ServerDescription must be provided with a non-empty address');
104
+ }
105
+
106
+ this.address =
107
+ typeof address === 'string'
108
+ ? HostAddress.fromString(address).toString() // Use HostAddress to normalize
109
+ : address.toString();
110
+ this.type = parseServerType(hello, options);
111
+ this.hosts = hello?.hosts?.map((host: string) => host.toLowerCase()) ?? [];
112
+ this.passives = hello?.passives?.map((host: string) => host.toLowerCase()) ?? [];
113
+ this.arbiters = hello?.arbiters?.map((host: string) => host.toLowerCase()) ?? [];
114
+ this.tags = hello?.tags ?? {};
115
+ this.minWireVersion = hello?.minWireVersion ?? 0;
116
+ this.maxWireVersion = hello?.maxWireVersion ?? 0;
117
+ this.roundTripTime = options?.roundTripTime ?? -1;
118
+ this.minRoundTripTime = options?.minRoundTripTime ?? 0;
119
+ this.lastUpdateTime = processTimeMS();
120
+ this.lastWriteDate = hello?.lastWrite?.lastWriteDate ?? 0;
121
+ // NOTE: This actually builds the stack string instead of holding onto the getter and all its
122
+ // associated references. This is done to prevent a memory leak.
123
+ this.error = options.error ?? null;
124
+ this.error?.stack;
125
+ // TODO(NODE-2674): Preserve int64 sent from MongoDB
126
+ this.topologyVersion = this.error?.topologyVersion ?? hello?.topologyVersion ?? null;
127
+ this.setName = hello?.setName ?? null;
128
+ this.setVersion = hello?.setVersion ?? null;
129
+ this.electionId = hello?.electionId ?? null;
130
+ this.logicalSessionTimeoutMinutes = hello?.logicalSessionTimeoutMinutes ?? null;
131
+ this.maxMessageSizeBytes = hello?.maxMessageSizeBytes ?? null;
132
+ this.maxWriteBatchSize = hello?.maxWriteBatchSize ?? null;
133
+ this.maxBsonObjectSize = hello?.maxBsonObjectSize ?? null;
134
+ this.primary = hello?.primary ?? null;
135
+ this.me = hello?.me?.toLowerCase() ?? null;
136
+ this.$clusterTime = hello?.$clusterTime ?? null;
137
+ this.iscryptd = Boolean(hello?.iscryptd);
138
+ }
139
+
140
+ get hostAddress(): HostAddress {
141
+ return HostAddress.fromString(this.address);
142
+ }
143
+
144
+ get allHosts(): string[] {
145
+ return this.hosts.concat(this.arbiters).concat(this.passives);
146
+ }
147
+
148
+ /** Is this server available for reads*/
149
+ get isReadable(): boolean {
150
+ return this.type === ServerType.RSSecondary || this.isWritable;
151
+ }
152
+
153
+ /** Is this server data bearing */
154
+ get isDataBearing(): boolean {
155
+ return DATA_BEARING_SERVER_TYPES.has(this.type);
156
+ }
157
+
158
+ /** Is this server available for writes */
159
+ get isWritable(): boolean {
160
+ return WRITABLE_SERVER_TYPES.has(this.type);
161
+ }
162
+
163
+ get host(): string {
164
+ const chopLength = `:${this.port}`.length;
165
+ return this.address.slice(0, -chopLength);
166
+ }
167
+
168
+ get port(): number {
169
+ const port = this.address.split(':').pop();
170
+ return port ? Number.parseInt(port, 10) : 27017;
171
+ }
172
+
173
+ /**
174
+ * Determines if another `ServerDescription` is equal to this one per the rules defined in the SDAM specification.
175
+ * @see https://github.com/mongodb/specifications/blob/master/source/server-discovery-and-monitoring/server-discovery-and-monitoring.md
176
+ */
177
+ equals(other?: ServerDescription | null): boolean {
178
+ // Despite using the comparator that would determine a nullish topologyVersion as greater than
179
+ // for equality we should only always perform direct equality comparison
180
+ const topologyVersionsEqual =
181
+ this.topologyVersion === other?.topologyVersion ||
182
+ compareTopologyVersion(this.topologyVersion, other?.topologyVersion) === 0;
183
+
184
+ const electionIdsEqual =
185
+ this.electionId != null && other?.electionId != null
186
+ ? compareObjectId(this.electionId, other.electionId) === 0
187
+ : this.electionId === other?.electionId;
188
+
189
+ return (
190
+ other != null &&
191
+ other.iscryptd === this.iscryptd &&
192
+ errorStrictEqual(this.error, other.error) &&
193
+ this.type === other.type &&
194
+ this.minWireVersion === other.minWireVersion &&
195
+ arrayStrictEqual(this.hosts, other.hosts) &&
196
+ tagsStrictEqual(this.tags, other.tags) &&
197
+ this.setName === other.setName &&
198
+ this.setVersion === other.setVersion &&
199
+ electionIdsEqual &&
200
+ this.primary === other.primary &&
201
+ this.logicalSessionTimeoutMinutes === other.logicalSessionTimeoutMinutes &&
202
+ topologyVersionsEqual
203
+ );
204
+ }
205
+ }
206
+
207
+ // Parses a `hello` message and determines the server type
208
+ export function parseServerType(hello?: Document, options?: ServerDescriptionOptions): ServerType {
209
+ if (options?.loadBalanced) {
210
+ return ServerType.LoadBalancer;
211
+ }
212
+
213
+ if (!hello || !hello.ok) {
214
+ return ServerType.Unknown;
215
+ }
216
+
217
+ if (hello.isreplicaset) {
218
+ return ServerType.RSGhost;
219
+ }
220
+
221
+ if (hello.msg && hello.msg === 'isdbgrid') {
222
+ return ServerType.Mongos;
223
+ }
224
+
225
+ if (hello.setName) {
226
+ if (hello.hidden) {
227
+ return ServerType.RSOther;
228
+ } else if (hello.isWritablePrimary) {
229
+ return ServerType.RSPrimary;
230
+ } else if (hello.secondary) {
231
+ return ServerType.RSSecondary;
232
+ } else if (hello.arbiterOnly) {
233
+ return ServerType.RSArbiter;
234
+ } else {
235
+ return ServerType.RSOther;
236
+ }
237
+ }
238
+
239
+ return ServerType.Standalone;
240
+ }
241
+
242
+ function tagsStrictEqual(tags: TagSet, tags2: TagSet): boolean {
243
+ const tagsKeys = Object.keys(tags);
244
+ const tags2Keys = Object.keys(tags2);
245
+
246
+ return (
247
+ tagsKeys.length === tags2Keys.length &&
248
+ tagsKeys.every((key: string) => tags2[key] === tags[key])
249
+ );
250
+ }
251
+
252
+ /**
253
+ * Compares two topology versions.
254
+ *
255
+ * 1. If the response topologyVersion is unset or the ServerDescription's
256
+ * topologyVersion is null, the client MUST assume the response is more recent.
257
+ * 1. If the response's topologyVersion.processId is not equal to the
258
+ * ServerDescription's, the client MUST assume the response is more recent.
259
+ * 1. If the response's topologyVersion.processId is equal to the
260
+ * ServerDescription's, the client MUST use the counter field to determine
261
+ * which topologyVersion is more recent.
262
+ *
263
+ * ```ts
264
+ * currentTv < newTv === -1
265
+ * currentTv === newTv === 0
266
+ * currentTv > newTv === 1
267
+ * ```
268
+ */
269
+ export function compareTopologyVersion(
270
+ currentTv?: TopologyVersion | null,
271
+ newTv?: TopologyVersion | null
272
+ ): 0 | -1 | 1 {
273
+ if (currentTv == null || newTv == null) {
274
+ return -1;
275
+ }
276
+
277
+ if (!currentTv.processId.equals(newTv.processId)) {
278
+ return -1;
279
+ }
280
+
281
+ // TODO(NODE-2674): Preserve int64 sent from MongoDB
282
+ const currentCounter =
283
+ typeof currentTv.counter === 'bigint'
284
+ ? Long.fromBigInt(currentTv.counter)
285
+ : Long.isLong(currentTv.counter)
286
+ ? currentTv.counter
287
+ : Long.fromNumber(currentTv.counter);
288
+
289
+ const newCounter =
290
+ typeof newTv.counter === 'bigint'
291
+ ? Long.fromBigInt(newTv.counter)
292
+ : Long.isLong(newTv.counter)
293
+ ? newTv.counter
294
+ : Long.fromNumber(newTv.counter);
295
+
296
+ return currentCounter.compare(newCounter);
297
+ }
@@ -0,0 +1,415 @@
1
+ import { MongoInvalidArgumentError, MongoRuntimeError } from '../error';
2
+ import { ReadPreference } from '../read_preference';
3
+ import { ServerType, TopologyType } from './common';
4
+ import type { ServerDescription, TagSet } from './server_description';
5
+ import type { TopologyDescription } from './topology_description';
6
+
7
+ // max staleness constants
8
+ const IDLE_WRITE_PERIOD = 10000;
9
+ const SMALLEST_MAX_STALENESS_SECONDS = 90;
10
+
11
+ // Minimum version to try writes on secondaries.
12
+ export const MIN_SECONDARY_WRITE_WIRE_VERSION = 13;
13
+
14
+ /** @internal */
15
+ export type ServerSelector = (
16
+ topologyDescription: TopologyDescription,
17
+ servers: ServerDescription[],
18
+ deprioritized: DeprioritizedServers
19
+ ) => ServerDescription[];
20
+
21
+ /** @internal */
22
+ export class DeprioritizedServers {
23
+ private deprioritized: Set<string> = new Set();
24
+
25
+ constructor(descriptions?: Iterable<ServerDescription>) {
26
+ for (const description of descriptions ?? []) {
27
+ this.add(description);
28
+ }
29
+ }
30
+
31
+ add({ address }: ServerDescription) {
32
+ this.deprioritized.add(address);
33
+ }
34
+
35
+ has({ address }: ServerDescription): boolean {
36
+ return this.deprioritized.has(address);
37
+ }
38
+ }
39
+
40
+ function filterDeprioritized(
41
+ candidates: ServerDescription[],
42
+ deprioritized: DeprioritizedServers
43
+ ): ServerDescription[] {
44
+ const filtered = candidates.filter(candidate => !deprioritized.has(candidate));
45
+
46
+ return filtered.length ? filtered : candidates;
47
+ }
48
+
49
+ /**
50
+ * Returns a server selector that selects for writable servers
51
+ */
52
+ export function writableServerSelector(): ServerSelector {
53
+ return function writableServer(
54
+ topologyDescription: TopologyDescription,
55
+ servers: ServerDescription[],
56
+ deprioritized: DeprioritizedServers
57
+ ): ServerDescription[] {
58
+ const eligibleServers = filterDeprioritized(
59
+ servers.filter(({ isWritable }) => isWritable),
60
+ deprioritized
61
+ );
62
+
63
+ return latencyWindowReducer(topologyDescription, eligibleServers);
64
+ };
65
+ }
66
+
67
+ /**
68
+ * The purpose of this selector is to select the same server, only
69
+ * if it is in a state that it can have commands sent to it.
70
+ */
71
+ export function sameServerSelector(description?: ServerDescription): ServerSelector {
72
+ return function sameServerSelector(
73
+ _topologyDescription: TopologyDescription,
74
+ servers: ServerDescription[],
75
+ _deprioritized: DeprioritizedServers
76
+ ): ServerDescription[] {
77
+ if (!description) return [];
78
+ // Filter the servers to match the provided description only if
79
+ // the type is not unknown.
80
+ return servers.filter(sd => {
81
+ return sd.address === description.address && sd.type !== ServerType.Unknown;
82
+ });
83
+ };
84
+ }
85
+
86
+ /**
87
+ * Returns a server selector that uses a read preference to select a
88
+ * server potentially for a write on a secondary.
89
+ */
90
+ export function secondaryWritableServerSelector(
91
+ wireVersion: number,
92
+ readPreference?: ReadPreference
93
+ ): ServerSelector {
94
+ // If server version < 5.0, read preference always primary.
95
+ // If server version >= 5.0...
96
+ // - If read preference is supplied, use that.
97
+ // - If no read preference is supplied, use primary.
98
+ if (
99
+ !readPreference ||
100
+ !wireVersion ||
101
+ (wireVersion && wireVersion < MIN_SECONDARY_WRITE_WIRE_VERSION)
102
+ ) {
103
+ return readPreferenceServerSelector(ReadPreference.primary);
104
+ }
105
+ return readPreferenceServerSelector(readPreference);
106
+ }
107
+
108
+ /**
109
+ * Reduces the passed in array of servers by the rules of the "Max Staleness" specification
110
+ * found here:
111
+ *
112
+ * @see https://github.com/mongodb/specifications/blob/master/source/max-staleness/max-staleness.md
113
+ *
114
+ * @param readPreference - The read preference providing max staleness guidance
115
+ * @param topologyDescription - The topology description
116
+ * @param servers - The list of server descriptions to be reduced
117
+ * @returns The list of servers that satisfy the requirements of max staleness
118
+ */
119
+ function maxStalenessReducer(
120
+ readPreference: ReadPreference,
121
+ topologyDescription: TopologyDescription,
122
+ servers: ServerDescription[]
123
+ ): ServerDescription[] {
124
+ if (readPreference.maxStalenessSeconds == null || readPreference.maxStalenessSeconds < 0) {
125
+ return servers;
126
+ }
127
+
128
+ const maxStaleness = readPreference.maxStalenessSeconds;
129
+ const maxStalenessVariance =
130
+ (topologyDescription.heartbeatFrequencyMS + IDLE_WRITE_PERIOD) / 1000;
131
+ if (maxStaleness < maxStalenessVariance) {
132
+ throw new MongoInvalidArgumentError(
133
+ `Option "maxStalenessSeconds" must be at least ${maxStalenessVariance} seconds`
134
+ );
135
+ }
136
+
137
+ if (maxStaleness < SMALLEST_MAX_STALENESS_SECONDS) {
138
+ throw new MongoInvalidArgumentError(
139
+ `Option "maxStalenessSeconds" must be at least ${SMALLEST_MAX_STALENESS_SECONDS} seconds`
140
+ );
141
+ }
142
+
143
+ if (topologyDescription.type === TopologyType.ReplicaSetWithPrimary) {
144
+ const primary: ServerDescription = Array.from(topologyDescription.servers.values()).filter(
145
+ primaryFilter
146
+ )[0];
147
+
148
+ return servers.filter((server: ServerDescription) => {
149
+ const stalenessMS =
150
+ server.lastUpdateTime -
151
+ server.lastWriteDate -
152
+ (primary.lastUpdateTime - primary.lastWriteDate) +
153
+ topologyDescription.heartbeatFrequencyMS;
154
+
155
+ const staleness = stalenessMS / 1000;
156
+ const maxStalenessSeconds = readPreference.maxStalenessSeconds ?? 0;
157
+ return staleness <= maxStalenessSeconds;
158
+ });
159
+ }
160
+
161
+ if (topologyDescription.type === TopologyType.ReplicaSetNoPrimary) {
162
+ if (servers.length === 0) {
163
+ return servers;
164
+ }
165
+
166
+ const sMax = servers.reduce((max: ServerDescription, s: ServerDescription) =>
167
+ s.lastWriteDate > max.lastWriteDate ? s : max
168
+ );
169
+
170
+ return servers.filter((server: ServerDescription) => {
171
+ const stalenessMS =
172
+ sMax.lastWriteDate - server.lastWriteDate + topologyDescription.heartbeatFrequencyMS;
173
+
174
+ const staleness = stalenessMS / 1000;
175
+ const maxStalenessSeconds = readPreference.maxStalenessSeconds ?? 0;
176
+ return staleness <= maxStalenessSeconds;
177
+ });
178
+ }
179
+
180
+ return servers;
181
+ }
182
+
183
+ /**
184
+ * Determines whether a server's tags match a given set of tags.
185
+ *
186
+ * A tagset matches the server's tags if every k-v pair in the tagset
187
+ * is also in the server's tagset.
188
+ *
189
+ * Note that this does not requires that every k-v pair in the server's tagset is also
190
+ * in the client's tagset. The server's tagset is required only to be a superset of the
191
+ * client's tags.
192
+ *
193
+ * @see https://github.com/mongodb/specifications/blob/master/source/server-selection/server-selection.md#tag_sets
194
+ *
195
+ * @param tagSet - The requested tag set to match
196
+ * @param serverTags - The server's tags
197
+ */
198
+ function tagSetMatch(tagSet: TagSet, serverTags: TagSet) {
199
+ return Object.entries(tagSet).every(
200
+ ([key, value]) => serverTags[key] != null && serverTags[key] === value
201
+ );
202
+ }
203
+
204
+ /**
205
+ * Reduces a set of server descriptions based on tags requested by the read preference
206
+ *
207
+ * @param readPreference - The read preference providing the requested tags
208
+ * @param servers - The list of server descriptions to reduce
209
+ * @returns The list of servers matching the requested tags
210
+ */
211
+ function tagSetReducer(
212
+ { tags }: ReadPreference,
213
+ servers: ServerDescription[]
214
+ ): ServerDescription[] {
215
+ if (tags == null || tags.length === 0) {
216
+ // empty tag sets match all servers
217
+ return servers;
218
+ }
219
+
220
+ for (const tagSet of tags) {
221
+ const serversMatchingTagset = servers.filter((s: ServerDescription) =>
222
+ tagSetMatch(tagSet, s.tags)
223
+ );
224
+
225
+ if (serversMatchingTagset.length) {
226
+ return serversMatchingTagset;
227
+ }
228
+ }
229
+
230
+ return [];
231
+ }
232
+
233
+ /**
234
+ * Reduces a list of servers to ensure they fall within an acceptable latency window. This is
235
+ * further specified in the "Server Selection" specification, found here:
236
+ *
237
+ * @see https://github.com/mongodb/specifications/blob/master/source/server-selection/server-selection.md
238
+ *
239
+ * @param topologyDescription - The topology description
240
+ * @param servers - The list of servers to reduce
241
+ * @returns The servers which fall within an acceptable latency window
242
+ */
243
+ function latencyWindowReducer(
244
+ topologyDescription: TopologyDescription,
245
+ servers: ServerDescription[]
246
+ ): ServerDescription[] {
247
+ const low = servers.reduce(
248
+ (min: number, server: ServerDescription) => Math.min(server.roundTripTime, min),
249
+ Infinity
250
+ );
251
+
252
+ const high = low + topologyDescription.localThresholdMS;
253
+ return servers.filter(server => server.roundTripTime <= high && server.roundTripTime >= low);
254
+ }
255
+
256
+ // filters
257
+ function primaryFilter(server: ServerDescription): boolean {
258
+ return server.type === ServerType.RSPrimary;
259
+ }
260
+
261
+ function secondaryFilter(server: ServerDescription): boolean {
262
+ return server.type === ServerType.RSSecondary;
263
+ }
264
+
265
+ function nearestFilter(server: ServerDescription): boolean {
266
+ return server.type === ServerType.RSSecondary || server.type === ServerType.RSPrimary;
267
+ }
268
+
269
+ function knownFilter(server: ServerDescription): boolean {
270
+ return server.type !== ServerType.Unknown;
271
+ }
272
+
273
+ function loadBalancerFilter(server: ServerDescription): boolean {
274
+ return server.type === ServerType.LoadBalancer;
275
+ }
276
+
277
+ function isDeprioritizedFactory(
278
+ deprioritized: DeprioritizedServers
279
+ ): (server: ServerDescription) => boolean {
280
+ return server =>
281
+ // if any deprioritized servers equal the server, here we are.
282
+ !deprioritized.has(server);
283
+ }
284
+
285
+ function secondarySelector(
286
+ readPreference: ReadPreference,
287
+ topologyDescription: TopologyDescription,
288
+ servers: ServerDescription[],
289
+ deprioritized: DeprioritizedServers
290
+ ) {
291
+ const mode = readPreference.mode;
292
+ switch (mode) {
293
+ case 'primary':
294
+ // Note: no need to filter for deprioritized servers. A replica set has only one primary; that means that
295
+ // we are in one of two scenarios:
296
+ // 1. deprioritized servers is empty - return the primary.
297
+ // 2. deprioritized servers contains the primary - return the primary.
298
+ return servers.filter(primaryFilter);
299
+ case 'primaryPreferred': {
300
+ const primary = servers.filter(primaryFilter);
301
+
302
+ // If there is a primary and it is not deprioritized, use the primary. Otherwise,
303
+ // check for secondaries.
304
+ const eligiblePrimary = primary.filter(isDeprioritizedFactory(deprioritized));
305
+ if (eligiblePrimary.length) {
306
+ return eligiblePrimary;
307
+ }
308
+
309
+ // If we make it here, we either have:
310
+ // 1. a deprioritized primary
311
+ // 2. no eligible primary
312
+ // secondaries take precedence of deprioritized primaries.
313
+ const secondaries = tagSetReducer(
314
+ readPreference,
315
+ maxStalenessReducer(readPreference, topologyDescription, servers.filter(secondaryFilter))
316
+ );
317
+
318
+ const eligibleSecondaries = secondaries.filter(isDeprioritizedFactory(deprioritized));
319
+ if (eligibleSecondaries.length) {
320
+ return latencyWindowReducer(topologyDescription, eligibleSecondaries);
321
+ }
322
+
323
+ // if we make it here, we have no primaries or secondaries that not deprioritized.
324
+ // prefer the primary (which may not exist, if the topology has no primary).
325
+ // otherwise, return the secondaries (which also may not exist, but there is nothing else to check here).
326
+ return primary.length ? primary : latencyWindowReducer(topologyDescription, secondaries);
327
+ }
328
+ case 'nearest': {
329
+ const eligible = filterDeprioritized(
330
+ tagSetReducer(
331
+ readPreference,
332
+ maxStalenessReducer(readPreference, topologyDescription, servers.filter(nearestFilter))
333
+ ),
334
+ deprioritized
335
+ );
336
+ return latencyWindowReducer(topologyDescription, eligible);
337
+ }
338
+ case 'secondary':
339
+ case 'secondaryPreferred': {
340
+ const secondaries = tagSetReducer(
341
+ readPreference,
342
+ maxStalenessReducer(readPreference, topologyDescription, servers.filter(secondaryFilter))
343
+ );
344
+ const eligibleSecondaries = secondaries.filter(isDeprioritizedFactory(deprioritized));
345
+
346
+ if (eligibleSecondaries.length) {
347
+ return latencyWindowReducer(topologyDescription, eligibleSecondaries);
348
+ }
349
+
350
+ // we have no eligible secondaries, try for a primary if we can.
351
+ if (mode === ReadPreference.SECONDARY_PREFERRED) {
352
+ const primary = servers.filter(primaryFilter);
353
+
354
+ // unlike readPreference=primary, here we do filter for deprioritized servers.
355
+ // if the primary is deprioritized, deprioritized secondaries take precedence.
356
+ const eligiblePrimary = primary.filter(isDeprioritizedFactory(deprioritized));
357
+ if (eligiblePrimary.length) return eligiblePrimary;
358
+
359
+ // we have no eligible primary nor secondaries that have not been deprioritized
360
+ return secondaries.length
361
+ ? latencyWindowReducer(topologyDescription, secondaries)
362
+ : primary;
363
+ }
364
+
365
+ // return all secondaries in the latency window.
366
+ return latencyWindowReducer(topologyDescription, secondaries);
367
+ }
368
+
369
+ default: {
370
+ const _exhaustiveCheck: never = mode;
371
+ throw new MongoRuntimeError(
372
+ `unexpected readPreference=${mode} (should never happen). Please report a bug in the Node driver Jira project.`
373
+ );
374
+ }
375
+ }
376
+ }
377
+
378
+ /**
379
+ * Returns a function which selects servers based on a provided read preference
380
+ *
381
+ * @param readPreference - The read preference to select with
382
+ */
383
+ export function readPreferenceServerSelector(readPreference: ReadPreference): ServerSelector {
384
+ if (!readPreference.isValid()) {
385
+ throw new MongoInvalidArgumentError('Invalid read preference specified');
386
+ }
387
+
388
+ return function readPreferenceServers(
389
+ topologyDescription: TopologyDescription,
390
+ servers: ServerDescription[],
391
+ deprioritized: DeprioritizedServers
392
+ ): ServerDescription[] {
393
+ switch (topologyDescription.type) {
394
+ case 'Single':
395
+ return latencyWindowReducer(topologyDescription, servers.filter(knownFilter));
396
+ case 'ReplicaSetNoPrimary':
397
+ case 'ReplicaSetWithPrimary':
398
+ return secondarySelector(readPreference, topologyDescription, servers, deprioritized);
399
+ case 'Sharded': {
400
+ const selectable = filterDeprioritized(servers, deprioritized);
401
+ return latencyWindowReducer(topologyDescription, selectable.filter(knownFilter));
402
+ }
403
+ case 'Unknown':
404
+ return [];
405
+ case 'LoadBalanced':
406
+ return servers.filter(loadBalancerFilter);
407
+ default: {
408
+ const _exhaustiveCheck: never = topologyDescription.type;
409
+ throw new MongoRuntimeError(
410
+ `unexpected topology type: ${topologyDescription.type} (this should never happen). Please file a bug in the Node driver Jira project.`
411
+ );
412
+ }
413
+ }
414
+ };
415
+ }