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.
- package/README.md +11 -11
- package/lib/beta.d.ts +9229 -0
- package/lib/beta.js +21 -0
- package/lib/beta.js.map +1 -0
- package/lib/bulk/common.js +9 -7
- package/lib/bulk/common.js.map +1 -1
- package/lib/change_stream.js +38 -84
- package/lib/change_stream.js.map +1 -1
- package/lib/client-side-encryption/auto_encrypter.js +4 -2
- package/lib/client-side-encryption/auto_encrypter.js.map +1 -1
- package/lib/client-side-encryption/client_encryption.js +3 -2
- package/lib/client-side-encryption/client_encryption.js.map +1 -1
- package/lib/client-side-encryption/crypto_callbacks.js +81 -0
- package/lib/client-side-encryption/crypto_callbacks.js.map +1 -0
- package/lib/client-side-encryption/errors.js +1 -3
- package/lib/client-side-encryption/errors.js.map +1 -1
- package/lib/client-side-encryption/mongocryptd_manager.js +1 -1
- package/lib/client-side-encryption/mongocryptd_manager.js.map +1 -1
- package/lib/cmap/auth/aws_temporary_credentials.js +58 -10
- package/lib/cmap/auth/aws_temporary_credentials.js.map +1 -1
- package/lib/cmap/auth/mongo_credentials.js +15 -0
- package/lib/cmap/auth/mongo_credentials.js.map +1 -1
- package/lib/cmap/auth/mongodb_aws.js +7 -2
- package/lib/cmap/auth/mongodb_aws.js.map +1 -1
- package/lib/cmap/auth/providers.js +1 -0
- package/lib/cmap/auth/providers.js.map +1 -1
- package/lib/cmap/connect.js +1 -1
- package/lib/cmap/connect.js.map +1 -1
- package/lib/cmap/connection.js +27 -28
- package/lib/cmap/connection.js.map +1 -1
- package/lib/cmap/connection_pool.js +59 -59
- package/lib/cmap/connection_pool.js.map +1 -1
- package/lib/cmap/errors.js +1 -1
- package/lib/cmap/errors.js.map +1 -1
- package/lib/cmap/handshake/client_metadata.js +5 -7
- package/lib/cmap/handshake/client_metadata.js.map +1 -1
- package/lib/cmap/metrics.js +3 -3
- package/lib/cmap/metrics.js.map +1 -1
- package/lib/cmap/wire_protocol/constants.js +1 -3
- package/lib/cmap/wire_protocol/constants.js.map +1 -1
- package/lib/cmap/wire_protocol/on_data.js +1 -0
- package/lib/cmap/wire_protocol/on_data.js.map +1 -1
- package/lib/cmap/wire_protocol/responses.js +2 -2
- package/lib/cmap/wire_protocol/responses.js.map +1 -1
- package/lib/collection.js +1 -1
- package/lib/collection.js.map +1 -1
- package/lib/connection_string.js +10 -8
- package/lib/connection_string.js.map +1 -1
- package/lib/cursor/abstract_cursor.js +34 -17
- package/lib/cursor/abstract_cursor.js.map +1 -1
- package/lib/cursor/change_stream_cursor.js +2 -2
- package/lib/cursor/change_stream_cursor.js.map +1 -1
- package/lib/cursor/find_cursor.js +26 -37
- package/lib/cursor/find_cursor.js.map +1 -1
- package/lib/cursor/run_command_cursor.js +1 -1
- package/lib/cursor/run_command_cursor.js.map +1 -1
- package/lib/db.js +6 -6
- package/lib/db.js.map +1 -1
- package/lib/error.js +2 -2
- package/lib/error.js.map +1 -1
- package/lib/gridfs/download.js +5 -5
- package/lib/gridfs/download.js.map +1 -1
- package/lib/gridfs/index.js +9 -9
- package/lib/gridfs/index.js.map +1 -1
- package/lib/gridfs/upload.js +8 -2
- package/lib/gridfs/upload.js.map +1 -1
- package/lib/index.js +4 -2
- package/lib/index.js.map +1 -1
- package/lib/mongo_client.js +67 -58
- package/lib/mongo_client.js.map +1 -1
- package/lib/mongo_client_auth_providers.js +6 -0
- package/lib/mongo_client_auth_providers.js.map +1 -1
- package/lib/mongo_logger.js.map +1 -1
- package/lib/mongo_types.js +2 -1
- package/lib/mongo_types.js.map +1 -1
- package/lib/operations/aggregate.js +3 -0
- package/lib/operations/aggregate.js.map +1 -1
- package/lib/operations/command.js.map +1 -1
- package/lib/operations/create_collection.js +1 -0
- package/lib/operations/create_collection.js.map +1 -1
- package/lib/operations/drop.js +9 -8
- package/lib/operations/drop.js.map +1 -1
- package/lib/operations/execute_operation.js +1 -3
- package/lib/operations/execute_operation.js.map +1 -1
- package/lib/operations/find.js.map +1 -1
- package/lib/read_preference.js +14 -10
- package/lib/read_preference.js.map +1 -1
- package/lib/resource_management.js +58 -0
- package/lib/resource_management.js.map +1 -0
- package/lib/sdam/server.js +14 -14
- package/lib/sdam/server.js.map +1 -1
- package/lib/sdam/srv_polling.js +2 -2
- package/lib/sdam/srv_polling.js.map +1 -1
- package/lib/sdam/topology.js +68 -24
- package/lib/sdam/topology.js.map +1 -1
- package/lib/sessions.js +4 -5
- package/lib/sessions.js.map +1 -1
- package/lib/transactions.js +13 -2
- package/lib/transactions.js.map +1 -1
- package/lib/utils.js +14 -0
- package/lib/utils.js.map +1 -1
- package/mongodb.d.ts +244 -72
- package/package.json +20 -17
- package/src/beta.ts +22 -0
- package/src/bulk/common.ts +11 -9
- package/src/change_stream.ts +37 -85
- package/src/client-side-encryption/auto_encrypter.ts +12 -6
- package/src/client-side-encryption/client_encryption.ts +6 -5
- package/src/client-side-encryption/crypto_callbacks.ts +87 -0
- package/src/client-side-encryption/errors.ts +0 -3
- package/src/cmap/auth/aws_temporary_credentials.ts +70 -12
- package/src/cmap/auth/mongo_credentials.ts +21 -1
- package/src/cmap/auth/mongodb_aws.ts +17 -8
- package/src/cmap/auth/providers.ts +1 -0
- package/src/cmap/connect.ts +1 -1
- package/src/cmap/connection.ts +18 -14
- package/src/cmap/connection_pool.ts +13 -4
- package/src/cmap/errors.ts +1 -1
- package/src/cmap/handshake/client_metadata.ts +26 -18
- package/src/cmap/wire_protocol/constants.ts +0 -2
- package/src/cmap/wire_protocol/on_data.ts +2 -1
- package/src/collection.ts +1 -1
- package/src/connection_string.ts +20 -13
- package/src/cursor/abstract_cursor.ts +52 -12
- package/src/cursor/change_stream_cursor.ts +2 -2
- package/src/cursor/find_cursor.ts +27 -40
- package/src/cursor/run_command_cursor.ts +1 -1
- package/src/error.ts +2 -2
- package/src/gridfs/download.ts +4 -0
- package/src/gridfs/upload.ts +22 -0
- package/src/index.ts +8 -2
- package/src/mongo_client.ts +100 -68
- package/src/mongo_client_auth_providers.ts +8 -0
- package/src/mongo_logger.ts +1 -1
- package/src/mongo_types.ts +2 -1
- package/src/operations/aggregate.ts +6 -0
- package/src/operations/command.ts +12 -0
- package/src/operations/create_collection.ts +3 -0
- package/src/operations/drop.ts +11 -9
- package/src/operations/execute_operation.ts +2 -6
- package/src/operations/find.ts +11 -2
- package/src/read_preference.ts +9 -0
- package/src/resource_management.ts +74 -0
- package/src/sdam/topology.ts +60 -2
- package/src/sessions.ts +8 -2
- package/src/transactions.ts +17 -2
- package/src/utils.ts +18 -0
- package/tsconfig.json +7 -5
- package/lib/operations/end_sessions.js +0 -34
- package/lib/operations/end_sessions.js.map +0 -1
- 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
|
-
/**
|
|
23
|
-
|
|
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
|
|
48
|
-
throw
|
|
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
|
-
?
|
|
115
|
+
? AWSTemporaryCredentialProvider.awsSDK.fromNodeProviderChain({
|
|
97
116
|
clientConfig: { region: AWS_REGION }
|
|
98
117
|
})
|
|
99
|
-
:
|
|
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
|
-
/** @
|
|
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:
|
|
37
|
+
private credentialFetcher: AWSTemporaryCredentialProvider;
|
|
38
|
+
private credentialProvider?: AWSCredentialProvider;
|
|
36
39
|
|
|
37
40
|
constructor(credentialProvider?: AWSCredentialProvider) {
|
|
38
41
|
super();
|
|
39
|
-
|
|
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
|
|
60
|
-
authContext.credentials
|
|
61
|
-
|
|
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:
|
|
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.
|
package/src/cmap/connect.ts
CHANGED
|
@@ -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.
|
|
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,
|
package/src/cmap/connection.ts
CHANGED
|
@@ -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
|
-
/** @
|
|
143
|
+
/** @deprecated Will be removed in the next major version */
|
|
141
144
|
cancellationToken?: CancellationToken;
|
|
145
|
+
metadata: ClientMetadata;
|
|
142
146
|
/** @internal */
|
|
143
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
606
|
-
// no
|
|
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
|
-
|
|
623
|
+
extendedMetadata: this.server.topology.client.options.extendedMetadata
|
|
615
624
|
};
|
|
616
625
|
|
|
617
626
|
this.pending++;
|
package/src/cmap/errors.ts
CHANGED
|
@@ -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.
|
|
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
|
-
* @
|
|
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
|
|
51
|
+
name: 'aws.lambda' | 'gcp.func' | 'azure.func' | 'vercel';
|
|
51
52
|
timeout_sec?: Int32;
|
|
52
53
|
memory_mb?: Int32;
|
|
53
54
|
region?: string;
|
|
54
|
-
|
|
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
|
|
119
|
+
export function makeClientMetadata(
|
|
109
120
|
driverInfoList: DriverInfo[],
|
|
110
121
|
{ appName = '' }: MakeClientMetadataOptions
|
|
111
|
-
):
|
|
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
|
|
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()
|
|
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(
|
|
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
|
|
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>
|
|
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();
|
package/src/connection_string.ts
CHANGED
|
@@ -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 {
|
|
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
|
-
|
|
417
|
-
|
|
418
|
-
|
|
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
|
|