mongodb 6.20.0-dev.20251106.sha.696664cb → 6.21.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 (151) hide show
  1. package/README.md +11 -11
  2. package/lib/beta.d.ts +9229 -0
  3. package/lib/beta.js +21 -0
  4. package/lib/beta.js.map +1 -0
  5. package/lib/bulk/common.js +9 -7
  6. package/lib/bulk/common.js.map +1 -1
  7. package/lib/change_stream.js +38 -84
  8. package/lib/change_stream.js.map +1 -1
  9. package/lib/client-side-encryption/auto_encrypter.js +4 -2
  10. package/lib/client-side-encryption/auto_encrypter.js.map +1 -1
  11. package/lib/client-side-encryption/client_encryption.js +3 -2
  12. package/lib/client-side-encryption/client_encryption.js.map +1 -1
  13. package/lib/client-side-encryption/crypto_callbacks.js +81 -0
  14. package/lib/client-side-encryption/crypto_callbacks.js.map +1 -0
  15. package/lib/client-side-encryption/errors.js +1 -3
  16. package/lib/client-side-encryption/errors.js.map +1 -1
  17. package/lib/client-side-encryption/mongocryptd_manager.js +1 -1
  18. package/lib/client-side-encryption/mongocryptd_manager.js.map +1 -1
  19. package/lib/cmap/auth/aws_temporary_credentials.js +58 -10
  20. package/lib/cmap/auth/aws_temporary_credentials.js.map +1 -1
  21. package/lib/cmap/auth/mongo_credentials.js +15 -0
  22. package/lib/cmap/auth/mongo_credentials.js.map +1 -1
  23. package/lib/cmap/auth/mongodb_aws.js +7 -2
  24. package/lib/cmap/auth/mongodb_aws.js.map +1 -1
  25. package/lib/cmap/auth/providers.js +1 -0
  26. package/lib/cmap/auth/providers.js.map +1 -1
  27. package/lib/cmap/connect.js +1 -1
  28. package/lib/cmap/connect.js.map +1 -1
  29. package/lib/cmap/connection.js +27 -28
  30. package/lib/cmap/connection.js.map +1 -1
  31. package/lib/cmap/connection_pool.js +59 -59
  32. package/lib/cmap/connection_pool.js.map +1 -1
  33. package/lib/cmap/errors.js +1 -1
  34. package/lib/cmap/errors.js.map +1 -1
  35. package/lib/cmap/handshake/client_metadata.js +5 -7
  36. package/lib/cmap/handshake/client_metadata.js.map +1 -1
  37. package/lib/cmap/metrics.js +3 -3
  38. package/lib/cmap/metrics.js.map +1 -1
  39. package/lib/cmap/wire_protocol/constants.js +1 -3
  40. package/lib/cmap/wire_protocol/constants.js.map +1 -1
  41. package/lib/cmap/wire_protocol/on_data.js +1 -0
  42. package/lib/cmap/wire_protocol/on_data.js.map +1 -1
  43. package/lib/cmap/wire_protocol/responses.js +2 -2
  44. package/lib/cmap/wire_protocol/responses.js.map +1 -1
  45. package/lib/collection.js +1 -1
  46. package/lib/collection.js.map +1 -1
  47. package/lib/connection_string.js +10 -8
  48. package/lib/connection_string.js.map +1 -1
  49. package/lib/cursor/abstract_cursor.js +34 -17
  50. package/lib/cursor/abstract_cursor.js.map +1 -1
  51. package/lib/cursor/change_stream_cursor.js +2 -2
  52. package/lib/cursor/change_stream_cursor.js.map +1 -1
  53. package/lib/cursor/find_cursor.js +26 -37
  54. package/lib/cursor/find_cursor.js.map +1 -1
  55. package/lib/cursor/run_command_cursor.js +1 -1
  56. package/lib/cursor/run_command_cursor.js.map +1 -1
  57. package/lib/db.js +6 -6
  58. package/lib/db.js.map +1 -1
  59. package/lib/error.js +2 -2
  60. package/lib/error.js.map +1 -1
  61. package/lib/gridfs/download.js +5 -5
  62. package/lib/gridfs/download.js.map +1 -1
  63. package/lib/gridfs/index.js +9 -9
  64. package/lib/gridfs/index.js.map +1 -1
  65. package/lib/gridfs/upload.js +8 -2
  66. package/lib/gridfs/upload.js.map +1 -1
  67. package/lib/index.js +4 -2
  68. package/lib/index.js.map +1 -1
  69. package/lib/mongo_client.js +67 -58
  70. package/lib/mongo_client.js.map +1 -1
  71. package/lib/mongo_client_auth_providers.js +6 -0
  72. package/lib/mongo_client_auth_providers.js.map +1 -1
  73. package/lib/mongo_logger.js.map +1 -1
  74. package/lib/mongo_types.js +2 -1
  75. package/lib/mongo_types.js.map +1 -1
  76. package/lib/operations/aggregate.js +3 -0
  77. package/lib/operations/aggregate.js.map +1 -1
  78. package/lib/operations/command.js.map +1 -1
  79. package/lib/operations/create_collection.js +1 -0
  80. package/lib/operations/create_collection.js.map +1 -1
  81. package/lib/operations/drop.js +9 -8
  82. package/lib/operations/drop.js.map +1 -1
  83. package/lib/operations/execute_operation.js +1 -3
  84. package/lib/operations/execute_operation.js.map +1 -1
  85. package/lib/operations/find.js.map +1 -1
  86. package/lib/read_preference.js +14 -10
  87. package/lib/read_preference.js.map +1 -1
  88. package/lib/resource_management.js +58 -0
  89. package/lib/resource_management.js.map +1 -0
  90. package/lib/sdam/server.js +14 -14
  91. package/lib/sdam/server.js.map +1 -1
  92. package/lib/sdam/srv_polling.js +2 -2
  93. package/lib/sdam/srv_polling.js.map +1 -1
  94. package/lib/sdam/topology.js +68 -24
  95. package/lib/sdam/topology.js.map +1 -1
  96. package/lib/sessions.js +4 -5
  97. package/lib/sessions.js.map +1 -1
  98. package/lib/transactions.js +13 -2
  99. package/lib/transactions.js.map +1 -1
  100. package/lib/utils.js +14 -0
  101. package/lib/utils.js.map +1 -1
  102. package/mongodb.d.ts +244 -72
  103. package/package.json +20 -17
  104. package/src/beta.ts +22 -0
  105. package/src/bulk/common.ts +11 -9
  106. package/src/change_stream.ts +37 -85
  107. package/src/client-side-encryption/auto_encrypter.ts +12 -6
  108. package/src/client-side-encryption/client_encryption.ts +6 -5
  109. package/src/client-side-encryption/crypto_callbacks.ts +87 -0
  110. package/src/client-side-encryption/errors.ts +0 -3
  111. package/src/cmap/auth/aws_temporary_credentials.ts +70 -12
  112. package/src/cmap/auth/mongo_credentials.ts +21 -1
  113. package/src/cmap/auth/mongodb_aws.ts +17 -8
  114. package/src/cmap/auth/providers.ts +1 -0
  115. package/src/cmap/connect.ts +1 -1
  116. package/src/cmap/connection.ts +18 -14
  117. package/src/cmap/connection_pool.ts +13 -4
  118. package/src/cmap/errors.ts +1 -1
  119. package/src/cmap/handshake/client_metadata.ts +26 -18
  120. package/src/cmap/wire_protocol/constants.ts +0 -2
  121. package/src/cmap/wire_protocol/on_data.ts +2 -1
  122. package/src/collection.ts +1 -1
  123. package/src/connection_string.ts +20 -13
  124. package/src/cursor/abstract_cursor.ts +52 -12
  125. package/src/cursor/change_stream_cursor.ts +2 -2
  126. package/src/cursor/find_cursor.ts +27 -40
  127. package/src/cursor/run_command_cursor.ts +1 -1
  128. package/src/error.ts +2 -2
  129. package/src/gridfs/download.ts +4 -0
  130. package/src/gridfs/upload.ts +22 -0
  131. package/src/index.ts +8 -2
  132. package/src/mongo_client.ts +100 -68
  133. package/src/mongo_client_auth_providers.ts +8 -0
  134. package/src/mongo_logger.ts +1 -1
  135. package/src/mongo_types.ts +2 -1
  136. package/src/operations/aggregate.ts +6 -0
  137. package/src/operations/command.ts +12 -0
  138. package/src/operations/create_collection.ts +3 -0
  139. package/src/operations/drop.ts +11 -9
  140. package/src/operations/execute_operation.ts +2 -6
  141. package/src/operations/find.ts +11 -2
  142. package/src/read_preference.ts +9 -0
  143. package/src/resource_management.ts +74 -0
  144. package/src/sdam/topology.ts +60 -2
  145. package/src/sessions.ts +8 -2
  146. package/src/transactions.ts +17 -2
  147. package/src/utils.ts +18 -0
  148. package/tsconfig.json +7 -5
  149. package/lib/operations/end_sessions.js +0 -34
  150. package/lib/operations/end_sessions.js.map +0 -1
  151. package/src/operations/end_sessions.ts +0 -44
