mongodb 6.20.0-dev.20251009.sha.fb2824ff → 6.20.0-dev.20251011.sha.cc85ebf2

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.
@@ -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 { type ServerCommandOptions, type TimeoutContext } from '.';
5
+ import { TopologyType } 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,13 +16,11 @@ 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,
20
19
  type ClientMetadata,
21
20
  isDriverInfoEqual,
22
21
  makeClientMetadata
23
22
  } from './cmap/handshake/client_metadata';
24
23
  import type { CompressorName } from './cmap/wire_protocol/compression';
25
- import { MongoDBResponse } from './cmap/wire_protocol/responses';
26
24
  import { parseOptions, resolveSRVRecord } from './connection_string';
27
25
  import { MONGO_CLIENT_EVENTS } from './constants';
28
26
  import { type AbstractCursor } from './cursor/abstract_cursor';
@@ -44,8 +42,8 @@ import {
44
42
  type ClientBulkWriteResult
45
43
  } from './operations/client_bulk_write/common';
46
44
  import { ClientBulkWriteExecutor } from './operations/client_bulk_write/executor';
45
+ import { EndSessionsOperation } from './operations/end_sessions';
47
46
  import { executeOperation } from './operations/execute_operation';
48
- import { AbstractOperation } from './operations/operation';
49
47
  import type { ReadConcern, ReadConcernLevel, ReadConcernLike } from './read_concern';
50
48
  import { ReadPreference, type ReadPreferenceMode } from './read_preference';
51
49
  import type { ServerMonitoringMode } from './sdam/monitor';
@@ -62,7 +60,7 @@ import {
62
60
  type HostAddress,
63
61
  hostMatchesWildcards,
64
62
  isHostMatch,
65
- MongoDBNamespace,
63
+ type MongoDBNamespace,
66
64
  noop,
67
65
  ns,
68
66
  resolveOptions,
@@ -407,31 +405,12 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
407
405
  * The consolidate, parsed, transformed and merged options.
408
406
  */
409
407
  public readonly options: Readonly<
410
- Omit<
411
- MongoOptions,
412
- | 'monitorCommands'
413
- | 'ca'
414
- | 'crl'
415
- | 'key'
416
- | 'cert'
417
- | 'driverInfo'
418
- | 'additionalDriverInfo'
419
- | 'metadata'
420
- | 'extendedMetadata'
421
- >
408
+ Omit<MongoOptions, 'monitorCommands' | 'ca' | 'crl' | 'key' | 'cert' | 'driverInfo'>
422
409
  > &
423
- Pick<
424
- MongoOptions,
425
- | 'monitorCommands'
426
- | 'ca'
427
- | 'crl'
428
- | 'key'
429
- | 'cert'
430
- | 'driverInfo'
431
- | 'additionalDriverInfo'
432
- | 'metadata'
433
- | 'extendedMetadata'
434
- >;
410
+ Pick<MongoOptions, 'monitorCommands' | 'ca' | 'crl' | 'key' | 'cert' | 'driverInfo'> & {
411
+ /** @internal */
412
+ metadata: Promise<ClientMetadata>;
413
+ };
435
414
 
436
415
  private driverInfoList: DriverInfo[] = [];
437
416
 
@@ -502,10 +481,9 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
502
481
  if (isDuplicateDriverInfo) return;
503
482
 
504
483
  this.driverInfoList.push(driverInfo);
505
- this.options.metadata = makeClientMetadata(this.driverInfoList, this.options);
506
- this.options.extendedMetadata = addContainerMetadata(this.options.metadata)
484
+ this.options.metadata = makeClientMetadata(this.driverInfoList, this.options)
507
485
  .then(undefined, squashError)
508
- .then(result => result ?? {}); // ensure Promise<Document>
486
+ .then(result => result ?? ({} as ClientMetadata)); // ensure Promise<Document>
509
487
  }
510
488
 
511
489
  /** @internal */
@@ -590,20 +568,13 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
590
568
  }
591
569
 
