mongodb 6.8.2 → 6.9.0-dev.20240917.sha.20396e1b

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 (252) hide show
  1. package/README.md +14 -1
  2. package/lib/beta.d.ts +7940 -0
  3. package/lib/beta.js +21 -0
  4. package/lib/beta.js.map +1 -0
  5. package/lib/bson.js +5 -5
  6. package/lib/bson.js.map +1 -1
  7. package/lib/bulk/common.js +16 -21
  8. package/lib/bulk/common.js.map +1 -1
  9. package/lib/bulk/ordered.js.map +1 -1
  10. package/lib/bulk/unordered.js.map +1 -1
  11. package/lib/change_stream.js +10 -8
  12. package/lib/change_stream.js.map +1 -1
  13. package/lib/client-side-encryption/auto_encrypter.js +14 -3
  14. package/lib/client-side-encryption/auto_encrypter.js.map +1 -1
  15. package/lib/client-side-encryption/client_encryption.js +25 -7
  16. package/lib/client-side-encryption/client_encryption.js.map +1 -1
  17. package/lib/client-side-encryption/crypto_callbacks.js +6 -6
  18. package/lib/client-side-encryption/crypto_callbacks.js.map +1 -1
  19. package/lib/client-side-encryption/mongocryptd_manager.js +9 -5
  20. package/lib/client-side-encryption/mongocryptd_manager.js.map +1 -1
  21. package/lib/client-side-encryption/providers/aws.js +1 -2
  22. package/lib/client-side-encryption/providers/aws.js.map +1 -1
  23. package/lib/client-side-encryption/providers/azure.js +5 -5
  24. package/lib/client-side-encryption/providers/azure.js.map +1 -1
  25. package/lib/client-side-encryption/providers/gcp.js +1 -2
  26. package/lib/client-side-encryption/providers/gcp.js.map +1 -1
  27. package/lib/client-side-encryption/providers/index.js +2 -3
  28. package/lib/client-side-encryption/providers/index.js.map +1 -1
  29. package/lib/client-side-encryption/state_machine.js +9 -4
  30. package/lib/client-side-encryption/state_machine.js.map +1 -1
  31. package/lib/cmap/auth/auth_provider.js.map +1 -1
  32. package/lib/cmap/auth/aws_temporary_credentials.js.map +1 -1
  33. package/lib/cmap/auth/gssapi.js +4 -4
  34. package/lib/cmap/auth/gssapi.js.map +1 -1
  35. package/lib/cmap/auth/mongo_credentials.js +2 -7
  36. package/lib/cmap/auth/mongo_credentials.js.map +1 -1
  37. package/lib/cmap/auth/mongodb_aws.js.map +1 -1
  38. package/lib/cmap/auth/mongodb_oidc/automated_callback_workflow.js.map +1 -1
  39. package/lib/cmap/auth/mongodb_oidc/azure_machine_workflow.js.map +1 -1
  40. package/lib/cmap/auth/mongodb_oidc/callback_workflow.js +0 -2
  41. package/lib/cmap/auth/mongodb_oidc/callback_workflow.js.map +1 -1
  42. package/lib/cmap/auth/mongodb_oidc/command_builders.js +2 -3
  43. package/lib/cmap/auth/mongodb_oidc/command_builders.js.map +1 -1
  44. package/lib/cmap/auth/mongodb_oidc/gcp_machine_workflow.js.map +1 -1
  45. package/lib/cmap/auth/mongodb_oidc/human_callback_workflow.js.map +1 -1
  46. package/lib/cmap/auth/mongodb_oidc/machine_workflow.js +0 -2
  47. package/lib/cmap/auth/mongodb_oidc/machine_workflow.js.map +1 -1
  48. package/lib/cmap/auth/mongodb_oidc/token_cache.js.map +1 -1
  49. package/lib/cmap/auth/mongodb_oidc/token_machine_workflow.js.map +1 -1
  50. package/lib/cmap/auth/mongodb_oidc.js.map +1 -1
  51. package/lib/cmap/auth/plain.js.map +1 -1
  52. package/lib/cmap/auth/scram.js.map +1 -1
  53. package/lib/cmap/auth/x509.js.map +1 -1
  54. package/lib/cmap/command_monitoring_events.js.map +1 -1
  55. package/lib/cmap/commands.js +62 -5
  56. package/lib/cmap/commands.js.map +1 -1
  57. package/lib/cmap/connect.js +10 -7
  58. package/lib/cmap/connect.js.map +1 -1
  59. package/lib/cmap/connection.js +3 -5
  60. package/lib/cmap/connection.js.map +1 -1
  61. package/lib/cmap/connection_pool.js +11 -9
  62. package/lib/cmap/connection_pool.js.map +1 -1
  63. package/lib/cmap/connection_pool_events.js +7 -3
  64. package/lib/cmap/connection_pool_events.js.map +1 -1
  65. package/lib/cmap/handshake/client_metadata.js +5 -5
  66. package/lib/cmap/handshake/client_metadata.js.map +1 -1
  67. package/lib/cmap/metrics.js +1 -1
  68. package/lib/cmap/metrics.js.map +1 -1
  69. package/lib/cmap/stream_description.js.map +1 -1
  70. package/lib/cmap/wire_protocol/compression.js +5 -5
  71. package/lib/cmap/wire_protocol/compression.js.map +1 -1
  72. package/lib/cmap/wire_protocol/constants.js +4 -4
  73. package/lib/cmap/wire_protocol/on_data.js +1 -2
  74. package/lib/cmap/wire_protocol/on_data.js.map +1 -1
  75. package/lib/cmap/wire_protocol/on_demand/document.js.map +1 -1
  76. package/lib/cmap/wire_protocol/responses.js +4 -4
  77. package/lib/cmap/wire_protocol/responses.js.map +1 -1
  78. package/lib/cmap/wire_protocol/shared.js +2 -3
  79. package/lib/cmap/wire_protocol/shared.js.map +1 -1
  80. package/lib/collection.js.map +1 -1
  81. package/lib/connection_string.js +12 -6
  82. package/lib/connection_string.js.map +1 -1
  83. package/lib/constants.js +1 -0
  84. package/lib/constants.js.map +1 -1
  85. package/lib/cursor/abstract_cursor.js +21 -6
  86. package/lib/cursor/abstract_cursor.js.map +1 -1
  87. package/lib/cursor/aggregation_cursor.js +1 -1
  88. package/lib/cursor/aggregation_cursor.js.map +1 -1
  89. package/lib/cursor/change_stream_cursor.js.map +1 -1
  90. package/lib/cursor/find_cursor.js +3 -3
  91. package/lib/cursor/find_cursor.js.map +1 -1
  92. package/lib/db.js +2 -2
  93. package/lib/db.js.map +1 -1
  94. package/lib/deps.js +16 -8
  95. package/lib/deps.js.map +1 -1
  96. package/lib/encrypter.js.map +1 -1
  97. package/lib/error.js +19 -14
  98. package/lib/error.js.map +1 -1
  99. package/lib/explain.js +6 -6
  100. package/lib/explain.js.map +1 -1
  101. package/lib/gridfs/download.js +1 -4
  102. package/lib/gridfs/download.js.map +1 -1
  103. package/lib/gridfs/index.js +1 -1
  104. package/lib/gridfs/index.js.map +1 -1
  105. package/lib/gridfs/upload.js +0 -4
  106. package/lib/gridfs/upload.js.map +1 -1
  107. package/lib/index.js +4 -2
  108. package/lib/index.js.map +1 -1
  109. package/lib/mongo_client.js +15 -1
  110. package/lib/mongo_client.js.map +1 -1
  111. package/lib/mongo_client_auth_providers.js +6 -2
  112. package/lib/mongo_client_auth_providers.js.map +1 -1
  113. package/lib/mongo_logger.js +8 -8
  114. package/lib/mongo_logger.js.map +1 -1
  115. package/lib/mongo_types.js +1 -0
  116. package/lib/mongo_types.js.map +1 -1
  117. package/lib/operations/aggregate.js +1 -0
  118. package/lib/operations/aggregate.js.map +1 -1
  119. package/lib/operations/bulk_write.js.map +1 -1
  120. package/lib/operations/client_bulk_write/command_builder.js +198 -0
  121. package/lib/operations/client_bulk_write/command_builder.js.map +1 -0
  122. package/lib/operations/client_bulk_write/common.js +3 -0
  123. package/lib/operations/client_bulk_write/common.js.map +1 -0
  124. package/lib/operations/collections.js.map +1 -1
  125. package/lib/operations/command.js +1 -1
  126. package/lib/operations/command.js.map +1 -1
  127. package/lib/operations/count.js.map +1 -1
  128. package/lib/operations/create_collection.js.map +1 -1
  129. package/lib/operations/delete.js +2 -2
  130. package/lib/operations/delete.js.map +1 -1
  131. package/lib/operations/distinct.js.map +1 -1
  132. package/lib/operations/drop.js.map +1 -1
  133. package/lib/operations/estimated_document_count.js.map +1 -1
  134. package/lib/operations/execute_operation.js +111 -109
  135. package/lib/operations/execute_operation.js.map +1 -1
  136. package/lib/operations/find.js.map +1 -1
  137. package/lib/operations/find_and_modify.js +2 -8
  138. package/lib/operations/find_and_modify.js.map +1 -1
  139. package/lib/operations/get_more.js.map +1 -1
  140. package/lib/operations/indexes.js.map +1 -1
  141. package/lib/operations/insert.js.map +1 -1
  142. package/lib/operations/is_capped.js.map +1 -1
  143. package/lib/operations/kill_cursors.js.map +1 -1
  144. package/lib/operations/list_collections.js.map +1 -1
  145. package/lib/operations/list_databases.js.map +1 -1
  146. package/lib/operations/operation.js +5 -5
  147. package/lib/operations/operation.js.map +1 -1
  148. package/lib/operations/options_operation.js.map +1 -1
  149. package/lib/operations/profiling_level.js.map +1 -1
  150. package/lib/operations/search_indexes/drop.js.map +1 -1
  151. package/lib/operations/set_profiling_level.js.map +1 -1
  152. package/lib/operations/stats.js.map +1 -1
  153. package/lib/operations/update.js +2 -2
  154. package/lib/operations/update.js.map +1 -1
  155. package/lib/operations/validate_collection.js.map +1 -1
  156. package/lib/read_concern.js.map +1 -1
  157. package/lib/read_preference.js +1 -1
  158. package/lib/read_preference.js.map +1 -1
  159. package/lib/resource_management.js +58 -0
  160. package/lib/resource_management.js.map +1 -0
  161. package/lib/sdam/common.js +3 -3
  162. package/lib/sdam/common.js.map +1 -1
  163. package/lib/sdam/monitor.js +1 -5
  164. package/lib/sdam/monitor.js.map +1 -1
  165. package/lib/sdam/server.js +2 -2
  166. package/lib/sdam/server.js.map +1 -1
  167. package/lib/sdam/server_description.js +3 -3
  168. package/lib/sdam/server_description.js.map +1 -1
  169. package/lib/sdam/server_selection.js +5 -5
  170. package/lib/sdam/server_selection.js.map +1 -1
  171. package/lib/sdam/srv_polling.js +2 -3
  172. package/lib/sdam/srv_polling.js.map +1 -1
  173. package/lib/sdam/topology.js +1 -1
  174. package/lib/sdam/topology.js.map +1 -1
  175. package/lib/sdam/topology_description.js.map +1 -1
  176. package/lib/sessions.js +221 -218
  177. package/lib/sessions.js.map +1 -1
  178. package/lib/sort.js +2 -3
  179. package/lib/sort.js.map +1 -1
  180. package/lib/timeout.js +0 -1
  181. package/lib/timeout.js.map +1 -1
  182. package/lib/transactions.js +2 -2
  183. package/lib/transactions.js.map +1 -1
  184. package/lib/utils.js +54 -54
  185. package/lib/utils.js.map +1 -1
  186. package/lib/write_concern.js +2 -2
  187. package/lib/write_concern.js.map +1 -1
  188. package/mongodb.d.ts +191 -148
  189. package/package.json +27 -28
  190. package/src/beta.ts +22 -0
  191. package/src/bson.ts +1 -2
  192. package/src/bulk/common.ts +18 -18
  193. package/src/change_stream.ts +33 -15
  194. package/src/client-side-encryption/auto_encrypter.ts +18 -82
  195. package/src/client-side-encryption/client_encryption.ts +51 -54
  196. package/src/client-side-encryption/mongocryptd_manager.ts +10 -6
  197. package/src/client-side-encryption/state_machine.ts +28 -6
  198. package/src/cmap/auth/gssapi.ts +1 -1
  199. package/src/cmap/auth/mongo_credentials.ts +2 -8
  200. package/src/cmap/auth/mongodb_aws.ts +2 -2
  201. package/src/cmap/auth/mongodb_oidc/callback_workflow.ts +2 -2
  202. package/src/cmap/auth/mongodb_oidc/machine_workflow.ts +2 -2
  203. package/src/cmap/commands.ts +70 -5
  204. package/src/cmap/connect.ts +4 -1
  205. package/src/cmap/connection.ts +2 -2
  206. package/src/cmap/connection_pool.ts +17 -9
  207. package/src/cmap/connection_pool_events.ts +34 -2
  208. package/src/cmap/handshake/client_metadata.ts +1 -1
  209. package/src/cmap/wire_protocol/constants.ts +4 -4
  210. package/src/cmap/wire_protocol/shared.ts +1 -2
  211. package/src/collection.ts +16 -15
  212. package/src/connection_string.ts +10 -3
  213. package/src/constants.ts +1 -0
  214. package/src/cursor/abstract_cursor.ts +38 -13
  215. package/src/cursor/aggregation_cursor.ts +8 -6
  216. package/src/cursor/find_cursor.ts +2 -2
  217. package/src/db.ts +1 -1
  218. package/src/deps.ts +8 -1
  219. package/src/error.ts +33 -14
  220. package/src/explain.ts +47 -11
  221. package/src/gridfs/download.ts +28 -4
  222. package/src/gridfs/upload.ts +1 -6
  223. package/src/index.ts +11 -2
  224. package/src/mongo_client.ts +29 -5
  225. package/src/mongo_client_auth_providers.ts +8 -2
  226. package/src/mongo_logger.ts +5 -3
  227. package/src/mongo_types.ts +69 -68
  228. package/src/operations/aggregate.ts +2 -1
  229. package/src/operations/bulk_write.ts +2 -2
  230. package/src/operations/client_bulk_write/command_builder.ts +283 -0
  231. package/src/operations/client_bulk_write/common.ts +146 -0
  232. package/src/operations/command.ts +1 -1
  233. package/src/operations/execute_operation.ts +137 -131
  234. package/src/operations/find_and_modify.ts +2 -7
  235. package/src/operations/insert.ts +3 -4
  236. package/src/operations/operation.ts +7 -10
  237. package/src/operations/search_indexes/drop.ts +4 -1
  238. package/src/resource_management.ts +74 -0
  239. package/src/sdam/monitor.ts +3 -5
  240. package/src/sdam/server.ts +1 -1
  241. package/src/sdam/server_description.ts +5 -6
  242. package/src/sdam/srv_polling.ts +1 -2
  243. package/src/sessions.ts +291 -277
  244. package/src/sort.ts +1 -1
  245. package/src/timeout.ts +0 -1
  246. package/src/transactions.ts +1 -2
  247. package/src/utils.ts +25 -9
  248. package/src/write_concern.ts +2 -2
  249. package/tsconfig.json +2 -1
  250. package/lib/cmap/auth/mongocr.js +0 -35
  251. package/lib/cmap/auth/mongocr.js.map +0 -1
  252. package/src/cmap/auth/mongocr.ts +0 -38
