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,5 +1,10 @@
1
1
  import { type AWSCredentials, getAwsCredentialProvider } from '../../deps';
2
2
  import { MongoAWSError } from '../../error';
3
+ import { request } from '../../utils';
4
+
5
+ const AWS_RELATIVE_URI = 'http://169.254.170.2';
6
+ const AWS_EC2_URI = 'http://169.254.169.254';
7
+ const AWS_EC2_PATH = '/latest/meta-data/iam/security-credentials';
3
8
 
4
9
  /**
5
10
  * @internal
@@ -19,9 +24,26 @@ export interface AWSTempCredentials {
19
24
  /** @public **/
20
25
  export type AWSCredentialProvider = () => Promise<AWSCredentials>;
21
26
 
22
- /** @internal */
23
- export class AWSSDKCredentialProvider {
27
+ /**
28
+ * @internal
29
+ *
30
+ * Fetches temporary AWS credentials.
31
+ */
32
+ export abstract class AWSTemporaryCredentialProvider {
33
+ abstract getCredentials(): Promise<AWSTempCredentials>;
24
34
  private static _awsSDK: ReturnType<typeof getAwsCredentialProvider>;
35
+ protected static get awsSDK() {
36
+ AWSTemporaryCredentialProvider._awsSDK ??= getAwsCredentialProvider();
37
+ return AWSTemporaryCredentialProvider._awsSDK;
38
+ }
39
+
40
+ static get isAWSSDKInstalled(): boolean {
41
+ return !('kModuleError' in AWSTemporaryCredentialProvider.awsSDK);
42
+ }
43
+ }
44
+
45
+ /** @internal */
46
+ export class AWSSDKCredentialProvider extends AWSTemporaryCredentialProvider {
25
47
  private _provider?: AWSCredentialProvider;
26
48
 
27
49
  /**
@@ -29,23 +51,20 @@ export class AWSSDKCredentialProvider {
29
51
  * @param credentialsProvider - The credentials provider.
30
52
  */
31
53
  constructor(credentialsProvider?: AWSCredentialProvider) {
54
+ super();
55
+
32
56
  if (credentialsProvider) {
33
57
  this._provider = credentialsProvider;
34
58
  }
35
59
  }
36
60
 
37
- static get awsSDK() {
38
- AWSSDKCredentialProvider._awsSDK ??= getAwsCredentialProvider();
39
- return AWSSDKCredentialProvider._awsSDK;
40
- }
41
-
42
61
  /**
43
62
  * The AWS SDK caches credentials automatically and handles refresh when the credentials have expired.
44
63
  * To ensure this occurs, we need to cache the `provider` returned by the AWS sdk and re-use it when fetching credentials.
45
64
  */
46
65
  private get provider(): () => Promise<AWSCredentials> {
47
- if ('kModuleError' in AWSSDKCredentialProvider.awsSDK) {
48
- throw AWSSDKCredentialProvider.awsSDK.kModuleError;
66
+ if ('kModuleError' in AWSTemporaryCredentialProvider.awsSDK) {
67
+ throw AWSTemporaryCredentialProvider.awsSDK.kModuleError;
49
68
  }
50
69
  if (this._provider) {
51
70
  return this._provider;
@@ -93,15 +112,15 @@ export class AWSSDKCredentialProvider {
93
112
 
94
113
  this._provider =
95
114
  awsRegionSettingsExist && useRegionalSts
96
- ? AWSSDKCredentialProvider.awsSDK.fromNodeProviderChain({
115
+ ? AWSTemporaryCredentialProvider.awsSDK.fromNodeProviderChain({
97
116
  clientConfig: { region: AWS_REGION }
98
117
  })
99
- : AWSSDKCredentialProvider.awsSDK.fromNodeProviderChain();
118
+ : AWSTemporaryCredentialProvider.awsSDK.fromNodeProviderChain();
100
119
 
101
120
  return this._provider;
102
121
  }
103
122
 
104
- async getCredentials(): Promise<AWSTempCredentials> {
123
+ override async getCredentials(): Promise<AWSTempCredentials> {
105
124
  /*
106
125
  * Creates a credential provider that will attempt to find credentials from the
107
126
  * following sources (listed in order of precedence):
@@ -125,3 +144,42 @@ export class AWSSDKCredentialProvider {
125
144
  }
126
145
  }
127
146
  }
147
+
148
+ /**
149
+ * @internal
150
+ * Fetches credentials manually (without the AWS SDK), as outlined in the [Obtaining Credentials](https://github.com/mongodb/specifications/blob/master/source/auth/auth.md#obtaining-credentials)
151
+ * section of the Auth spec.
152
+ */
153
+ export class LegacyAWSTemporaryCredentialProvider extends AWSTemporaryCredentialProvider {
154
+ override async getCredentials(): Promise<AWSTempCredentials> {
155
+ // If the environment variable AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
156
+ // is set then drivers MUST assume that it was set by an AWS ECS agent
157
+ if (process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI) {
158
+ return await request(
159
+ `${AWS_RELATIVE_URI}${process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI}`
160
+ );
161
+ }
162
+
163
+ // Otherwise assume we are on an EC2 instance
164
+
165
+ // get a token
166
+ const token = await request(`${AWS_EC2_URI}/latest/api/token`, {
167
+ method: 'PUT',
168
+ json: false,
169
+ headers: { 'X-aws-ec2-metadata-token-ttl-seconds': 30 }
170
+ });
171
+
172
+ // get role name
173
+ const roleName = await request(`${AWS_EC2_URI}/${AWS_EC2_PATH}`, {
174
+ json: false,
175
+ headers: { 'X-aws-ec2-metadata-token': token }
176
+ });
177
+
178
+ // get temp credentials
179
+ const creds = await request(`${AWS_EC2_URI}/${AWS_EC2_PATH}/${roleName}`, {
180
+ headers: { 'X-aws-ec2-metadata-token': token }
181
+ });
182
+
183
+ return creds;
184
+ }
185
+ }
@@ -58,7 +58,7 @@ export interface AuthMechanismProperties extends Document {
58
58
  SERVICE_NAME?: string;
59
59
  SERVICE_REALM?: string;
60
60
  CANONICALIZE_HOST_NAME?: GSSAPICanonicalizationValue;
61
- /** @internal */
61
+ /** @deprecated Will be removed in the next major version. */
62
62
  AWS_SESSION_TOKEN?: string;
63
63
  /** A user provided OIDC machine callback function. */
64
64
  OIDC_CALLBACK?: OIDCCallbackFunction;
@@ -135,6 +135,26 @@ export class MongoCredentials {
135
135
  this.mechanism = options.mechanism || AuthMechanism.MONGODB_DEFAULT;
136
136
  this.mechanismProperties = options.mechanismProperties || {};
137
137
 
138
+ if (this.mechanism.match(/MONGODB-AWS/i)) {
139
+ if (!this.username && process.env.AWS_ACCESS_KEY_ID) {
140
+ this.username = process.env.AWS_ACCESS_KEY_ID;
141
+ }
142
+
143
+ if (!this.password && process.env.AWS_SECRET_ACCESS_KEY) {
144
+ this.password = process.env.AWS_SECRET_ACCESS_KEY;
145
+ }
146
+
147
+ if (
148
+ this.mechanismProperties.AWS_SESSION_TOKEN == null &&
149
+ process.env.AWS_SESSION_TOKEN != null
150
+ ) {
151
+ this.mechanismProperties = {
152
+ ...this.mechanismProperties,
153
+ AWS_SESSION_TOKEN: process.env.AWS_SESSION_TOKEN
154
+ };
155
+ }
156
+ }
157
+
138
158
  if (this.mechanism === AuthMechanism.MONGODB_OIDC && !this.mechanismProperties.ALLOWED_HOSTS) {
139
159
  this.mechanismProperties = {
140
160
  ...this.mechanismProperties,
@@ -11,7 +11,9 @@ import { type AuthContext, AuthProvider } from './auth_provider';
11
11
  import {
12
12
  type AWSCredentialProvider,
13
13
  AWSSDKCredentialProvider,
14
- type AWSTempCredentials
14
+ type AWSTempCredentials,
15
+ AWSTemporaryCredentialProvider,
16
+ LegacyAWSTemporaryCredentialProvider
15
17
  } from './aws_temporary_credentials';
16
18
  import { MongoCredentials } from './mongo_credentials';
17
19
  import { AuthMechanism } from './providers';
@@ -32,11 +34,16 @@ interface AWSSaslContinuePayload {
32
34
  }
33
35
 
34
36
  export class MongoDBAWS extends AuthProvider {
35
- private credentialFetcher: AWSSDKCredentialProvider;
37
+ private credentialFetcher: AWSTemporaryCredentialProvider;
38
+ private credentialProvider?: AWSCredentialProvider;
36
39
 
37
40
  constructor(credentialProvider?: AWSCredentialProvider) {
38
41
  super();
39
- this.credentialFetcher = new AWSSDKCredentialProvider(credentialProvider);
42
+
43
+ this.credentialProvider = credentialProvider;
44
+ this.credentialFetcher = AWSTemporaryCredentialProvider.isAWSSDKInstalled
45
+ ? new AWSSDKCredentialProvider(credentialProvider)
46
+ : new LegacyAWSTemporaryCredentialProvider();
40
47
  }
41
48
 
42
49
  override async auth(authContext: AuthContext): Promise<void> {
@@ -56,10 +63,12 @@ export class MongoDBAWS extends AuthProvider {
56
63
  );
57
64
  }
58
65
 
59
- authContext.credentials = await makeTempCredentials(
60
- authContext.credentials,
61
- this.credentialFetcher
62
- );
66
+ if (!authContext.credentials.username) {
67
+ authContext.credentials = await makeTempCredentials(
68
+ authContext.credentials,
69
+ this.credentialFetcher
70
+ );
71
+ }
63
72
 
64
73
  const { credentials } = authContext;
65
74
 
@@ -153,7 +162,7 @@ export class MongoDBAWS extends AuthProvider {
153
162
 
154
163
  async function makeTempCredentials(
155
164
  credentials: MongoCredentials,
156
- awsCredentialFetcher: AWSSDKCredentialProvider
165
+ awsCredentialFetcher: AWSTemporaryCredentialProvider
157
166
  ): Promise<MongoCredentials> {
158
167
  function makeMongoCredentialsFromAWSTemp(creds: AWSTempCredentials) {
159
168
  // The AWS session token (creds.Token) may or may not be set.
@@ -1,6 +1,7 @@
1
1
  /** @public */
2
2
  export const AuthMechanism = Object.freeze({
3
3
  MONGODB_AWS: 'MONGODB-AWS',
4
+ MONGODB_CR: 'MONGODB-CR',
4
5
  MONGODB_DEFAULT: 'DEFAULT',
5
6
  MONGODB_GSSAPI: 'GSSAPI',
6
7
  MONGODB_PLAIN: 'PLAIN',
@@ -222,7 +222,7 @@ export async function prepareHandshakeDocument(
222
222
  const options = authContext.options;
223
223
  const compressors = options.compressors ? options.compressors : [];
224
224
  const { serverApi } = authContext.connection;
225
- const clientMetadata: Document = await options.metadata;
225
+ const clientMetadata: Document = await options.extendedMetadata;
226
226
 
227
227
  const handshakeDoc: HandshakeDocument = {
228
228
  [serverApi?.version || options.loadBalanced === true ? 'hello' : LEGACY_HELLO_COMMAND]: 1,
@@ -22,6 +22,7 @@ import {
22
22
  import {
23
23
  MongoCompatibilityError,
24
24
  MONGODB_ERROR_CODES,
25
+ MongoMissingDependencyError,
25
26
  MongoNetworkError,
26
27
  MongoNetworkTimeoutError,
27
28
  MongoOperationTimeoutError,
@@ -90,6 +91,8 @@ export interface CommandOptions extends BSONSerializeOptions {
90
91
  /** Session to use for the operation */
91
92
  session?: ClientSession;
92
93
  documentsReturnedIn?: string;
94
+ /** @deprecated Will be removed in the next major version. */
95
+ noResponse?: boolean;
93
96
  omitMaxTimeMS?: boolean;
94
97
 
95
98
  // TODO(NODE-2802): Currently the CommandOptions take a property willRetryWrite which is a hint
@@ -137,10 +140,11 @@ export interface ConnectionOptions
137
140
  tls: boolean;
138
141
  noDelay?: boolean;
139
142
  socketTimeoutMS?: number;
140
- /** @internal */
143
+ /** @deprecated Will be removed in the next major version */
141
144
  cancellationToken?: CancellationToken;
145
+ metadata: ClientMetadata;
142
146
  /** @internal */
143
- metadata: Promise<ClientMetadata>;
147
+ extendedMetadata: Promise<Document>;
144
148
  /** @internal */
145
149
  mongoLogger?: MongoLogger | undefined;
146
150
  }
@@ -466,7 +470,7 @@ export class Connection extends TypedEventEmitter<ConnectionEvents> {
466
470
  signal: options.signal
467
471
  });
468
472
 
469
- if (message.moreToCome) {
473
+ if (options.noResponse || message.moreToCome) {
470
474
  yield MongoDBResponse.empty;
471
475
  return;
472
476
  }
@@ -566,7 +570,11 @@ export class Connection extends TypedEventEmitter<ConnectionEvents> {
566
570
  new CommandSucceededEvent(
567
571
  this,
568
572
  message,
569
- message.moreToCome ? { ok: 1 } : (object ??= document.toObject(bsonOptions)),
573
+ options.noResponse
574
+ ? undefined
575
+ : message.moreToCome
576
+ ? { ok: 1 }
577
+ : (object ??= document.toObject(bsonOptions)),
570
578
  started,
571
579
  this.description.serverConnectionId
572
580
  )
@@ -709,15 +717,7 @@ export class Connection extends TypedEventEmitter<ConnectionEvents> {
709
717
  }
710
718
  }
711
719
 
712
- try {
713
- if (this.socket.write(buffer)) return;
714
- } catch (writeError) {
715
- const networkError = new MongoNetworkError('unexpected error writing to socket', {
716
- cause: writeError
717
- });
718
- this.onError(networkError);
719
- throw networkError;
720
- }
720
+ if (this.socket.write(buffer)) return;
721
721
 
722
722
  const drainEvent = once<void>(this.socket, 'drain', options);
723
723
  const timeout = options?.timeoutContext?.timeoutForSocketWrite;
@@ -870,7 +870,11 @@ export class CryptoConnection extends Connection {
870
870
  ): Promise<Document> {
871
871
  const { autoEncrypter } = this;
872
872
  if (!autoEncrypter) {
873
- throw new MongoRuntimeError('No AutoEncrypter available for encryption');
873
+ // TODO(NODE-6065): throw a MongoRuntimeError in Node V7
874
+ // @ts-expect-error No cause provided because there is no underlying error.
875
+ throw new MongoMissingDependencyError('No AutoEncrypter available for encryption', {
876
+ dependencyName: 'n/a'
877
+ });
874
878
  }
875
879
 
876
880
  const serverWireVersion = maxWireVersion(this);
@@ -97,6 +97,15 @@ export const PoolState = Object.freeze({
97
97
 
98
98
  type PoolState = (typeof PoolState)[keyof typeof PoolState];
99
99
 
100
+ /**
101
+ * @public
102
+ * @deprecated This interface is deprecated and will be removed in a future release as it is not used
103
+ * in the driver
104
+ */
105
+ export interface CloseOptions {
106
+ force?: boolean;
107
+ }
108
+
100
109
  /** @public */
101
110
  export type ConnectionPoolEvents = {
102
111
  connectionPoolCreated(event: ConnectionPoolCreatedEvent): void;
@@ -601,9 +610,9 @@ export class ConnectionPool extends TypedEventEmitter<ConnectionPoolEvents> {
601
610
  }
602
611
 
603
612
  private createConnection(callback: Callback<Connection>) {
604
- // Note that metadata may have changed on the client but have
605
- // been frozen here, so we pull the metadata promise always from the client
606
- // no matter what options were set at the construction of the pool.
613
+ // Note that metadata and extendedMetadata may have changed on the client but have
614
+ // been frozen here, so we pull the extendedMetadata promise always from the client
615
+ // no mattter what options were set at the construction of the pool.
607
616
  const connectOptions: ConnectionOptions = {
608
617
  ...this.options,
609
618
  id: this.connectionCounter.next().value,
@@ -611,7 +620,7 @@ export class ConnectionPool extends TypedEventEmitter<ConnectionPoolEvents> {
611
620
  cancellationToken: this.cancellationToken,
612
621
  mongoLogger: this.mongoLogger,
613
622
  authProviders: this.server.topology.client.s.authProviders,
614
- metadata: this.server.topology.client.options.metadata
623
+ extendedMetadata: this.server.topology.client.options.extendedMetadata
615
624
  };
616
625
 
617
626
  this.pending++;
@@ -56,7 +56,7 @@ export class PoolClearedError extends MongoNetworkError {
56
56
  super(errorMessage, pool.serverError ? { cause: pool.serverError } : undefined);
57
57
  this.address = pool.address;
58
58
 
59
- this.addErrorLabel(MongoErrorLabel.PoolRequestedRetry);
59
+ this.addErrorLabel(MongoErrorLabel.PoolRequstedRetry);
60
60
  }
61
61
 
62
62
  override get name(): string {
@@ -27,7 +27,8 @@ export function isDriverInfoEqual(info1: DriverInfo, info2: DriverInfo): boolean
27
27
  }
28
28
 
29
29
  /**
30
- * @internal
30
+ * @public
31
+ * @deprecated This interface will be made internal in the next major release.
31
32
  * @see https://github.com/mongodb/specifications/blob/master/source/mongodb-handshake/handshake.md#hello-command
32
33
  */
33
34
  export interface ClientMetadata {
@@ -47,17 +48,27 @@ export interface ClientMetadata {
47
48
  };
48
49
  /** FaaS environment information */
49
50
  env?: {
50
- name?: 'aws.lambda' | 'gcp.func' | 'azure.func' | 'vercel';
51
+ name: 'aws.lambda' | 'gcp.func' | 'azure.func' | 'vercel';
51
52
  timeout_sec?: Int32;
52
53
  memory_mb?: Int32;
53
54
  region?: string;
54
- container?: {
55
- runtime?: string;
56
- orchestrator?: string;
57
- };
55
+ url?: string;
58
56
  };
59
57
  }
60
58
 
59
+ /**
60
+ * @public
61
+ * @deprecated This interface will be made internal in the next major release.
62
+ */
63
+ export interface ClientMetadataOptions {
64
+ driverInfo?: {
65
+ name?: string;
66
+ version?: string;
67
+ platform?: string;
68
+ };
69
+ appName?: string;
70
+ }
71
+
61
72
  /** @internal */
62
73
  export class LimitedSizeDocument {
63
74
  private document = new Map();
@@ -105,10 +116,10 @@ type MakeClientMetadataOptions = Pick<MongoOptions, 'appName'>;
105
116
  * 3. Omit the `env` document entirely.
106
117
  * 4. Truncate `platform`. -- special we do not truncate this field
107
118
  */
108
- export async function makeClientMetadata(
119
+ export function makeClientMetadata(
109
120
  driverInfoList: DriverInfo[],
110
121
  { appName = '' }: MakeClientMetadataOptions
111
- ): Promise<ClientMetadata> {
122
+ ): ClientMetadata {
112
123
  const metadataDocument = new LimitedSizeDocument(512);
113
124
 
114
125
  // Add app name first, it must be sent
@@ -180,21 +191,19 @@ export async function makeClientMetadata(
180
191
  }
181
192
  }
182
193
  }
183
- return await addContainerMetadata(metadataDocument.toObject() as ClientMetadata);
194
+ return metadataDocument.toObject() as ClientMetadata;
184
195
  }
185
196
 
186
197
  let dockerPromise: Promise<boolean>;
187
- type ContainerMetadata = NonNullable<NonNullable<ClientMetadata['env']>['container']>;
188
198
  /** @internal */
189
- async function getContainerMetadata(): Promise<ContainerMetadata> {
199
+ async function getContainerMetadata() {
200
+ const containerMetadata: Record<string, any> = {};
190
201
  dockerPromise ??= fileIsAccessible('/.dockerenv');
191
202
  const isDocker = await dockerPromise;
192
203
 
193
204
  const { KUBERNETES_SERVICE_HOST = '' } = process.env;
194
205
  const isKubernetes = KUBERNETES_SERVICE_HOST.length > 0 ? true : false;
195
206
 
196
- const containerMetadata: ContainerMetadata = {};
197
-
198
207
  if (isDocker) containerMetadata.runtime = 'docker';
199
208
  if (isKubernetes) containerMetadata.orchestrator = 'kubernetes';
200
209
 
@@ -206,16 +215,15 @@ async function getContainerMetadata(): Promise<ContainerMetadata> {
206
215
  * Re-add each metadata value.
207
216
  * Attempt to add new env container metadata, but keep old data if it does not fit.
208
217
  */
209
- async function addContainerMetadata(originalMetadata: ClientMetadata): Promise<ClientMetadata> {
218
+ export async function addContainerMetadata(
219
+ originalMetadata: ClientMetadata
220
+ ): Promise<ClientMetadata> {
210
221
  const containerMetadata = await getContainerMetadata();
211
222
  if (Object.keys(containerMetadata).length === 0) return originalMetadata;
212
223
 
213
224
  const extendedMetadata = new LimitedSizeDocument(512);
214
225
 
215
- const extendedEnvMetadata: NonNullable<ClientMetadata['env']> = {
216
- ...originalMetadata?.env,
217
- container: containerMetadata
218
- };
226
+ const extendedEnvMetadata = { ...originalMetadata?.env, container: containerMetadata };
219
227
 
220
228
  for (const [key, val] of Object.entries(originalMetadata)) {
221
229
  if (key !== 'env') {
@@ -1,7 +1,5 @@
1
1
  export const MIN_SUPPORTED_SERVER_VERSION = '4.2';
2
2
  export const MAX_SUPPORTED_SERVER_VERSION = '8.2';
3
- export const MIN_SUPPORTED_SNAPSHOT_READS_WIRE_VERSION = 13;
4
- export const MIN_SUPPORTED_SNAPSHOT_READS_SERVER_VERSION = '5.0';
5
3
  export const MIN_SUPPORTED_WIRE_VERSION = 8;
6
4
  export const MAX_SUPPORTED_WIRE_VERSION = 27;
7
5
  export const MIN_SUPPORTED_QE_WIRE_VERSION = 21;
@@ -49,7 +49,7 @@ export function onData(
49
49
  /** Set to true only after event listeners have been removed. */
50
50
  let finished = false;
51
51
 
52
- const iterator: AsyncGenerator<Buffer> & AsyncDisposable = {
52
+ const iterator: AsyncGenerator<Buffer> = {
53
53
  next() {
54
54
  // First, we consume all unread events
55
55
  const value = unconsumedEvents.shift();
@@ -89,6 +89,7 @@ export function onData(
89
89
  return this;
90
90
  },
91
91
 
92
+ // Note this should currently not be used, but is required by the AsyncGenerator interface.
92
93
  async [Symbol.asyncDispose]() {
93
94
  await closeHandler();
94
95
  }
package/src/collection.ts CHANGED
@@ -546,7 +546,7 @@ export class Collection<TSchema extends Document = Document> {
546
546
  // Explicitly set the limit to 1 and singleBatch to true for all commands, per the spec.
547
547
  // noCursorTimeout must be unset as well as batchSize.
548
548
  // See: https://github.com/mongodb/specifications/blob/master/source/crud/crud.md#findone-api-details
549
- const { ...opts } = options;
549
+ const { batchSize: _batchSize, noCursorTimeout: _noCursorTimeout, ...opts } = options;
550
550
  opts.singleBatch = true;
551
551
  const cursor = this.find(filter, opts).limit(1);
552
552
  const result = await cursor.next();
@@ -7,7 +7,12 @@ import { MongoCredentials } from './cmap/auth/mongo_credentials';
7
7
  import { AUTH_MECHS_AUTH_SRC_EXTERNAL, AuthMechanism } from './cmap/auth/providers';
8
8
  import { Compressor, type CompressorName } from './cmap/wire_protocol/compression';
9
9
  import { Encrypter } from './encrypter';
10
- import { MongoAPIError, MongoInvalidArgumentError, MongoParseError } from './error';
10
+ import {
11
+ MongoAPIError,
12
+ MongoInvalidArgumentError,
13
+ MongoMissingCredentialsError,
14
+ MongoParseError
15
+ } from './error';
11
16
  import {
12
17
  MongoClient,
13
18
  type MongoClientOptions,
@@ -412,18 +417,10 @@ export function parseOptions(
412
417
  });
413
418
  }
414
419
 
415
- if (isAws) {
416
- const { username, password } = mongoOptions.credentials;
417
- if (username || password) {
418
- throw new MongoAPIError(
419
- 'username and password cannot be provided when using MONGODB-AWS. Credentials must be provided in a manner that can be read by the AWS SDK.'
420
- );
421
- }
422
- if (mongoOptions.credentials.mechanismProperties.AWS_SESSION_TOKEN) {
423
- throw new MongoAPIError(
424
- 'AWS_SESSION_TOKEN cannot be provided when using MONGODB-AWS. Credentials must be provided in a manner that can be read by the AWS SDK.'
425
- );
426
- }
420
+ if (isAws && mongoOptions.credentials.username && !mongoOptions.credentials.password) {
421
+ throw new MongoMissingCredentialsError(
422
+ `When using ${mongoOptions.credentials.mechanism} password must be set when a username is specified`
423
+ );
427
424
  }
428
425
 
429
426
  mongoOptions.credentials.validate();
@@ -1286,6 +1283,16 @@ export const OPTIONS = {
1286
1283
  secureProtocol: { type: 'any' },
1287
1284
  index: { type: 'any' },
1288
1285
  // Legacy options from v3 era
1286
+ useNewUrlParser: {
1287
+ type: 'boolean',
1288
+ deprecated:
1289
+ 'useNewUrlParser has no effect since Node.js Driver version 4.0.0 and will be removed in the next major version'
1290
+ } as OptionDescriptor,
1291
+ useUnifiedTopology: {
1292
+ type: 'boolean',
1293
+ deprecated:
1294
+ 'useUnifiedTopology has no effect since Node.js Driver version 4.0.0 and will be removed in the next major version'
1295
+ } as OptionDescriptor,
1289
1296
  __skipPingOnConnect: { type: 'boolean' }
1290
1297
  } as Record<keyof MongoClientOptions, OptionDescriptor>;
1291
1298