592
570
  /**
593
- * Connect to MongoDB using a url
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.
594
573
  *
595
- * @remarks
596
- * Calling `connect` is optional since the first operation you perform will call `connect` if it's needed.
597
- * `timeoutMS` will bound the time any operation can take before throwing a timeout error.
598
- * However, when the operation being run is automatically connecting your `MongoClient` the `timeoutMS` will not apply to the time taken to connect the MongoClient.
599
- * This means the time to setup the `MongoClient` does not count against `timeoutMS`.
600
- * If you are using `timeoutMS` we recommend connecting your client explicitly in advance of any operation to avoid this inconsistent execution time.
574
+ * @param url - The MongoDB connection string (supports `mongodb://` and `mongodb+srv://` schemes)
575
+ * @param options - Optional configuration options for the client
601
576
  *
602
- * @remarks
603
- * The driver will look up corresponding SRV and TXT records if the connection string starts with `mongodb+srv://`.
604
- * If those look ups throw a DNS Timeout error, the driver will retry the look up once.
605
- *
606
- * @see docs.mongodb.org/manual/reference/connection-string/
577
+ * @see https://www.mongodb.com/docs/manual/reference/connection-string/
607
578
  */
608
579
  async connect(): Promise<this> {
609
580
  if (this.connectionLock) {
@@ -791,40 +762,12 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
791
762
  return;
792
763
  }
793
764
 
794
- // If we would attempt to select a server and get nothing back we short circuit
795
- // to avoid the server selection timeout.
796
- const selector = readPreferenceServerSelector(ReadPreference.primaryPreferred);
797
- const topologyDescription = this.topology.description;
798
- const serverDescriptions = Array.from(topologyDescription.servers.values());
799
- const servers = selector(topologyDescription, serverDescriptions);
800
- if (servers.length !== 0) {
801
- const endSessions = Array.from(this.s.sessionPool.sessions, ({ id }) => id);
802
- if (endSessions.length !== 0) {
803
- try {
804
- class EndSessionsOperation extends AbstractOperation<void> {
805
- override ns = MongoDBNamespace.fromString('admin.$cmd');
806
- override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
807
- override buildCommand(_connection: Connection, _session?: ClientSession): Document {
808
- return {
809
- endSessions
810
- };
811
- }
812
- override buildOptions(timeoutContext: TimeoutContext): ServerCommandOptions {
813
- return {
814
- timeoutContext,
815
- readPreference: ReadPreference.primaryPreferred,
816
- noResponse: true
817
- };
818
- }
819
- override get commandName(): string {
820
- return 'endSessions';
821
- }
822
- }
823
- await executeOperation(this, new EndSessionsOperation());
824
- } catch (error) {
825
- squashError(error);
826
- }
827
- }
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);
828
771
  }
829
772
 
830
773
  // clear out references to old topology
@@ -837,6 +780,27 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
837
780
  if (encrypter) {
838
781
  await encrypter.close(this);
839
782
  }
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
+ }
840
804
  }
841
805
 
842
806
  /**
@@ -864,21 +828,35 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
864
828
  }
865
829
 
866
830
  /**
867
- * Connect to MongoDB using a url
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
868
843
  *
869
844
  * @remarks
870
- * Calling `connect` is optional since the first operation you perform will call `connect` if it's needed.
871
- * `timeoutMS` will bound the time any operation can take before throwing a timeout error.
872
- * However, when the operation being run is automatically connecting your `MongoClient` the `timeoutMS` will not apply to the time taken to connect the MongoClient.
873
- * This means the time to setup the `MongoClient` does not count against `timeoutMS`.
874
- * If you are using `timeoutMS` we recommend connecting your client explicitly in advance of any operation to avoid this inconsistent execution time.
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
875
850
  *
876
851
  * @remarks
877
- * The programmatically provided options take precedence over the URI options.
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).
878
854
  *
879
855
  * @remarks
880
- * The driver will look up corresponding SRV and TXT records if the connection string starts with `mongodb+srv://`.
881
- * If those look ups throw a DNS Timeout error, the driver will retry the look up once.
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.
882
860
  *
883
861
  * @see https://www.mongodb.com/docs/manual/reference/connection-string/
884
862
  */
@@ -1099,12 +1077,8 @@ export interface MongoOptions
1099
1077
  compressors: CompressorName[];
1100
1078
  writeConcern: WriteConcern;
1101
1079
  dbName: string;