@@ -5,14 +5,22 @@ import type {
5
5
  MongoCryptOptions
6
6
  } from 'mongodb-client-encryption';
7
7
 
8
- import { type Binary, deserialize, type Document, type Long, serialize, type UUID } from '../bson';
8
+ import {
9
+ type Binary,
10
+ deserialize,
11
+ type Document,
12
+ type Int32,
13
+ type Long,
14
+ serialize,
15
+ type UUID
16
+ } from '../bson';
9
17
  import { type AnyBulkWriteOperation, type BulkWriteResult } from '../bulk/common';
10
18
  import { type ProxyOptions } from '../cmap/connection';
11
19
  import { type Collection } from '../collection';
12
20
  import { type FindCursor } from '../cursor/find_cursor';
13
21
  import { type Db } from '../db';
14
22
  import { getMongoDBClientEncryption } from '../deps';
15
- import { type MongoClient } from '../mongo_client';
23
+ import { type MongoClient, type MongoClientOptions } from '../mongo_client';
16
24
  import { type Filter, type WithId } from '../mongo_types';
17
25
  import { type CreateCollectionOptions } from '../operations/create_collection';
18
26
  import { type DeleteResult } from '../operations/delete';
@@ -28,7 +36,11 @@ import {
28
36
  type KMSProviders,
29
37
  refreshKMSCredentials
30
38
  } from './providers/index';