@@ -1,4 +1,4 @@
1
- import { Readable } from 'stream';
1
+ import { Readable, Transform } from 'stream';
2
2
 
3
3
  import { type BSONSerializeOptions, type Document, Long, pluckBSONSerializeOptions } from '../bson';
4
4
  import { type OnDemandDocumentDeserializeOptions } from '../cmap/wire_protocol/on_demand/document';
@@ -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 { type ClientSession, maybeClearPinnedConnection } from '../sessions';
23
24
  import { type CSOTTimeoutContext, type Timeout, TimeoutContext } from '../timeout';
@@ -58,6 +59,15 @@ export const CURSOR_FLAGS = [
58
59
  'partial'
59
60
  ] as const;
60
61
 
62
+ /**
63
+ * @public
64
+ * @deprecated Will be removed in the next major version
65
+ */
66
+ export interface CursorStreamOptions {
67
+ /** @deprecated Will be removed in the next major version */
68
+ transform?(this: void, doc: Document): Document;
69
+ }
70
+
61
71
  /** @public */
62
72
  export type CursorFlag = (typeof CURSOR_FLAGS)[number];
63
73
 
@@ -430,10 +440,13 @@ export abstract class AbstractCursor<
430
440
  }
431
441
 
432
442
  /**
443
+ * @beta
433
444
  * @experimental
434
445
  * An alias for {@link AbstractCursor.close|AbstractCursor.close()}.
435
446
  */