1102
- /** @deprecated - Will be made internal in a future major release. */
1103
- metadata: ClientMetadata;
1104
- /** @deprecated - Will be made internal in a future major release. */
1105
- extendedMetadata: Promise<Document>;
1106
- /** @deprecated - Will be made internal in a future major release. */
1107
- additionalDriverInfo: DriverInfo[];
1080
+ /** @internal */
1081
+ metadata: Promise<ClientMetadata>;
1108
1082
  /** @internal */
1109
1083
  autoEncrypter?: AutoEncrypter;
1110
1084
  /** @internal */
@@ -21,14 +21,6 @@ const AUTH_PROVIDERS = new Map<
21
21
  AuthMechanism.MONGODB_AWS,
22
22
  ({ AWS_CREDENTIAL_PROVIDER }) => new MongoDBAWS(AWS_CREDENTIAL_PROVIDER)
23
23
  ],
24
- [
25
- AuthMechanism.MONGODB_CR,
26
- () => {
27
- throw new MongoInvalidArgumentError(
28
- 'MONGODB-CR is no longer a supported auth mechanism in MongoDB 4.0+'
29
- );
30
- }
31
- ],
32
24
  [AuthMechanism.MONGODB_GSSAPI, () => new GSSAPI()],
33
25
  [AuthMechanism.MONGODB_OIDC, properties => new MongoDBOIDC(getWorkflow(properties))],
34
26
  [AuthMechanism.MONGODB_PLAIN, () => new Plain()],
@@ -0,0 +1,42 @@
1
+ import {
2
+ type ClientSession,
3
+ type Connection,
4
+ type ServerCommandOptions,
5
+ type ServerSessionId,
6
+ type TimeoutContext
7
+ } from '..';
8
+ import { type Document } from '../bson';
9
+ import { MongoDBResponse } from '../cmap/wire_protocol/responses';
10
+ import { ReadPreference } from '../read_preference';
11
+ import { MongoDBNamespace } from '../utils';
12
+ import { AbstractOperation } from './operation';
13
+
14
+ export class EndSessionsOperation extends AbstractOperation<void> {
15
+ override ns = MongoDBNamespace.fromString('admin.$cmd');
16
+ override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
17
+
18
+ private sessions: Array<ServerSessionId>;
19
+
20
+ constructor(sessions: Array<ServerSessionId>) {
21
+ super();
22
+ this.sessions = sessions;
23
+ }
24
+
25
+ override buildCommand(_connection: Connection, _session?: ClientSession): Document {
26
+ return {
27
+ endSessions: this.sessions
28
+ };
29
+ }
30
+
31
+ override buildOptions(timeoutContext: TimeoutContext): ServerCommandOptions {
32
+ return {
33
+ timeoutContext,
34
+ readPreference: ReadPreference.primaryPreferred,
35
+ noResponse: true
36
+ };
37
+ }
38
+
39
+ override get commandName(): string {
40
+ return 'endSessions';
41
+ }
42
+ }
@@ -150,8 +150,7 @@ export interface TopologyOptions extends BSONSerializeOptions, ServerOptions {
150
150
  /** Indicates that a client should directly connect to a node without attempting to discover its topology type */
151
151
  directConnection: boolean;
152
152
  loadBalanced: boolean;
153
- metadata: ClientMetadata;
154
- extendedMetadata: Promise<Document>;
153
+ metadata: Promise<ClientMetadata>;
155
154
  serverMonitoringMode: ServerMonitoringMode;
156
155
  /** MongoDB server API version */
157
156
  serverApi?: ServerApi;
@@ -466,7 +465,7 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
466
465
  );
467
466
 
468
467
  const skipPingOnConnect = this.s.options.__skipPingOnConnect === true;
469
- if (!skipPingOnConnect && this.s.credentials) {
468
+ if (!skipPingOnConnect) {
470
469
  const connection = await server.pool.checkOut({ timeoutContext: timeoutContext });
471
470
  server.pool.checkIn(connection);
472
471
  stateTransition(this, STATE_CONNECTED);
@@ -750,10 +749,6 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
750
749
  if (typeof callback === 'function') callback(undefined, true);
751
750
  }
752
751
 
753
- get clientMetadata(): ClientMetadata {
754
- return this.s.options.metadata;
755
- }
756
-
757
752
  isConnected(): boolean {
758
753
  return this.s.state === STATE_CONNECTED;
759
754
  }