31
- import { type CSFLEKMSTlsOptions, StateMachine } from './state_machine';
39
+ import {
40
+ type ClientEncryptionSocketOptions,
41
+ type CSFLEKMSTlsOptions,
42
+ StateMachine
43
+ } from './state_machine';
32
44
 
33
45
  /**
34
46
  * @public
@@ -199,7 +211,8 @@ export class ClientEncryption {
199
211
 
200
212
  const stateMachine = new StateMachine({
201
213
  proxyOptions: this._proxyOptions,
202
- tlsOptions: this._tlsOptions
214
+ tlsOptions: this._tlsOptions,
215
+ socketOptions: autoSelectSocketOptions(this._client.options)
203
216
  });
204
217
 
205
218
  const dataKey = deserialize(await stateMachine.execute(this, context)) as DataKey;
@@ -256,7 +269,8 @@ export class ClientEncryption {
256
269
  const context = this._mongoCrypt.makeRewrapManyDataKeyContext(filterBson, keyEncryptionKeyBson);
257
270
  const stateMachine = new StateMachine({
258
271
  proxyOptions: this._proxyOptions,
259
- tlsOptions: this._tlsOptions
272
+ tlsOptions: this._tlsOptions,
273
+ socketOptions: autoSelectSocketOptions(this._client.options)
260
274
  });
261
275
 
262
276
  const { v: dataKeys } = deserialize(await stateMachine.execute(this, context));
@@ -595,9 +609,7 @@ export class ClientEncryption {
595
609
  /**
596
610
  * Encrypts a Match Expression or Aggregate Expression to query a range index.
597
611
  *
598
- * Only supported when queryType is "rangePreview" and algorithm is "RangePreview".
599
- *
600
- * @experimental The Range algorithm is experimental only. It is not intended for production use. It is subject to breaking changes.
612
+ * Only supported when queryType is "range" and algorithm is "Range".
601
613
  *
602
614
  * @param expression - a BSON document of one of the following forms:
603
615
  * 1. A Match Expression of this form:
@@ -637,7 +649,8 @@ export class ClientEncryption {
637
649
 
638
650
  const stateMachine = new StateMachine({
639
651
  proxyOptions: this._proxyOptions,
640
- tlsOptions: this._tlsOptions
652
+ tlsOptions: this._tlsOptions,
653
+ socketOptions: autoSelectSocketOptions(this._client.options)
641
654
  });
642
655
 
643
656
  const { v } = deserialize(await stateMachine.execute(this, context));
@@ -715,7 +728,8 @@ export class ClientEncryption {
715
728
  const valueBuffer = serialize({ v: value });
716
729
  const stateMachine = new StateMachine({
717
730
  proxyOptions: this._proxyOptions,
718
- tlsOptions: this._tlsOptions
731
+ tlsOptions: this._tlsOptions,
732
+ socketOptions: autoSelectSocketOptions(this._client.options)
719
733
  });
720
734
  const context = this._mongoCrypt.makeExplicitEncryptionContext(valueBuffer, contextOptions);
721
735
 
@@ -737,7 +751,7 @@ export interface ClientEncryptionEncryptOptions {
737
751
  | 'AEAD_AES_256_CBC_HMAC_SHA_512-Random'
738
752
  | 'Indexed'
739
753
  | 'Unindexed'
740
- | 'RangePreview';
754
+ | 'Range';
741
755
 
742
756
  /**
743
757
  * The id of the Binary dataKey to use for encryption
@@ -753,13 +767,11 @@ export interface ClientEncryptionEncryptOptions {
753
767
  contentionFactor?: bigint | number;
754
768
 
755
769
  /**
756
- * The query type supported. Only the queryType `equality` is stable.
757
- *
758
- * @experimental Public Technical Preview: The queryType `rangePreview` is experimental.
770
+ * The query type.
759
771
  */