436
- async [Symbol.asyncDispose]() {
447
+ declare [Symbol.asyncDispose]: () => Promise<void>;
448
+ /** @internal */
449
+ async asyncDispose() {
437
450
  await this.close();
438
451
  }
439
452
 
@@ -513,7 +526,7 @@ export abstract class AbstractCursor<
513
526
  }
514
527
  }
515
528
 
516
- stream(): Readable & AsyncIterable<TSchema> {
529
+ stream(options?: CursorStreamOptions): Readable & AsyncIterable<TSchema> {
517
530
  const readable = new ReadableCursorStream(this);
518
531
  const abortListener = addAbortListener(this.signal, function () {
519
532
  readable.destroy(this.reason);
@@ -522,6 +535,31 @@ export abstract class AbstractCursor<
522
535
  abortListener?.[kDispose]();
523
536
  });
524
537
 
538
+ if (options?.transform) {
539
+ const transform = options.transform;
540
+
541
+ const transformedStream = readable.pipe(
542
+ new Transform({
543
+ objectMode: true,
544
+ highWaterMark: 1,
545
+ transform(chunk, _, callback) {
546
+ try {
547
+ const transformed = transform(chunk);
548
+ callback(undefined, transformed);
549
+ } catch (err) {
550
+ callback(err);
551
+ }
552
+ }
553
+ })
554
+ );
555
+
556
+ // Bubble errors to transformed stream, because otherwise no way
557
+ // to handle this error.
558
+ readable.on('error', err => transformedStream.emit('error', err));
559
+
560
+ return transformedStream;
561
+ }
562
+
525
563
  return readable;
526
564
  }
527
565
 
@@ -666,11 +704,7 @@ export abstract class AbstractCursor<
666
704
  array.push(await this.transformDocument(doc));
667
705
  }
668
706
  } else {
669
- // Note: previous versions of this logic used `array.push(...)`, which adds each item
670
- // to the callstack. For large arrays, this can exceed the maximum call size.
671
- for (const doc of docs) {
672
- array.push(doc);
673
- }
707
+ array.push(...docs);
674
708
  }
675
709
  }
676
710
  return array;
@@ -862,7 +896,7 @@ export abstract class AbstractCursor<
862
896
  ): Promise<InitialCursorResponse>;
863
897
 
864
898
  /** @internal */
