mongodb 6.8.2 → 6.9.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 (242) hide show
  1. package/README.md +14 -1
  2. package/lib/beta.d.ts +7905 -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.map +1 -1
  36. package/lib/cmap/auth/mongocr.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 +2 -2
  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 +1 -1
  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.map +1 -1
  100. package/lib/gridfs/download.js +1 -4
  101. package/lib/gridfs/download.js.map +1 -1
  102. package/lib/gridfs/index.js +1 -1
  103. package/lib/gridfs/index.js.map +1 -1
  104. package/lib/gridfs/upload.js +0 -4
  105. package/lib/gridfs/upload.js.map +1 -1
  106. package/lib/index.js +4 -2
  107. package/lib/index.js.map +1 -1
  108. package/lib/mongo_client.js +15 -1
  109. package/lib/mongo_client.js.map +1 -1
  110. package/lib/mongo_client_auth_providers.js.map +1 -1
  111. package/lib/mongo_logger.js +8 -8
  112. package/lib/mongo_logger.js.map +1 -1
  113. package/lib/mongo_types.js +1 -0
  114. package/lib/mongo_types.js.map +1 -1
  115. package/lib/operations/aggregate.js +1 -0
  116. package/lib/operations/aggregate.js.map +1 -1
  117. package/lib/operations/bulk_write.js.map +1 -1
  118. package/lib/operations/client_bulk_write/command_builder.js +198 -0
  119. package/lib/operations/client_bulk_write/command_builder.js.map +1 -0
  120. package/lib/operations/client_bulk_write/common.js +3 -0
  121. package/lib/operations/client_bulk_write/common.js.map +1 -0
  122. package/lib/operations/collections.js.map +1 -1
  123. package/lib/operations/command.js +1 -1
  124. package/lib/operations/command.js.map +1 -1
  125. package/lib/operations/count.js.map +1 -1
  126. package/lib/operations/create_collection.js.map +1 -1
  127. package/lib/operations/delete.js +2 -2
  128. package/lib/operations/delete.js.map +1 -1
  129. package/lib/operations/distinct.js.map +1 -1
  130. package/lib/operations/drop.js.map +1 -1
  131. package/lib/operations/estimated_document_count.js.map +1 -1
  132. package/lib/operations/execute_operation.js +111 -109
  133. package/lib/operations/execute_operation.js.map +1 -1
  134. package/lib/operations/find.js.map +1 -1
  135. package/lib/operations/find_and_modify.js +2 -8
  136. package/lib/operations/find_and_modify.js.map +1 -1
  137. package/lib/operations/get_more.js.map +1 -1
  138. package/lib/operations/indexes.js.map +1 -1
  139. package/lib/operations/insert.js.map +1 -1
  140. package/lib/operations/is_capped.js.map +1 -1
  141. package/lib/operations/kill_cursors.js.map +1 -1
  142. package/lib/operations/list_collections.js.map +1 -1
  143. package/lib/operations/list_databases.js.map +1 -1
  144. package/lib/operations/operation.js +5 -5
  145. package/lib/operations/operation.js.map +1 -1
  146. package/lib/operations/options_operation.js.map +1 -1
  147. package/lib/operations/profiling_level.js.map +1 -1
  148. package/lib/operations/search_indexes/drop.js.map +1 -1
  149. package/lib/operations/set_profiling_level.js.map +1 -1
  150. package/lib/operations/stats.js.map +1 -1
  151. package/lib/operations/update.js +2 -2
  152. package/lib/operations/update.js.map +1 -1
  153. package/lib/operations/validate_collection.js.map +1 -1
  154. package/lib/read_concern.js.map +1 -1
  155. package/lib/read_preference.js +1 -1
  156. package/lib/read_preference.js.map +1 -1
  157. package/lib/resource_management.js +58 -0
  158. package/lib/resource_management.js.map +1 -0
  159. package/lib/sdam/common.js +3 -3
  160. package/lib/sdam/common.js.map +1 -1
  161. package/lib/sdam/monitor.js +1 -5
  162. package/lib/sdam/monitor.js.map +1 -1
  163. package/lib/sdam/server.js +2 -2
  164. package/lib/sdam/server.js.map +1 -1
  165. package/lib/sdam/server_description.js +3 -3
  166. package/lib/sdam/server_description.js.map +1 -1
  167. package/lib/sdam/server_selection.js +5 -5
  168. package/lib/sdam/server_selection.js.map +1 -1
  169. package/lib/sdam/srv_polling.js +2 -3
  170. package/lib/sdam/srv_polling.js.map +1 -1
  171. package/lib/sdam/topology.js +1 -1
  172. package/lib/sdam/topology.js.map +1 -1
  173. package/lib/sdam/topology_description.js.map +1 -1
  174. package/lib/sessions.js +221 -218
  175. package/lib/sessions.js.map +1 -1
  176. package/lib/sort.js +2 -3
  177. package/lib/sort.js.map +1 -1
  178. package/lib/timeout.js +0 -1
  179. package/lib/timeout.js.map +1 -1
  180. package/lib/transactions.js +2 -2
  181. package/lib/transactions.js.map +1 -1
  182. package/lib/utils.js +49 -51
  183. package/lib/utils.js.map +1 -1
  184. package/lib/write_concern.js +2 -2
  185. package/lib/write_concern.js.map +1 -1
  186. package/mongodb.d.ts +150 -142
  187. package/package.json +26 -27
  188. package/src/beta.ts +22 -0
  189. package/src/bson.ts +1 -2
  190. package/src/bulk/common.ts +18 -18
  191. package/src/change_stream.ts +33 -15
  192. package/src/client-side-encryption/auto_encrypter.ts +18 -82
  193. package/src/client-side-encryption/client_encryption.ts +51 -54
  194. package/src/client-side-encryption/mongocryptd_manager.ts +10 -6
  195. package/src/client-side-encryption/state_machine.ts +28 -6
  196. package/src/cmap/auth/gssapi.ts +1 -1
  197. package/src/cmap/auth/mongodb_aws.ts +2 -2
  198. package/src/cmap/auth/mongodb_oidc/callback_workflow.ts +2 -2
  199. package/src/cmap/auth/mongodb_oidc/machine_workflow.ts +2 -2
  200. package/src/cmap/commands.ts +70 -5
  201. package/src/cmap/connect.ts +4 -1
  202. package/src/cmap/connection.ts +2 -2
  203. package/src/cmap/connection_pool.ts +17 -9
  204. package/src/cmap/connection_pool_events.ts +34 -2
  205. package/src/cmap/handshake/client_metadata.ts +1 -1
  206. package/src/cmap/wire_protocol/constants.ts +2 -2
  207. package/src/cmap/wire_protocol/shared.ts +1 -2
  208. package/src/collection.ts +16 -15
  209. package/src/connection_string.ts +10 -3
  210. package/src/constants.ts +1 -0
  211. package/src/cursor/abstract_cursor.ts +38 -13
  212. package/src/cursor/aggregation_cursor.ts +6 -4
  213. package/src/deps.ts +8 -1
  214. package/src/error.ts +33 -14
  215. package/src/gridfs/download.ts +28 -4
  216. package/src/gridfs/upload.ts +1 -6
  217. package/src/index.ts +5 -1
  218. package/src/mongo_client.ts +29 -5
  219. package/src/mongo_logger.ts +5 -3
  220. package/src/mongo_types.ts +69 -68
  221. package/src/operations/aggregate.ts +2 -1
  222. package/src/operations/bulk_write.ts +2 -2
  223. package/src/operations/client_bulk_write/command_builder.ts +283 -0
  224. package/src/operations/client_bulk_write/common.ts +146 -0
  225. package/src/operations/command.ts +1 -1
  226. package/src/operations/execute_operation.ts +137 -131
  227. package/src/operations/find_and_modify.ts +2 -7
  228. package/src/operations/insert.ts +3 -4
  229. package/src/operations/operation.ts +7 -10
  230. package/src/operations/search_indexes/drop.ts +4 -1
  231. package/src/resource_management.ts +74 -0
  232. package/src/sdam/monitor.ts +3 -5
  233. package/src/sdam/server.ts +1 -1
  234. package/src/sdam/server_description.ts +5 -6
  235. package/src/sdam/srv_polling.ts +1 -2
  236. package/src/sessions.ts +291 -277
  237. package/src/sort.ts +1 -1
  238. package/src/timeout.ts +0 -1
  239. package/src/transactions.ts +1 -2
  240. package/src/utils.ts +9 -4
  241. package/src/write_concern.ts +2 -2
  242. package/tsconfig.json +2 -1