760
- queryType?: 'equality' | 'rangePreview';
772
+ queryType?: 'equality' | 'range';
761
773
 
762
- /** @experimental Public Technical Preview: The index options for a Queryable Encryption field supporting "rangePreview" queries.*/
774
+ /** The index options for a Queryable Encryption field supporting "range" queries.*/
763
775
  rangeOptions?: RangeOptions;
764
776
  }
765
777
 
@@ -947,52 +959,37 @@ export interface ClientEncryptionRewrapManyDataKeyResult {
947
959
 
948
960
  /**
949
961
  * @public
950
- * RangeOptions specifies index options for a Queryable Encryption field supporting "rangePreview" queries.
951
- * min, max, sparsity, and range must match the values set in the encryptedFields of the destination collection.
962
+ * RangeOptions specifies index options for a Queryable Encryption field supporting "range" queries.
963
+ * min, max, sparsity, trimFactor and range must match the values set in the encryptedFields of the destination collection.
952
964
  * For double and decimal128, min/max/precision must all be set, or all be unset.
953
965
  */
954
966
  export interface RangeOptions {
967
+ /** min is the minimum value for the encrypted index. Required if precision is set. */
955
968
  min?: any;
969
+ /** max is the minimum value for the encrypted index. Required if precision is set. */
956
970
  max?: any;
957
- sparsity: Long;
971
+ /** sparsity may be used to tune performance. must be non-negative. When omitted, a default value is used. */
972
+ sparsity?: Long | bigint;
973
+ /** trimFactor may be used to tune performance. must be non-negative. When omitted, a default value is used. */
974
+ trimFactor?: Int32 | number;
975
+ /* precision determines the number of significant digits after the decimal point. May only be set for double or decimal128. */
958
976
  precision?: number;
959
977
  }
960
978
 
961
979
  /**
962
- * @public
963
- * Options to provide when encrypting data.
980
+ * Get the socket options from the client.
981
+ * @param baseOptions - The mongo client options.
982
+ * @returns ClientEncryptionSocketOptions
964
983
  */
965
- export interface ClientEncryptionEncryptOptions {
966
- /**
967
- * The algorithm to use for encryption.
968
- */
969
- algorithm:
970
- | 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'
971
- | 'AEAD_AES_256_CBC_HMAC_SHA_512-Random'
972
- | 'Indexed'
973
- | 'Unindexed'
974
- | 'RangePreview';
975
-
976
- /**
977
- * The id of the Binary dataKey to use for encryption
978
- */
979
- keyId?: Binary;
980
-
981
- /**
982
- * A unique string name corresponding to an already existing dataKey.
983
- */
984
- keyAltName?: string;
985
-
986
- /** The contention factor. */
987
- contentionFactor?: bigint | number;
988
-
989
- /**
990
- * The query type supported. Only the queryType `equality` is stable.
991
- *
992
- * @experimental Public Technical Preview: The queryType `rangePreview` is experimental.
993
- */
994
- queryType?: 'equality' | 'rangePreview';
995
-
996
- /** @experimental Public Technical Preview: The index options for a Queryable Encryption field supporting "rangePreview" queries.*/
997
- rangeOptions?: RangeOptions;
984
+ export function autoSelectSocketOptions(
985
+ baseOptions: MongoClientOptions
986
+ ): ClientEncryptionSocketOptions {
987
+ const options: ClientEncryptionSocketOptions = { autoSelectFamily: true };
988
+ if ('autoSelectFamily' in baseOptions) {
989
+ options.autoSelectFamily = baseOptions.autoSelectFamily;
990
+ }
991
+ if ('autoSelectFamilyAttemptTimeout' in baseOptions) {
992
+ options.autoSelectFamilyAttemptTimeout = baseOptions.autoSelectFamilyAttemptTimeout;
993
+ }
994
+ return options;
998
995
  }
@@ -12,8 +12,8 @@ export class MongocryptdManager {
12
12
 
13
13
  uri: string;
14
14
  bypassSpawn: boolean;
15
- spawnPath: string;
16
- spawnArgs: Array<string>;
15
+ spawnPath = '';
16
+ spawnArgs: Array<string> = [];
17
17
  _child?: ChildProcess;
18
18
 
19
19
  constructor(extraOptions: AutoEncryptionExtraOptions = {}) {
@@ -24,9 +24,13 @@ export class MongocryptdManager {
24
24
 
25
25
  this.bypassSpawn = !!extraOptions.mongocryptdBypassSpawn;
26
26
 
27
- this.spawnPath = extraOptions.mongocryptdSpawnPath || '';
28
- this.spawnArgs = [];
29
- if (Array.isArray(extraOptions.mongocryptdSpawnArgs)) {
27
+ if (Object.hasOwn(extraOptions, 'mongocryptdSpawnPath') && extraOptions.mongocryptdSpawnPath) {
28
+ this.spawnPath = extraOptions.mongocryptdSpawnPath;
29
+ }
30
+ if (
31
+ Object.hasOwn(extraOptions, 'mongocryptdSpawnArgs') &&
32
+ Array.isArray(extraOptions.mongocryptdSpawnArgs)
33
+ ) {
30
34
  this.spawnArgs = this.spawnArgs.concat(extraOptions.mongocryptdSpawnArgs);
31
35
  }
32
36
  if (
@@ -45,7 +49,7 @@ export class MongocryptdManager {
45
49
  async spawn(): Promise<void> {
46
50
  const cmdName = this.spawnPath || 'mongocryptd';
47
51
 
48
- // eslint-disable-next-line @typescript-eslint/no-var-requires
52
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
49
53
  const { spawn } = require('child_process') as typeof import('child_process');
50
54
 
51
55
  // Spawned with stdio: ignore and detached: true
@@ -14,7 +14,7 @@ import { type ProxyOptions } from '../cmap/connection';
14
14
  import { getSocks, type SocksLib } from '../deps';
15
15
  import { type MongoClient, type MongoClientOptions } from '../mongo_client';
16
16
  import { BufferPool, MongoDBCollectionNamespace, promiseWithResolvers } from '../utils';
17
- import { type DataKey } from './client_encryption';
17
+ import { autoSelectSocketOptions, type DataKey } from './client_encryption';
18
18
  import { MongoCryptError } from './errors';
19
19
  import { type MongocryptdManager } from './mongocryptd_manager';
20
20
  import { type KMSProviders } from './providers';
@@ -114,6 +114,16 @@ export type CSFLEKMSTlsOptions = {
114
114
  [key: string]: ClientEncryptionTlsOptions | undefined;
115
115
  };
116
116
 
117
+ /**
118
+ * @public
119
+ *
120
+ * Socket options to use for KMS requests.
121
+ */
122
+ export type ClientEncryptionSocketOptions = Pick<
123
+ MongoClientOptions,
124
+ 'autoSelectFamily' | 'autoSelectFamilyAttemptTimeout'
125
+ >;
126
+
117
127
  /**
118
128
  * This is kind of a hack. For `rewrapManyDataKey`, we have tests that
119
129
  * guarantee that when there are no matching keys, `rewrapManyDataKey` returns
@@ -153,6 +163,9 @@ export type StateMachineOptions = {
153
163
 
154
164
  /** TLS options for KMS requests, if set. */
155
165
  tlsOptions: CSFLEKMSTlsOptions;
166
+
167
+ /** Socket specific options we support. */
168
+ socketOptions: ClientEncryptionSocketOptions;
156
169
  } & Pick<BSONSerializeOptions, 'promoteLongs' | 'promoteValues'>;
157
170
 
158
171
  /**
@@ -289,10 +302,17 @@ export class StateMachine {
289
302
  async kmsRequest(request: MongoCryptKMSRequest): Promise<void> {
290
303
  const parsedUrl = request.endpoint.split(':');
291
304
  const port = parsedUrl[1] != null ? Number.parseInt(parsedUrl[1], 10) : HTTPS_PORT;
292
- const options: tls.ConnectionOptions & { host: string; port: number } = {
305
+ const socketOptions = autoSelectSocketOptions(this.options.socketOptions || {});
306
+ const options: tls.ConnectionOptions & {
307
+ host: string;
308
+ port: number;
309
+ autoSelectFamily?: boolean;
310
+ autoSelectFamilyAttemptTimeout?: number;
311
+ } = {
293
312
  host: parsedUrl[0],
294
313
  servername: parsedUrl[0],
295
- port
314
+ port,
315
+ ...socketOptions
296
316
  };
297
317
  const message = request.message;
298
318
  const buffer = new BufferPool();
@@ -351,10 +371,12 @@ export class StateMachine {
351
371
 
352
372
  try {
353
373
  if (this.options.proxyOptions && this.options.proxyOptions.proxyHost) {
354
- netSocket.connect({
374
+ const netSocketOptions = {
355
375
  host: this.options.proxyOptions.proxyHost,
356
- port: this.options.proxyOptions.proxyPort || 1080
357
- });
376
+ port: this.options.proxyOptions.proxyPort || 1080,
377
+ ...socketOptions
378
+ };
379
+ netSocket.connect(netSocketOptions);
358
380
  await willConnect;
359
381
 
360
382
  try {
@@ -168,7 +168,7 @@ export async function performGSSAPICanonicalizeHostName(
168
168
  const results = await dns.promises.resolvePtr(address);
169
169
  // If the ptr did not error but had no results, return the host.
170
170
  return results.length > 0 ? results[0] : host;
171
- } catch (error) {
171
+ } catch {
172
172
  // This can error as ptr records may not exist for all ips. In this case
173
173
  // fallback to a cname lookup as dns.lookup() does not return the
174
174
  // cname.
@@ -20,15 +20,10 @@ function getDefaultAuthMechanism(hello: Document | null): AuthMechanism {
20
20
  ? AuthMechanism.MONGODB_SCRAM_SHA256
21
21
  : AuthMechanism.MONGODB_SCRAM_SHA1;
22
22
  }
23
-
24
- // Fallback to legacy selection method. If wire version >= 3, use scram-sha-1
25
- if (hello.maxWireVersion >= 3) {
26
- return AuthMechanism.MONGODB_SCRAM_SHA1;
27
- }
28
23
  }
29
24
 
30
- // Default for wireprotocol < 3
31
- return AuthMechanism.MONGODB_CR;
25
+ // Default auth mechanism for 4.0 and higher.
26
+ return AuthMechanism.MONGODB_SCRAM_SHA256;
32
27
  }
33
28
 
34
29
  const ALLOWED_ENVIRONMENT_NAMES: AuthMechanismProperties['ENVIRONMENT'][] = [
@@ -173,7 +168,6 @@ export class MongoCredentials {
173
168
  validate(): void {
174
169
  if (
175
170
  (this.mechanism === AuthMechanism.MONGODB_GSSAPI ||
176
- this.mechanism === AuthMechanism.MONGODB_CR ||
177
171
  this.mechanism === AuthMechanism.MONGODB_PLAIN ||
178
172
  this.mechanism === AuthMechanism.MONGODB_SCRAM_SHA1 ||
179
173
  this.mechanism === AuthMechanism.MONGODB_SCRAM_SHA256) &&
@@ -78,8 +78,8 @@ export class MongoDBAWS extends AuthProvider {
78
78
  accessKeyId && secretAccessKey && sessionToken
79
79
  ? { accessKeyId, secretAccessKey, sessionToken }
80
80
  : accessKeyId && secretAccessKey
81
- ? { accessKeyId, secretAccessKey }
82
- : undefined;
81
+ ? { accessKeyId, secretAccessKey }
82
+ : undefined;
83
83
 
84
84
  const db = credentials.source;
85
85
  const nonce = await randomBytes(32);
@@ -160,9 +160,9 @@ export abstract class CallbackWorkflow implements Workflow {
160
160
  // previous lock, only the current callback's value would get returned.
161
161
  await lock;
162
162
  lock = lock
163
- // eslint-disable-next-line github/no-then
163
+
164
164
  .catch(() => null)
165
- // eslint-disable-next-line github/no-then
165
+
166
166
  .then(async () => {
167
167
  const difference = Date.now() - this.lastExecutionTime;
168
168
  if (difference <= THROTTLE_MS) {
@@ -115,9 +115,9 @@ export abstract class MachineWorkflow implements Workflow {
115
115
  // previous lock, only the current callback's value would get returned.
116
116
  await lock;
117
117
  lock = lock
118
- // eslint-disable-next-line github/no-then
118
+
119
119
  .catch(() => null)
120
- // eslint-disable-next-line github/no-then
120
+
121
121
  .then(async () => {
122
122
  const difference = Date.now() - this.lastExecutionTime;
123
123
  if (difference <= THROTTLE_MS) {
@@ -30,6 +30,8 @@ const QUERY_FAILURE = 2;
30
30
  const SHARD_CONFIG_STALE = 4;
31
31
  const AWAIT_CAPABLE = 8;
32
32
 
33
+ const encodeUTF8Into = BSON.BSON.onDemand.ByteUtils.encodeUTF8Into;
34
+
33
35
  /** @internal */
34
36
  export type WriteProtocolMessageType = OpQueryRequest | OpMsgRequest;
35
37
 
@@ -73,7 +75,11 @@ export class OpQueryRequest {
73
75
  exhaust: boolean;
74
76
  partial: boolean;
75
77
 
76
- constructor(public databaseName: string, public query: Document, options: OpQueryOptions) {
78
+ constructor(
79
+ public databaseName: string,
80
+ public query: Document,
81
+ options: OpQueryOptions
82
+ ) {
77
83
  // Basic options needed to be passed in
78
84
  // TODO(NODE-3483): Replace with MongoCommandError
79
85
  const ns = `${databaseName}.$cmd`;
@@ -411,6 +417,15 @@ export interface OpMsgOptions {
411
417
  readPreference: ReadPreference;
412
418
  }
413
419
 
420
+ /** @internal */
421
+ export class DocumentSequence {
422
+ documents: Document[];
423
+
424
+ constructor(documents: Document[]) {
425
+ this.documents = documents;
426
+ }
427
+ }
428
+
414
429
  /** @internal */
415
430
  export class OpMsgRequest {
416
431
  requestId: number;
@@ -480,7 +495,7 @@ export class OpMsgRequest {
480
495
 
481
496
  let totalLength = header.length;
482
497
  const command = this.command;
483
- totalLength += this.makeDocumentSegment(buffers, command);
498
+ totalLength += this.makeSections(buffers, command);
484
499
 
485
500
  header.writeInt32LE(totalLength, 0); // messageLength
486
501
  header.writeInt32LE(this.requestId, 4); // requestID
@@ -490,15 +505,65 @@ export class OpMsgRequest {
490
505
  return buffers;
491
506
  }
492
507
 
493
- makeDocumentSegment(buffers: Uint8Array[], document: Document): number {
494
- const payloadTypeBuffer = Buffer.alloc(1);
508
+ /**
509
+ * Add the sections to the OP_MSG request's buffers and returns the length.
510
+ */
511
+ makeSections(buffers: Uint8Array[], document: Document): number {
512
+ const sequencesBuffer = this.extractDocumentSequences(document);
513
+ const payloadTypeBuffer = Buffer.allocUnsafe(1);
495
514
  payloadTypeBuffer[0] = 0;
496
515
 
497
516
  const documentBuffer = this.serializeBson(document);
517
+ // First section, type 0
498
518
  buffers.push(payloadTypeBuffer);
499
519
  buffers.push(documentBuffer);
520
+ // Subsequent sections, type 1
521
+ buffers.push(sequencesBuffer);
522
+
523
+ return payloadTypeBuffer.length + documentBuffer.length + sequencesBuffer.length;
524
+ }
500
525
 
501
- return payloadTypeBuffer.length + documentBuffer.length;
526
+ /**
527
+ * Extracts the document sequences from the command document and returns
528
+ * a buffer to be added as multiple sections after the initial type 0
529
+ * section in the message.
530
+ */
531
+ extractDocumentSequences(document: Document): Uint8Array {
532
+ // Pull out any field in the command document that's value is a document sequence.
533
+ const chunks = [];
534
+ for (const [key, value] of Object.entries(document)) {
535
+ if (value instanceof DocumentSequence) {
536
+ // Document sequences starts with type 1 at the first byte.
537
+ const buffer = Buffer.allocUnsafe(1 + 4 + key.length);
538
+ buffer[0] = 1;
539
+ // Third part is the field name at offset 5.
540
+ encodeUTF8Into(buffer, key, 5);
541
+ chunks.push(buffer);
542
+ // Fourth part are the documents' bytes.
543
+ let docsLength = 0;
544
+ for (const doc of value.documents) {
545
+ const docBson = this.serializeBson(doc);
546
+ docsLength += docBson.length;
547
+ chunks.push(docBson);
548
+ }
549
+ // Second part of the sequence is the length at offset 1;
550
+ buffer.writeInt32LE(key.length + docsLength, 1);
551
+ // Why are we removing the field from the command? This is because it needs to be
552
+ // removed in the OP_MSG request first section, and DocumentSequence is not a
553
+ // BSON type and is specific to the MongoDB wire protocol so there's nothing
554
+ // our BSON serializer can do about this. Since DocumentSequence is not exposed
555
+ // in the public API and only used internally, we are never mutating an original
556
+ // command provided by the user, just our own, and it's cheaper to delete from
557
+ // our own command than copying it.
558
+ delete document[key];
559
+ }
560
+ }
561
+ if (chunks.length > 0) {
562
+ return Buffer.concat(chunks);
563
+ }
564
+ // If we have no document sequences we return an empty buffer for nothing to add
565
+ // to the payload.
566
+ return Buffer.alloc(0);
502
567
  }
503
568
 
504
569
  serializeBson(document: Document): Uint8Array {
@@ -164,7 +164,7 @@ export async function performInitialHandshake(
164
164
  } catch (error) {
165
165
  if (error instanceof MongoError) {
166
166
  error.addErrorLabel(MongoErrorLabel.HandshakeError);
167
- if (needsRetryableWriteLabel(error, response.maxWireVersion)) {
167
+ if (needsRetryableWriteLabel(error, response.maxWireVersion, conn.description.type)) {
168
168
  error.addErrorLabel(MongoErrorLabel.RetryableWriteError);
169
169
  }
170
170
  }
@@ -249,6 +249,7 @@ export async function prepareHandshakeDocument(
249
249
 
250
250
  /** @public */
251
251
  export const LEGAL_TLS_SOCKET_OPTIONS = [
252
+ 'allowPartialTrustChain',
252
253
  'ALPNProtocols',
253
254
  'ca',
254
255
  'cert',
@@ -269,6 +270,8 @@ export const LEGAL_TLS_SOCKET_OPTIONS = [
269
270
 
270
271
  /** @public */
271
272
  export const LEGAL_TCP_SOCKET_OPTIONS = [
273
+ 'autoSelectFamily',
274
+ 'autoSelectFamilyAttemptTimeout',
272
275
  'family',
273
276
  'hints',
274
277
  'localAddress',
@@ -333,7 +333,7 @@ export class Connection extends TypedEventEmitter<ConnectionEvents> {
333
333
 
334
334
  this.socket.destroy();
335
335
  this.error = error;
336
- // eslint-disable-next-line github/no-then
336
+
337
337
  this.dataEvents?.throw(error).then(undefined, squashError);
338
338
  this.closed = true;
339
339
  this.emit(Connection.CLOSE);
@@ -603,7 +603,7 @@ export class Connection extends TypedEventEmitter<ConnectionEvents> {
603
603
  }
604
604
  throw new MongoUnexpectedServerResponseError('Server ended moreToCome unexpectedly');
605
605
  };
606
- // eslint-disable-next-line github/no-then
606
+
607
607
  exhaustLoop().then(undefined, replyListener);
608
608
  }
609
609
 
@@ -27,7 +27,7 @@ import {
27
27
  import { CancellationToken, TypedEventEmitter } from '../mongo_types';
28
28
  import type { Server } from '../sdam/server';
29
29
  import { Timeout, TimeoutError } from '../timeout';
30
- import { type Callback, List, makeCounter, promiseWithResolvers } from '../utils';
30
+ import { type Callback, List, makeCounter, now, promiseWithResolvers } from '../utils';
31
31
  import { connect } from './connect';
32
32
  import { Connection, type ConnectionEvents, type ConnectionOptions } from './connection';
33
33
  import {
@@ -104,6 +104,7 @@ export interface WaitQueueMember {
104
104
  reject: (err: AnyError) => void;
105
105
  timeout: Timeout;
106
106
  [kCancelled]?: boolean;
107
+ checkoutTime: number;
107
108
  }
108
109
 
109
110
  /** @internal */
@@ -355,6 +356,7 @@ export class ConnectionPool extends TypedEventEmitter<ConnectionPoolEvents> {
355
356
  * explicitly destroyed by the new owner.
356
357
  */
357
358
  async checkOut(): Promise<Connection> {
359
+ const checkoutTime = now();
358
360
  this.emitAndLog(
359
361
  ConnectionPool.CONNECTION_CHECK_OUT_STARTED,
360
362
  new ConnectionCheckOutStartedEvent(this)
@@ -369,7 +371,8 @@ export class ConnectionPool extends TypedEventEmitter<ConnectionPoolEvents> {
369
371
  const waitQueueMember: WaitQueueMember = {
370
372
  resolve,
371
373
  reject,
372
- timeout
374
+ timeout,
375
+ checkoutTime
373
376
  };
374
377
 
375
378
  this[kWaitQueue].push(waitQueueMember);
@@ -385,7 +388,7 @@ export class ConnectionPool extends TypedEventEmitter<ConnectionPoolEvents> {
385
388
 
386
389
  this.emitAndLog(
387
390
  ConnectionPool.CONNECTION_CHECK_OUT_FAILED,
388
- new ConnectionCheckOutFailedEvent(this, 'timeout')
391
+ new ConnectionCheckOutFailedEvent(this, 'timeout', waitQueueMember.checkoutTime)
389
392
  );
390
393
  const timeoutError = new WaitQueueTimeoutError(
391
394
  this.loadBalanced
@@ -629,12 +632,12 @@ export class ConnectionPool extends TypedEventEmitter<ConnectionPoolEvents> {
629
632
 
630
633
  this[kPending]++;
631
634
  // This is our version of a "virtual" no-I/O connection as the spec requires
635
+ const connectionCreatedTime = now();
632
636
  this.emitAndLog(
633
637
  ConnectionPool.CONNECTION_CREATED,
634
638
  new ConnectionCreatedEvent(this, { id: connectOptions.id })
635
639
  );
636
640
 
637
- // eslint-disable-next-line github/no-then
638
641
  connect(connectOptions).then(
639
642
  connection => {
640
643
  // The pool might have closed since we started trying to create a connection
@@ -670,7 +673,7 @@ export class ConnectionPool extends TypedEventEmitter<ConnectionPoolEvents> {
670
673
  connection.markAvailable();
671
674
  this.emitAndLog(
672
675
  ConnectionPool.CONNECTION_READY,
673
- new ConnectionReadyEvent(this, connection)
676
+ new ConnectionReadyEvent(this, connection, connectionCreatedTime)
674
677
  );
675
678
 
676
679
  this[kPending]--;
@@ -759,7 +762,7 @@ export class ConnectionPool extends TypedEventEmitter<ConnectionPoolEvents> {
759
762
  const error = this.closed ? new PoolClosedError(this) : new PoolClearedError(this);
760
763
  this.emitAndLog(
761
764
  ConnectionPool.CONNECTION_CHECK_OUT_FAILED,
762
- new ConnectionCheckOutFailedEvent(this, reason, error)
765
+ new ConnectionCheckOutFailedEvent(this, reason, waitQueueMember.checkoutTime, error)
763
766
  );
764
767
  waitQueueMember.timeout.clear();
765
768
  this[kWaitQueue].shift();
@@ -780,7 +783,7 @@ export class ConnectionPool extends TypedEventEmitter<ConnectionPoolEvents> {
780
783
  this[kCheckedOut].add(connection);
781
784
  this.emitAndLog(
782
785
  ConnectionPool.CONNECTION_CHECKED_OUT,
783
- new ConnectionCheckedOutEvent(this, connection)
786
+ new ConnectionCheckedOutEvent(this, connection, waitQueueMember.checkoutTime)
784
787
  );
785
788
  waitQueueMember.timeout.clear();
786
789
 
@@ -809,14 +812,19 @@ export class ConnectionPool extends TypedEventEmitter<ConnectionPoolEvents> {
809
812
  this.emitAndLog(
810
813
  ConnectionPool.CONNECTION_CHECK_OUT_FAILED,
811
814
  // TODO(NODE-5192): Remove this cast
812
- new ConnectionCheckOutFailedEvent(this, 'connectionError', err as MongoError)
815
+ new ConnectionCheckOutFailedEvent(
816
+ this,
817
+ 'connectionError',
818
+ waitQueueMember.checkoutTime,
819
+ err as MongoError
820
+ )
813
821
  );
814
822
  waitQueueMember.reject(err);
815
823
  } else if (connection) {
816
824
  this[kCheckedOut].add(connection);
817
825
  this.emitAndLog(
818
826
  ConnectionPool.CONNECTION_CHECKED_OUT,
819
- new ConnectionCheckedOutEvent(this, connection)
827
+ new ConnectionCheckedOutEvent(this, connection, waitQueueMember.checkoutTime)
820
828
  );
821
829
  waitQueueMember.resolve(connection);
822
830
  }