865
- async getMore(): Promise<CursorResponse> {
899
+ async getMore(batchSize: number): Promise<CursorResponse> {
866
900
  if (this.cursorId == null) {
867
901
  throw new MongoRuntimeError(
868
902
  'Unexpected null cursor id. A cursor creating command should have set this'
@@ -879,10 +913,11 @@ export abstract class AbstractCursor<
879
913
  'Unexpected null session. A cursor creating command should have set this'
880
914
  );
881
915
  }
916
+
882
917
  const getMoreOptions = {
883
918
  ...this.cursorOptions,
884
919
  session: this.cursorSession,
885
- batchSize: this.cursorOptions.batchSize
920
+ batchSize
886
921
  };
887
922
 
888
923
  const getMoreOperation = new GetMoreOperation(
@@ -955,11 +990,14 @@ export abstract class AbstractCursor<
955
990
  await this.cursorInit();
956
991
  // If the cursor died or returned documents, return
957
992
  if ((this.documents?.length ?? 0) !== 0 || this.isDead) return;
993
+ // Otherwise, run a getMore
958
994
  }
959
995
 
960
- // Otherwise, run a getMore
996
+ // otherwise need to call getMore
997
+ const batchSize = this.cursorOptions.batchSize || 1000;
998
+
961
999
  try {
962
- const response = await this.getMore();
1000
+ const response = await this.getMore(batchSize);
963
1001
  this.cursorId = response.id;
964
1002
  this.documents = response;
965
1003
  } catch (error) {
@@ -1188,6 +1226,8 @@ class ReadableCursorStream extends Readable {
1188
1226
  }
1189
1227
  }
1190
1228
 
1229
+ configureResourceManagement(AbstractCursor.prototype);
1230
+
1191
1231
  /**
1192
1232
  * @internal
1193
1233
  * The cursor timeout context is a wrapper around a timeout context
@@ -158,8 +158,8 @@ export class ChangeStreamCursor<
158
158
  return { server, session, response };
159
159
  }
160
160
 
161
- override async getMore(): Promise<CursorResponse> {
162
- const response = await super.getMore();
161
+ override async getMore(batchSize: number): Promise<CursorResponse> {
162
+ const response = await super.getMore(batchSize);
163
163
 
164
164
  this.maxWireVersion = maxWireVersion(this.server);
165
165
  this._processBatch(response);
@@ -16,7 +16,7 @@ import { FindOperation, type FindOptions } from '../operations/find';
16
16
  import type { Hint } from '../operations/operation';
17
17
  import type { ClientSession } from '../sessions';
18
18
  import { formatSort, type Sort, type SortDirection } from '../sort';
19
- import { emitWarningOnce, mergeOptions, type MongoDBNamespace, noop, squashError } from '../utils';
19
+ import { emitWarningOnce, mergeOptions, type MongoDBNamespace, squashError } from '../utils';
20
20
  import { type InitialCursorResponse } from './abstract_cursor';
21
21
  import { ExplainableCursor } from './explainable_cursor';
22
22
 
@@ -98,50 +98,37 @@ export class FindCursor<TSchema = any> extends ExplainableCursor<TSchema> {
98
98
  }
99
99
 
100
100
  /** @internal */
101
- override async getMore(): Promise<CursorResponse> {
101
+ override async getMore(batchSize: number): Promise<CursorResponse> {
102
102
  const numReturned = this.numReturned;
103
- const limit = this.findOptions.limit ?? Infinity;
104
- const remaining = limit - numReturned;
105
-
106
- if (numReturned === limit && !this.id?.isZero()) {
107
- // this is an optimization for the special case of a limit for a find command to avoid an
108
- // extra getMore when the limit has been reached and the limit is a multiple of the batchSize.
109
- // This is a consequence of the new query engine in 5.0 having no knowledge of the limit as it
110
- // produces results for the find command. Once a batch is filled up, it is returned and only
111
- // on the subsequent getMore will the query framework consider the limit, determine the cursor
112
- // is exhausted and return a cursorId of zero.
113
- // instead, if we determine there are no more documents to request from the server, we preemptively
114
- // close the cursor
115
- try {
116
- await this.close();
117
- } catch (error) {
118
- squashError(error);
103
+ if (numReturned) {
104
+ // TODO(DRIVERS-1448): Remove logic to enforce `limit` in the driver
105
+ const limit = this.findOptions.limit;
106
+ batchSize =
107
+ limit && limit > 0 && numReturned + batchSize > limit ? limit - numReturned : batchSize;
108
+
109
+ if (batchSize <= 0) {
110
+ try {
111
+ await this.close();
112
+ } catch (error) {
113
+ squashError(error);
114
+ // this is an optimization for the special case of a limit for a find command to avoid an
115
+ // extra getMore when the limit has been reached and the limit is a multiple of the batchSize.
116
+ // This is a consequence of the new query engine in 5.0 having no knowledge of the limit as it
117
+ // produces results for the find command. Once a batch is filled up, it is returned and only
118
+ // on the subsequent getMore will the query framework consider the limit, determine the cursor
119
+ // is exhausted and return a cursorId of zero.
120
+ // instead, if we determine there are no more documents to request from the server, we preemptively
121
+ // close the cursor
122
+ }
123
+ return CursorResponse.emptyGetMore;
119
124
  }
120
- return CursorResponse.emptyGetMore;
121
- }
122
-
123
- // TODO(DRIVERS-1448): Remove logic to enforce `limit` in the driver
124
- let cleanup: () => void = noop;
125
- const { batchSize } = this.cursorOptions;
126
- if (batchSize != null && batchSize > remaining) {
127
- this.cursorOptions.batchSize = remaining;
128
-
129
- // After executing the final getMore, re-assign the batchSize back to its original value so that
130
- // if the cursor is rewound and executed, the batchSize is still correct.
131
- cleanup = () => {
132
- this.cursorOptions.batchSize = batchSize;
133
- };
134
125
  }
135
126
 
136
- try {
137
- const response = await super.getMore();
127
+ const response = await super.getMore(batchSize);
128
+ // TODO: wrap this in some logic to prevent it from happening if we don't need this support
129
+ this.numReturned = this.numReturned + response.batchSize;
138
130
 
139
- this.numReturned = this.numReturned + response.batchSize;
140
-
141
- return response;
142
- } finally {
143
- cleanup?.();
144
- }
131
+ return response;
145
132
  }
146
133
 
147
134
  /**
@@ -159,7 +159,7 @@ export class RunCommandCursor extends AbstractCursor {
159
159
  }
160
160
 
161
161
  /** @internal */
162
- override async getMore(): Promise<CursorResponse> {
162
+ override async getMore(_batchSize: number): Promise<CursorResponse> {
163
163
  if (!this.session) {
164
164
  throw new MongoRuntimeError(
165
165
  'Unexpected null session. A cursor creating command should have set this'
package/src/error.ts CHANGED
@@ -97,7 +97,7 @@ export const MongoErrorLabel = Object.freeze({
97
97
  ResumableChangeStreamError: 'ResumableChangeStreamError',
98
98
  HandshakeError: 'HandshakeError',
99
99
  ResetPool: 'ResetPool',
100
- PoolRequestedRetry: 'PoolRequestedRetry',
100
+ PoolRequstedRetry: 'PoolRequstedRetry',
101
101
  InterruptInUseConnections: 'InterruptInUseConnections',
102
102
  NoWritesPerformed: 'NoWritesPerformed'
103
103
  } as const);
@@ -1444,7 +1444,7 @@ export function needsRetryableWriteLabel(
1444
1444
  export function isRetryableWriteError(error: MongoError): boolean {
1445
1445
  return (
1446
1446
  error.hasErrorLabel(MongoErrorLabel.RetryableWriteError) ||
1447
- error.hasErrorLabel(MongoErrorLabel.PoolRequestedRetry)
1447
+ error.hasErrorLabel(MongoErrorLabel.PoolRequstedRetry)
1448
1448
  );
1449
1449
  }
1450
1450
 
@@ -53,6 +53,10 @@ export interface GridFSFile {
53
53
  filename: string;
54
54
  metadata?: Document;
55
55
  uploadDate: Date;
56
+ /** @deprecated Will be removed in the next major version. */
57
+ contentType?: string;
58
+ /** @deprecated Will be removed in the next major version. */
59
+ aliases?: string[];
56
60
  }
57
61
 
58
62
  /** @internal */
@@ -32,6 +32,16 @@ export interface GridFSBucketWriteStreamOptions extends WriteConcernOptions {
32
32
  id?: ObjectId;
33
33
  /** Object to store in the file document's `metadata` field */
34
34
  metadata?: Document;
35
+ /**
36
+ * String to store in the file document's `contentType` field.
37
+ * @deprecated Will be removed in the next major version. Add a contentType field to the metadata document instead.
38
+ */
39
+ contentType?: string;
40
+ /**
41
+ * Array of strings to store in the file document's `aliases` field.
42
+ * @deprecated Will be removed in the next major version. Add an aliases field to the metadata document instead.
43
+ */
44
+ aliases?: string[];
35
45
  /**
36
46
  * @experimental
37
47
  * Specifies the time an operation will run until it throws a timeout error
@@ -295,6 +305,8 @@ function checkDone(stream: GridFSBucketWriteStream, callback: Callback): void {
295
305
  stream.length,
296
306
  stream.chunkSizeBytes,
297
307
  stream.filename,
308
+ stream.options.contentType,
309
+ stream.options.aliases,
298
310
  stream.options.metadata
299
311
  );
300
312
 
@@ -390,6 +402,8 @@ function createFilesDoc(
390
402
  length: number,
391
403
  chunkSize: number,
392
404
  filename: string,
405
+ contentType?: string,
406
+ aliases?: string[],
393
407
  metadata?: Document
394
408
  ): GridFSFile {
395
409
  const ret: GridFSFile = {
@@ -400,6 +414,14 @@ function createFilesDoc(
400
414
  filename
401
415
  };
402
416
 
417
+ if (contentType) {
418
+ ret.contentType = contentType;
419
+ }
420
+
421
+ if (aliases) {
422
+ ret.aliases = aliases;
423
+ }
424
+
403
425
  if (metadata) {
404
426
  ret.metadata = metadata;
405
427
  }
package/src/index.ts CHANGED
@@ -87,6 +87,7 @@ export {
87
87
  MongoWriteConcernError,
88
88
  WriteConcernErrorResult
89
89
  } from './error';
90
+ export { configureExplicitResourceManagement } from './resource_management';
90
91
  export {
91
92
  AbstractCursor,
92
93
  // Actual driver classes exported
@@ -223,6 +224,7 @@ export type {
223
224
  ChangeStreamSplitEvent,
224
225
  ChangeStreamUpdateDocument,
225
226
  OperationTime,
227
+ ResumeOptions,
226
228
  ResumeToken,
227
229
  UpdateDescription
228
230
  } from './change_stream';
@@ -305,6 +307,7 @@ export type {
305
307
  ProxyOptions
306
308
  } from './cmap/connection';
307
309
  export type {
310
+ CloseOptions,
308
311
  ConnectionPool,
309
312
  ConnectionPoolEvents,
310
313
  ConnectionPoolOptions,
@@ -312,7 +315,7 @@ export type {
312
315
  WaitQueueMember,
313
316
  WithConnectionCallback
314
317
  } from './cmap/connection_pool';
315
- export type { ClientMetadata } from './cmap/handshake/client_metadata';
318
+ export type { ClientMetadata, ClientMetadataOptions } from './cmap/handshake/client_metadata';
316
319
  export type { ConnectionPoolMetrics } from './cmap/metrics';
317
320
  export type { StreamDescription, StreamDescriptionOptions } from './cmap/stream_description';
318
321
  export type { CompressorName } from './cmap/wire_protocol/compression';
@@ -365,7 +368,8 @@ export type {
365
368
  export type {
366
369
  AbstractCursorEvents,
367
370
  AbstractCursorOptions,
368
- CursorFlag
371
+ CursorFlag,
372
+ CursorStreamOptions
369
373
  } from './cursor/abstract_cursor';
370
374
  export type {
371
375
  CursorTimeoutContext,
@@ -562,6 +566,7 @@ export type {
562
566
  ReadPreferenceLikeOptions,
563
567
  ReadPreferenceOptions
564
568
  } from './read_preference';
569
+ export type { AsyncDisposable } from './resource_management';
565
570
  export type { ClusterTime } from './sdam/common';
566
571
  export type {
567
572
  Monitor,
@@ -593,6 +598,7 @@ export type { SrvPoller, SrvPollerEvents, SrvPollerOptions } from './sdam/srv_po
593
598
  export type {
594
599
  ConnectOptions,
595
600
  SelectServerOptions,
601
+ ServerCapabilities,
596
602
  ServerSelectionCallback,
597
603
  ServerSelectionRequest,
598
604
  Topology,
@@ -2,7 +2,7 @@ import { promises as fs } from 'fs';
2
2
  import type { TcpNetConnectOpts } from 'net';
3
3
  import type { ConnectionOptions as TLSConnectionOptions, TLSSocketOptions } from 'tls';
4
4
 
5
- import { TopologyType } from '.';
5
+ import { type ServerCommandOptions, type TimeoutContext } from '.';
6
6
  import { type BSONSerializeOptions, type Document, resolveBSONOptions } from './bson';
7
7
  import { ChangeStream, type ChangeStreamDocument, type ChangeStreamOptions } from './change_stream';
8
8
  import type { AutoEncrypter, AutoEncryptionOptions } from './client-side-encryption/auto_encrypter';
@@ -16,11 +16,13 @@ import { AuthMechanism } from './cmap/auth/providers';
16
16
  import type { LEGAL_TCP_SOCKET_OPTIONS, LEGAL_TLS_SOCKET_OPTIONS } from './cmap/connect';
17
17
  import type { Connection } from './cmap/connection';
18
18
  import {
19
+ addContainerMetadata,
19
20
  type ClientMetadata,
20
21
  isDriverInfoEqual,
21
22
  makeClientMetadata
22
23
  } from './cmap/handshake/client_metadata';
23
24
  import type { CompressorName } from './cmap/wire_protocol/compression';
25
+ import { MongoDBResponse } from './cmap/wire_protocol/responses';
24
26
  import { parseOptions, resolveSRVRecord } from './connection_string';
25
27
  import { MONGO_CLIENT_EVENTS } from './constants';
26
28
  import { type AbstractCursor } from './cursor/abstract_cursor';
@@ -42,10 +44,11 @@ import {
42
44
  type ClientBulkWriteResult
43
45
  } from './operations/client_bulk_write/common';
44
46
  import { ClientBulkWriteExecutor } from './operations/client_bulk_write/executor';
45
- import { EndSessionsOperation } from './operations/end_sessions';
46
47
  import { executeOperation } from './operations/execute_operation';
48
+ import { AbstractOperation } from './operations/operation';
47
49
  import type { ReadConcern, ReadConcernLevel, ReadConcernLike } from './read_concern';
48
50
  import { ReadPreference, type ReadPreferenceMode } from './read_preference';
51
+ import { type AsyncDisposable, configureResourceManagement } from './resource_management';
49
52
  import type { ServerMonitoringMode } from './sdam/monitor';
50
53
  import type { TagSet } from './sdam/server_description';
51
54
  import { readPreferenceServerSelector } from './sdam/server_selection';
@@ -60,7 +63,7 @@ import {
60
63
  type HostAddress,
61
64
  hostMatchesWildcards,
62
65
  isHostMatch,
63
- type MongoDBNamespace,
66
+ MongoDBNamespace,
64
67
  noop,
65
68
  ns,
66
69
  resolveOptions,
@@ -405,12 +408,31 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
405
408
  * The consolidate, parsed, transformed and merged options.
406
409
  */
407
410
  public readonly options: Readonly<
408
- Omit<MongoOptions, 'monitorCommands' | 'ca' | 'crl' | 'key' | 'cert' | 'driverInfo'>
411
+ Omit<
412
+ MongoOptions,
413
+ | 'monitorCommands'
414
+ | 'ca'
415
+ | 'crl'
416
+ | 'key'
417
+ | 'cert'
418
+ | 'driverInfo'
419
+ | 'additionalDriverInfo'
420
+ | 'metadata'
421
+ | 'extendedMetadata'
422
+ >
409
423
  > &
410
- Pick<MongoOptions, 'monitorCommands' | 'ca' | 'crl' | 'key' | 'cert' | 'driverInfo'> & {
411
- /** @internal */
412
- metadata: Promise<ClientMetadata>;
413
- };
424
+ Pick<
425
+ MongoOptions,
426
+ | 'monitorCommands'
427
+ | 'ca'
428
+ | 'crl'
429
+ | 'key'
430
+ | 'cert'
431
+ | 'driverInfo'
432
+ | 'additionalDriverInfo'
433
+ | 'metadata'
434
+ | 'extendedMetadata'
435
+ >;
414
436
 
415
437
  private driverInfoList: DriverInfo[] = [];
416
438
 
@@ -463,10 +485,13 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
463
485
  }
464
486
 
465
487
  /**
488
+ * @beta
466
489
  * @experimental
467
490
  * An alias for {@link MongoClient.close|MongoClient.close()}.
468
491
  */
469
- async [Symbol.asyncDispose]() {
492
+ declare [Symbol.asyncDispose]: () => Promise<void>;
493
+ /** @internal */
494
+ async asyncDispose() {
470
495
  await this.close();
471
496
  }
472
497
 
@@ -481,9 +506,10 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
481
506
  if (isDuplicateDriverInfo) return;
482
507
 
483
508
  this.driverInfoList.push(driverInfo);
484
- this.options.metadata = makeClientMetadata(this.driverInfoList, this.options)
509
+ this.options.metadata = makeClientMetadata(this.driverInfoList, this.options);
510
+ this.options.extendedMetadata = addContainerMetadata(this.options.metadata)
485
511
  .then(undefined, squashError)
486
- .then(result => result ?? ({} as ClientMetadata)); // ensure Promise<Document>
512
+ .then(result => result ?? {}); // ensure Promise<Document>
487
513
  }
488
514
 
489
515
  /** @internal */
@@ -568,13 +594,20 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
568
594
  }
569
595
 
570
596
  /**
571
- * An optional method to verify a handful of assumptions that are generally useful at application boot-time before using a MongoClient.
572
- * For detailed information about the connect process see the MongoClient.connect static method documentation.
597
+ * Connect to MongoDB using a url
573
598
  *
574
- * @param url - The MongoDB connection string (supports `mongodb://` and `mongodb+srv://` schemes)
575
- * @param options - Optional configuration options for the client
599
+ * @remarks
600
+ * Calling `connect` is optional since the first operation you perform will call `connect` if it's needed.
601
+ * `timeoutMS` will bound the time any operation can take before throwing a timeout error.
602
+ * However, when the operation being run is automatically connecting your `MongoClient` the `timeoutMS` will not apply to the time taken to connect the MongoClient.
603
+ * This means the time to setup the `MongoClient` does not count against `timeoutMS`.
604
+ * If you are using `timeoutMS` we recommend connecting your client explicitly in advance of any operation to avoid this inconsistent execution time.
576
605
  *
577
- * @see https://www.mongodb.com/docs/manual/reference/connection-string/
606
+ * @remarks
607
+ * The driver will look up corresponding SRV and TXT records if the connection string starts with `mongodb+srv://`.
608
+ * If those look ups throw a DNS Timeout error, the driver will retry the look up once.
609
+ *
610
+ * @see docs.mongodb.org/manual/reference/connection-string/
578
611
  */
579
612
  async connect(): Promise<this> {
580
613
  if (this.connectionLock) {
@@ -762,12 +795,40 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
762
795
  return;
763
796
  }
764
797
 
765
- const supportsSessions =
766
- this.topology.description.type === TopologyType.LoadBalanced ||
767
- this.topology.description.logicalSessionTimeoutMinutes != null;
768
-
769
- if (supportsSessions) {
770
- await endSessions(this, this.topology);
798
+ // If we would attempt to select a server and get nothing back we short circuit
799
+ // to avoid the server selection timeout.
800
+ const selector = readPreferenceServerSelector(ReadPreference.primaryPreferred);
801
+ const topologyDescription = this.topology.description;
802
+ const serverDescriptions = Array.from(topologyDescription.servers.values());
803
+ const servers = selector(topologyDescription, serverDescriptions);
804
+ if (servers.length !== 0) {
805
+ const endSessions = Array.from(this.s.sessionPool.sessions, ({ id }) => id);
806
+ if (endSessions.length !== 0) {
807
+ try {
808
+ class EndSessionsOperation extends AbstractOperation<void> {
809
+ override ns = MongoDBNamespace.fromString('admin.$cmd');
810
+ override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
811
+ override buildCommand(_connection: Connection, _session?: ClientSession): Document {
812
+ return {
813
+ endSessions
814
+ };
815
+ }
816
+ override buildOptions(timeoutContext: TimeoutContext): ServerCommandOptions {
817
+ return {
818
+ timeoutContext,
819
+ readPreference: ReadPreference.primaryPreferred,
820
+ noResponse: true
821
+ };
822
+ }
823
+ override get commandName(): string {
824
+ return 'endSessions';
825
+ }
826
+ }
827
+ await executeOperation(this, new EndSessionsOperation());
828
+ } catch (error) {
829
+ squashError(error);
830
+ }
831
+ }
771
832
  }
772
833
 
773
834
  // clear out references to old topology
@@ -780,27 +841,6 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
780
841
  if (encrypter) {
781
842
  await encrypter.close(this);
782
843
  }
783
-
784
- async function endSessions(
785
- client: MongoClient,
786
- { description: topologyDescription }: Topology
787
- ) {
788
- // If we would attempt to select a server and get nothing back we short circuit
789
- // to avoid the server selection timeout.
790
- const selector = readPreferenceServerSelector(ReadPreference.primaryPreferred);
791
- const serverDescriptions = Array.from(topologyDescription.servers.values());
792
- const servers = selector(topologyDescription, serverDescriptions);
793
- if (servers.length !== 0) {
794
- const endSessions = Array.from(client.s.sessionPool.sessions, ({ id }) => id);
795
- if (endSessions.length !== 0) {
796
- try {
797
- await executeOperation(client, new EndSessionsOperation(endSessions));
798
- } catch (error) {
799
- squashError(error);
800
- }
801
- }
802
- }
803
- }
804
844
  }
805
845
 
806
846
  /**
@@ -828,35 +868,21 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
828
868
  }
829
869
 
830
870
  /**
831
- * Creates a new MongoClient instance and immediately connects it to MongoDB.
832
- * This convenience method combines `new MongoClient(url, options)` and `client.connect()` in a single step.
833
- *
834
- * Connect can be helpful to detect configuration issues early by validating:
835
- * - **DNS Resolution**: Verifies that SRV records and hostnames in the connection string resolve DNS entries
836
- * - **Network Connectivity**: Confirms that host addresses are reachable and ports are open
837
- * - **TLS Configuration**: Validates SSL/TLS certificates, CA files, and encryption settings are correct
838
- * - **Authentication**: Verifies that provided credentials are valid
839
- * - **Server Compatibility**: Ensures the MongoDB server version is supported by this driver version
840
- * - **Load Balancer Setup**: For load-balanced deployments, confirms the service is properly configured
841
- *
842
- * @returns A promise that resolves to the same MongoClient instance once connected
871
+ * Connect to MongoDB using a url
843
872
  *
844
873
  * @remarks
845
- * **Connection is Optional:** Calling `connect` is optional since any operation method (`find`, `insertOne`, etc.)
846
- * will automatically perform these same validation steps if the client is not already connected.
847
- * However, explicitly calling `connect` can make sense for:
848
- * - **Fail-fast Error Detection**: Non-transient connection issues (hostname unresolved, port refused connection) are discovered immediately rather than during your first operation
849
- * - **Predictable Performance**: Eliminates first connection overhead from your first database operation
874
+ * Calling `connect` is optional since the first operation you perform will call `connect` if it's needed.
875
+ * `timeoutMS` will bound the time any operation can take before throwing a timeout error.
876
+ * However, when the operation being run is automatically connecting your `MongoClient` the `timeoutMS` will not apply to the time taken to connect the MongoClient.
877
+ * This means the time to setup the `MongoClient` does not count against `timeoutMS`.
878
+ * If you are using `timeoutMS` we recommend connecting your client explicitly in advance of any operation to avoid this inconsistent execution time.
850
879
  *
851
880
  * @remarks
852
- * **Connection Pooling Impact:** Calling `connect` will populate the connection pool with one connection
853
- * to a server selected by the client's configured `readPreference` (defaults to primary).
881
+ * The programmatically provided options take precedence over the URI options.
854
882
  *
855
883
  * @remarks
856
- * **Timeout Behavior:** When using `timeoutMS`, the connection establishment time does not count against
857
- * the timeout for subsequent operations. This means `connect` runs without a `timeoutMS` limit, while
858
- * your database operations will still respect the configured timeout. If you need predictable operation
859
- * timing with `timeoutMS`, call `connect` explicitly before performing operations.
884
+ * The driver will look up corresponding SRV and TXT records if the connection string starts with `mongodb+srv://`.
885
+ * If those look ups throw a DNS Timeout error, the driver will retry the look up once.
860
886
  *
861
887
  * @see https://www.mongodb.com/docs/manual/reference/connection-string/
862
888
  */
@@ -1011,6 +1037,8 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
1011
1037
  }
1012
1038
  }
1013
1039
 
1040
+ configureResourceManagement(MongoClient.prototype);
1041
+
1014
1042
  /**
1015
1043
  * Parsed Mongo Client Options.
1016
1044
  *
@@ -1077,8 +1105,12 @@ export interface MongoOptions
1077
1105
  compressors: CompressorName[];
1078
1106
  writeConcern: WriteConcern;
1079
1107
  dbName: string;
1080
- /** @internal */
1081
- metadata: Promise<ClientMetadata>;
1108
+ /** @deprecated - Will be made internal in a future major release. */
1109
+ metadata: ClientMetadata;
1110
+ /** @deprecated - Will be made internal in a future major release. */
1111
+ extendedMetadata: Promise<Document>;
1112
+ /** @deprecated - Will be made internal in a future major release. */
1113
+ additionalDriverInfo: DriverInfo[];
1082
1114
  /** @internal */
1083
1115
  autoEncrypter?: AutoEncrypter;
1084
1116
  /** @internal */