@@ -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
  }
@@ -13,6 +13,7 @@ import {
13
13
  CONNECTION_READY
14
14
  } from '../constants';
15
15
  import type { MongoError } from '../error';
16
+ import { now } from '../utils';
16
17
  import type { Connection } from './connection';
17
18
  import type { ConnectionPool, ConnectionPoolOptions } from './connection_pool';
18
19
 
@@ -126,12 +127,25 @@ export class ConnectionCreatedEvent extends ConnectionPoolMonitoringEvent {
126
127
  export class ConnectionReadyEvent extends ConnectionPoolMonitoringEvent {
127
128
  /** The id of the connection */
128
129
  connectionId: number | '<monitor>';
130
+ /**
131
+ * The time it took to establish the connection.
132
+ * In accordance with the definition of establishment of a connection
133
+ * specified by `ConnectionPoolOptions.maxConnecting`,
134
+ * it is the time elapsed between emitting a `ConnectionCreatedEvent`
135
+ * and emitting this event as part of the same checking out.
136
+ *
137
+ * Naturally, when establishing a connection is part of checking out,
138
+ * this duration is not greater than
139
+ * `ConnectionCheckedOutEvent.duration`.
140
+ */
141
+ durationMS: number;
129
142
  /** @internal */
130
143
  name = CONNECTION_READY;
131
144
 
132
145
  /** @internal */
133
- constructor(pool: ConnectionPool, connection: Connection) {
146
+ constructor(pool: ConnectionPool, connection: Connection, connectionCreatedEventTime: number) {
134
147
  super(pool);
148
+ this.durationMS = now() - connectionCreatedEventTime;
135
149
  this.connectionId = connection.id;
136
150
  }
137
151
  }
@@ -194,14 +208,23 @@ export class ConnectionCheckOutFailedEvent extends ConnectionPoolMonitoringEvent
194
208
  error?: MongoError;
195
209
  /** @internal */
196
210
  name = CONNECTION_CHECK_OUT_FAILED;
211
+ /**
212
+ * The time it took to check out the connection.
213
+ * More specifically, the time elapsed between
214
+ * emitting a `ConnectionCheckOutStartedEvent`
215
+ * and emitting this event as part of the same check out.
216
+ */
217
+ durationMS: number;
197
218
 
198
219
  /** @internal */
199
220
  constructor(
200
221
  pool: ConnectionPool,
201
222
  reason: 'poolClosed' | 'timeout' | 'connectionError',
223
+ checkoutTime: number,
202
224
  error?: MongoError
203
225
  ) {
204
226
  super(pool);
227
+ this.durationMS = now() - checkoutTime;
205
228
  this.reason = reason;
206
229
  this.error = error;
207
230
  }
@@ -217,10 +240,19 @@ export class ConnectionCheckedOutEvent extends ConnectionPoolMonitoringEvent {
217
240
  connectionId: number | '<monitor>';
218
241
  /** @internal */
219
242
  name = CONNECTION_CHECKED_OUT;
243
+ /**
244
+ * The time it took to check out the connection.
245
+ * More specifically, the time elapsed between
246
+ * emitting a `ConnectionCheckOutStartedEvent`
247
+ * and emitting this event as part of the same checking out.
248
+ *
249
+ */
250
+ durationMS: number;
220
251
 
221
252
  /** @internal */
222
- constructor(pool: ConnectionPool, connection: Connection) {
253
+ constructor(pool: ConnectionPool, connection: Connection, checkoutTime: number) {
223
254
  super(pool);
255
+ this.durationMS = now() - checkoutTime;
224
256
  this.connectionId = connection.id;
225
257
  }
226
258
  }
@@ -6,7 +6,7 @@ import { MongoInvalidArgumentError } from '../../error';
6
6
  import type { MongoOptions } from '../../mongo_client';
7
7
  import { fileIsAccessible } from '../../utils';
8
8
 
9
- // eslint-disable-next-line @typescript-eslint/no-var-requires
9
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
10
10
  const NODE_DRIVER_VERSION = require('../../../package.json').version;
11
11
 
12
12
  /**
@@ -1,7 +1,7 @@
1
1
  export const MIN_SUPPORTED_SERVER_VERSION = '3.6';
2
- export const MAX_SUPPORTED_SERVER_VERSION = '7.0';
2
+ export const MAX_SUPPORTED_SERVER_VERSION = '8.0';
3
3
  export const MIN_SUPPORTED_WIRE_VERSION = 6;
4
- export const MAX_SUPPORTED_WIRE_VERSION = 21;
4
+ export const MAX_SUPPORTED_WIRE_VERSION = 25;
5
5
  export const MIN_SUPPORTED_QE_WIRE_VERSION = 21;
6
6
  export const MIN_SUPPORTED_QE_SERVER_VERSION = '7.0';
7
7
  export const OP_REPLY = 1;
@@ -1,6 +1,5 @@
1
1
  import { MongoInvalidArgumentError } from '../../error';
2
- import type { ReadPreferenceLike } from '../../read_preference';
3
- import { ReadPreference } from '../../read_preference';
2
+ import { ReadPreference, type ReadPreferenceLike } from '../../read_preference';
4
3
  import { ServerType } from '../../sdam/common';
5
4
  import type { Server } from '../../sdam/server';
6
5
  import type { ServerDescription } from '../../sdam/server_description';
package/src/collection.ts CHANGED
@@ -47,17 +47,18 @@ import {
47
47
  FindOneAndUpdateOperation,
48
48
  type FindOneAndUpdateOptions
49
49
  } from './operations/find_and_modify';
50
- import type {
51
- CreateIndexesOptions,
52
- DropIndexesOptions,
53
- IndexDescription,
54
- IndexDescriptionCompact,
55
- IndexDescriptionInfo,
56
- IndexInformationOptions,
57
- IndexSpecification,
58
- ListIndexesOptions
50
+ import {
51
+ CreateIndexesOperation,
52
+ type CreateIndexesOptions,
53
+ type DropIndexesOptions,
54
+ DropIndexOperation,
55
+ type IndexDescription,
56
+ type IndexDescriptionCompact,
57
+ type IndexDescriptionInfo,
58
+ type IndexInformationOptions,
59
+ type IndexSpecification,
60
+ type ListIndexesOptions
59
61
  } from './operations/indexes';
60
- import { CreateIndexesOperation, DropIndexOperation } from './operations/indexes';
61
62
  import {
62
63
  InsertManyOperation,
63
64
  type InsertManyResult,
@@ -292,7 +293,7 @@ export class Collection<TSchema extends Document = Document> {
292
293
  * @param options - Optional settings for the command
293
294
  */
294
295
  async insertMany(
295
- docs: OptionalUnlessRequiredId<TSchema>[],
296
+ docs: ReadonlyArray<OptionalUnlessRequiredId<TSchema>>,
296
297
  options?: BulkWriteOptions
297
298
  ): Promise<InsertManyResult<TSchema>> {
298
299
  return await executeOperation(
@@ -325,7 +326,7 @@ export class Collection<TSchema extends Document = Document> {
325
326
  * @throws MongoDriverError if operations is not an array
326
327
  */
327
328
  async bulkWrite(
328
- operations: AnyBulkWriteOperation<TSchema>[],
329
+ operations: ReadonlyArray<AnyBulkWriteOperation<TSchema>>,
329
330
  options?: BulkWriteOptions
330
331
  ): Promise<BulkWriteResult> {
331
332
  if (!Array.isArray(operations)) {
@@ -336,7 +337,7 @@ export class Collection<TSchema extends Document = Document> {
336
337
  this.client,
337
338
  new BulkWriteOperation(
338
339
  this as TODO_NODE_3286,
339
- operations as TODO_NODE_3286,
340
+ operations,
340
341
  resolveOptions(this, options ?? { ordered: true })
341
342
  )
342
343
  );
@@ -1121,8 +1122,8 @@ export class Collection<TSchema extends Document = Document> {
1121
1122
  indexNameOrOptions == null
1122
1123
  ? null
1123
1124
  : typeof indexNameOrOptions === 'object'
1124
- ? null
1125
- : indexNameOrOptions;
1125
+ ? null
1126
+ : indexNameOrOptions;
1126
1127
 
1127
1128
  return new ListSearchIndexesCursor(this as TODO_NODE_3286, indexName, options);
1128
1129
  }
@@ -73,7 +73,7 @@ export async function resolveSRVRecord(options: MongoOptions): Promise<HostAddre
73
73
  // the SRV record is resolved before starting a second DNS query.
74
74
  const lookupAddress = options.srvHost;
75
75
  const txtResolutionPromise = dns.promises.resolveTxt(lookupAddress);
76
- // eslint-disable-next-line github/no-then
76
+
77
77
  txtResolutionPromise.then(undefined, squashError); // rejections will be handled later
78
78
 
79
79
  // Resolve the SRV record and use the result as the list of hosts to connect to.
@@ -552,7 +552,6 @@ export function parseOptions(
552
552
 
553
553
  mongoOptions.metadata = makeClientMetadata(mongoOptions);
554
554
 
555
- // eslint-disable-next-line github/no-then
556
555
  mongoOptions.extendedMetadata = addContainerMetadata(mongoOptions.metadata).then(
557
556
  undefined,
558
557
  squashError
@@ -740,6 +739,13 @@ export const OPTIONS = {
740
739
  autoEncryption: {
741
740
  type: 'record'
742
741
  },
742
+ autoSelectFamily: {
743
+ type: 'boolean',
744
+ default: true
745
+ },
746
+ autoSelectFamilyAttemptTimeout: {
747
+ type: 'uint'
748
+ },
743
749
  bsonRegExp: {
744
750
  type: 'boolean'
745
751
  },
@@ -1222,7 +1228,8 @@ export const OPTIONS = {
1222
1228
  // Custom types for modifying core behavior
1223
1229
  connectionType: { type: 'any' },
1224
1230
  srvPoller: { type: 'any' },
1225
- // Accepted NodeJS Options
1231
+ // Accepted Node.js Options
1232
+ allowPartialTrustChain: { type: 'any' },
1226
1233
  minDHSize: { type: 'any' },
1227
1234
  pskCallback: { type: 'any' },
1228
1235
  secureContext: { type: 'any' },
package/src/constants.ts CHANGED
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-unnecessary-type-assertion */
1
2
  export const SYSTEM_NAMESPACE_COLLECTION = 'system.namespaces';
2
3
  export const SYSTEM_INDEX_COLLECTION = 'system.indexes';
3
4
  export const SYSTEM_PROFILE_COLLECTION = 'system.profile';
@@ -18,6 +18,7 @@ import { GetMoreOperation } from '../operations/get_more';
18
18
  import { KillCursorsOperation } from '../operations/kill_cursors';
19
19
  import { ReadConcern, type ReadConcernLike } from '../read_concern';
20
20
  import { ReadPreference, type ReadPreferenceLike } from '../read_preference';
21
+ import { type AsyncDisposable, configureResourceManagement } from '../resource_management';
21
22
  import type { Server } from '../sdam/server';
22
23
  import { ClientSession, maybeClearPinnedConnection } from '../sessions';
23
24
  import { type MongoDBNamespace, squashError } from '../utils';
@@ -125,9 +126,12 @@ export type AbstractCursorEvents = {
125
126
 
126
127
  /** @public */
127
128
  export abstract class AbstractCursor<
128
- TSchema = any,
129
- CursorEvents extends AbstractCursorEvents = AbstractCursorEvents
130
- > extends TypedEventEmitter<CursorEvents> {
129
+ TSchema = any,
130
+ CursorEvents extends AbstractCursorEvents = AbstractCursorEvents
131
+ >
132
+ extends TypedEventEmitter<CursorEvents>
133
+ implements AsyncDisposable
134
+ {
131
135
  /** @internal */
132
136
  private cursorId: Long | null;
133
137
  /** @internal */
@@ -286,14 +290,25 @@ export abstract class AbstractCursor<
286
290
  return !!this.cursorClient.topology?.loadBalanced;
287
291
  }
288
292
 
293
+ /**
294
+ * @beta
295
+ * @experimental
296
+ * An alias for {@link AbstractCursor.close|AbstractCursor.close()}.
297
+ */
298
+ declare [Symbol.asyncDispose]: () => Promise<void>;
299
+ /** @internal */
300
+ async asyncDispose() {
301
+ await this.close();
302
+ }
303
+
289
304
  /** Returns current buffered documents length */
290
305
  bufferedCount(): number {
291
306
  return this.documents?.length ?? 0;
292
307
  }
293
308
 
294
309
  /** Returns current buffered documents */
295
- readBufferedDocuments(number?: number): TSchema[] {
296
- const bufferedDocs: TSchema[] = [];
310
+ readBufferedDocuments(number?: number): NonNullable<TSchema>[] {
311
+ const bufferedDocs: NonNullable<TSchema>[] = [];
297
312
  const documentsToRead = Math.min(
298
313
  number ?? this.documents?.length ?? 0,
299
314
  this.documents?.length ?? 0
@@ -308,6 +323,7 @@ export abstract class AbstractCursor<
308
323
 
309
324
  return bufferedDocs;
310
325
  }
326
+
311
327
  async *[Symbol.asyncIterator](): AsyncGenerator<TSchema, void, void> {
312
328
  if (this.closed) {
313
329
  return;
@@ -457,6 +473,9 @@ export abstract class AbstractCursor<
457
473
  }
458
474
  }
459
475
 
476
+ /**
477
+ * Frees any client-side resources used by the cursor.
478
+ */
460
479
  async close(): Promise<void> {
461
480
  await this.cleanup();
462
481
  }
@@ -468,13 +487,22 @@ export abstract class AbstractCursor<
468
487
  * cursor.rewind() can be used to reset the cursor.
469
488
  */
470
489
  async toArray(): Promise<TSchema[]> {
471
- const array = [];
490
+ const array: TSchema[] = [];
491
+ // at the end of the loop (since readBufferedDocuments is called) the buffer will be empty
492
+ // then, the 'await of' syntax will run a getMore call
472
493
  for await (const document of this) {
473
494
  array.push(document);
495
+ const docs = this.readBufferedDocuments();
496
+ if (this.transform != null) {
497
+ for (const doc of docs) {
498
+ array.push(await this.transformDocument(doc));
499
+ }
500
+ } else {
501
+ array.push(...docs);
502
+ }
474
503
  }
475
504
  return array;
476
505
  }
477
-
478
506
  /**
479
507
  * Add a cursor flag to the cursor
480
508
  *
@@ -639,7 +667,6 @@ export abstract class AbstractCursor<
639
667
  // We only want to end this session if we created it, and it hasn't ended yet
640
668
  if (session.explicit === false) {
641
669
  if (!session.hasEnded) {
642
- // eslint-disable-next-line github/no-then
643
670
  session.endSession().then(undefined, squashError);
644
671
  }
645
672
  this.cursorSession = this.cursorClient.startSession({ owner: this, explicit: false });
@@ -815,7 +842,7 @@ export abstract class AbstractCursor<
815
842
  }
816
843
 
817
844
  /** @internal */
818
- private async transformDocument(document: NonNullable<TSchema>): Promise<TSchema> {
845
+ private async transformDocument(document: NonNullable<TSchema>): Promise<NonNullable<TSchema>> {
819
846
  if (this.transform == null) return document;
820
847
 
821
848
  try {
@@ -865,7 +892,6 @@ class ReadableCursorStream extends Readable {
865
892
  }
866
893
 
867
894
  override _destroy(error: Error | null, callback: (error?: Error | null) => void): void {
868
- // eslint-disable-next-line github/no-then
869
895
  this._cursor.close().then(
870
896
  () => callback(error),
871
897
  closeError => callback(closeError)
@@ -878,13 +904,11 @@ class ReadableCursorStream extends Readable {
878
904
  return;
879
905
  }
880
906
 
881
- // eslint-disable-next-line github/no-then
882
907
  this._cursor.next().then(
883
908
  result => {
884
909
  if (result == null) {
885
910
  this.push(null);
886
911
  } else if (this.destroyed) {
887
- // eslint-disable-next-line github/no-then
888
912
  this._cursor.close().then(undefined, squashError);
889
913
  } else {
890
914
  if (this.push(result)) {
@@ -900,7 +924,6 @@ class ReadableCursorStream extends Readable {
900
924
  // a client during iteration. Alternatively, we could do the "right" thing and
901
925
  // propagate the error message by removing this special case.
902
926
  if (err.message.match(/server is closed/)) {
903
- // eslint-disable-next-line github/no-then
904
927
  this._cursor.close().then(undefined, squashError);
905
928
  return this.push(null);
906
929
  }
@@ -927,3 +950,5 @@ class ReadableCursorStream extends Readable {
927
950
  );
928
951
  }
929
952
  }
953
+
954
+ configureResourceManagement(AbstractCursor.prototype);
@@ -5,10 +5,12 @@ import { AggregateOperation, type AggregateOptions } from '../operations/aggrega
5
5
  import { executeOperation } from '../operations/execute_operation';
6
6
  import type { ClientSession } from '../sessions';
7
7
  import type { Sort } from '../sort';
8
- import type { MongoDBNamespace } from '../utils';
9
- import { mergeOptions } from '../utils';
10
- import type { AbstractCursorOptions, InitialCursorResponse } from './abstract_cursor';
11
- import { AbstractCursor } from './abstract_cursor';
8
+ import { mergeOptions, type MongoDBNamespace } from '../utils';
9
+ import {
10
+ AbstractCursor,
11
+ type AbstractCursorOptions,
12
+ type InitialCursorResponse
13
+ } from './abstract_cursor';
12
14
 
13
15
  /** @public */
14
16
  export interface AggregationCursorOptions extends AbstractCursorOptions, AggregateOptions {}