mongodb 6.14.2 → 6.15.0-dev.20250320.sha.af30db93

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 (40) hide show
  1. package/README.md +8 -12
  2. package/lib/beta.d.ts +57 -0
  3. package/lib/client-side-encryption/auto_encrypter.js +5 -1
  4. package/lib/client-side-encryption/auto_encrypter.js.map +1 -1
  5. package/lib/client-side-encryption/client_encryption.js +5 -1
  6. package/lib/client-side-encryption/client_encryption.js.map +1 -1
  7. package/lib/client-side-encryption/providers/aws.js +2 -2
  8. package/lib/client-side-encryption/providers/aws.js.map +1 -1
  9. package/lib/client-side-encryption/providers/index.js +2 -2
  10. package/lib/client-side-encryption/providers/index.js.map +1 -1
  11. package/lib/cmap/auth/aws_temporary_credentials.js +10 -0
  12. package/lib/cmap/auth/aws_temporary_credentials.js.map +1 -1
  13. package/lib/cmap/auth/mongo_credentials.js.map +1 -1
  14. package/lib/cmap/auth/mongodb_aws.js +3 -2
  15. package/lib/cmap/auth/mongodb_aws.js.map +1 -1
  16. package/lib/cursor/abstract_cursor.js +13 -2
  17. package/lib/cursor/abstract_cursor.js.map +1 -1
  18. package/lib/index.js +0 -1
  19. package/lib/index.js.map +1 -1
  20. package/lib/mongo_client_auth_providers.js +24 -27
  21. package/lib/mongo_client_auth_providers.js.map +1 -1
  22. package/lib/sdam/server.js +6 -4
  23. package/lib/sdam/server.js.map +1 -1
  24. package/lib/timeout.js +6 -1
  25. package/lib/timeout.js.map +1 -1
  26. package/mongodb.d.ts +57 -0
  27. package/package.json +2 -2
  28. package/src/client-side-encryption/auto_encrypter.ts +17 -2
  29. package/src/client-side-encryption/client_encryption.ts +18 -1
  30. package/src/client-side-encryption/providers/aws.ts +9 -3
  31. package/src/client-side-encryption/providers/index.ts +15 -2
  32. package/src/cmap/auth/aws_temporary_credentials.ts +17 -1
  33. package/src/cmap/auth/mongo_credentials.ts +28 -0
  34. package/src/cmap/auth/mongodb_aws.ts +6 -2
  35. package/src/cursor/abstract_cursor.ts +49 -40
  36. package/src/deps.ts +2 -2
  37. package/src/index.ts +3 -1
  38. package/src/mongo_client_auth_providers.ts +26 -29
  39. package/src/sdam/server.ts +7 -4
  40. package/src/timeout.ts +8 -2
@@ -1146,50 +1146,59 @@ class ReadableCursorStream extends Readable {
1146
1146
  return;
1147
1147
  }
1148
1148
 
1149
- this._cursor.next().then(
1150
- result => {
1151
- if (result == null) {
1152
- this.push(null);
1153
- } else if (this.destroyed) {
1154
- this._cursor.close().then(undefined, squashError);
1155
- } else {
1156
- if (this.push(result)) {
1157
- return this._readNext();
1149
+ this._cursor
1150
+ .next()
1151
+ .then(
1152
+ // result from next()
1153
+ result => {
1154
+ if (result == null) {
1155
+ this.push(null);
1156
+ } else if (this.destroyed) {
1157
+ this._cursor.close().then(undefined, squashError);
1158
+ } else {
1159
+ if (this.push(result)) {
1160
+ return this._readNext();
1161
+ }
1162
+
1163
+ this._readInProgress = false;
1164
+ }
1165
+ },
1166
+ // error from next()
1167
+ err => {
1168
+ // NOTE: This is questionable, but we have a test backing the behavior. It seems the
1169
+ // desired behavior is that a stream ends cleanly when a user explicitly closes
1170
+ // a client during iteration. Alternatively, we could do the "right" thing and
1171
+ // propagate the error message by removing this special case.
1172
+ if (err.message.match(/server is closed/)) {
1173
+ this._cursor.close().then(undefined, squashError);
1174
+ return this.push(null);
1158
1175
  }
1159
1176
 
1160
- this._readInProgress = false;
1161
- }
1162
- },
1163
- err => {
1164
- // NOTE: This is questionable, but we have a test backing the behavior. It seems the
1165
- // desired behavior is that a stream ends cleanly when a user explicitly closes
1166
- // a client during iteration. Alternatively, we could do the "right" thing and
1167
- // propagate the error message by removing this special case.
1168
- if (err.message.match(/server is closed/)) {
1169
- this._cursor.close().then(undefined, squashError);
1170
- return this.push(null);
1171
- }
1177
+ // NOTE: This is also perhaps questionable. The rationale here is that these errors tend
1178
+ // to be "operation was interrupted", where a cursor has been closed but there is an
1179
+ // active getMore in-flight. This used to check if the cursor was killed but once
1180
+ // that changed to happen in cleanup legitimate errors would not destroy the
1181
+ // stream. There are change streams test specifically test these cases.
1182
+ if (err.message.match(/operation was interrupted/)) {
1183
+ return this.push(null);
1184
+ }
1172
1185
 
1173
- // NOTE: This is also perhaps questionable. The rationale here is that these errors tend
1174
- // to be "operation was interrupted", where a cursor has been closed but there is an
1175
- // active getMore in-flight. This used to check if the cursor was killed but once
1176
- // that changed to happen in cleanup legitimate errors would not destroy the
1177
- // stream. There are change streams test specifically test these cases.
1178
- if (err.message.match(/operation was interrupted/)) {
1179
- return this.push(null);
1186
+ // NOTE: The two above checks on the message of the error will cause a null to be pushed
1187
+ // to the stream, thus closing the stream before the destroy call happens. This means
1188
+ // that either of those error messages on a change stream will not get a proper
1189
+ // 'error' event to be emitted (the error passed to destroy). Change stream resumability
1190
+ // relies on that error event to be emitted to create its new cursor and thus was not
1191
+ // working on 4.4 servers because the error emitted on failover was "interrupted at
1192
+ // shutdown" while on 5.0+ it is "The server is in quiesce mode and will shut down".
1193
+ // See NODE-4475.
1194
+ return this.destroy(err);
1180
1195
  }
1181
-
1182
- // NOTE: The two above checks on the message of the error will cause a null to be pushed
1183
- // to the stream, thus closing the stream before the destroy call happens. This means
1184
- // that either of those error messages on a change stream will not get a proper
1185
- // 'error' event to be emitted (the error passed to destroy). Change stream resumability
1186
- // relies on that error event to be emitted to create its new cursor and thus was not
1187
- // working on 4.4 servers because the error emitted on failover was "interrupted at
1188
- // shutdown" while on 5.0+ it is "The server is in quiesce mode and will shut down".
1189
- // See NODE-4475.
1190
- return this.destroy(err);
1191
- }
1192
- );
1196
+ )
1197
+ // if either of the above handlers throw
1198
+ .catch(error => {
1199
+ this._readInProgress = false;
1200
+ this.destroy(error);
1201
+ });
1193
1202
  }
1194
1203
  }
1195
1204
 
package/src/deps.ts CHANGED
@@ -78,14 +78,14 @@ export function getZstdLibrary(): ZStandardLib | { kModuleError: MongoMissingDep
78
78
  }
79
79
 
80
80
  /**
81
- * @internal
81
+ * @public
82
82
  * Copy of the AwsCredentialIdentityProvider interface from [`smithy/types`](https://socket.dev/npm/package/\@smithy/types/files/1.1.1/dist-types/identity/awsCredentialIdentity.d.ts),
83
83
  * the return type of the aws-sdk's `fromNodeProviderChain().provider()`.
84
84
  */
85
85
  export interface AWSCredentials {
86
86
  accessKeyId: string;
87
87
  secretAccessKey: string;
88
- sessionToken: string;
88
+ sessionToken?: string;
89
89
  expiration?: Date;
90
90
  }
91
91
 
package/src/index.ts CHANGED
@@ -128,10 +128,11 @@ export { ReadPreferenceMode } from './read_preference';
128
128
  export { ServerType, TopologyType } from './sdam/common';
129
129
 
130
130
  // Helper classes
131
+ export type { AWSCredentialProvider } from './cmap/auth/aws_temporary_credentials';
132
+ export type { AWSCredentials } from './deps';
131
133
  export { ReadConcern } from './read_concern';
132
134
  export { ReadPreference } from './read_preference';
133
135
  export { WriteConcern } from './write_concern';
134
-
135
136
  // events
136
137
  export {
137
138
  CommandFailedEvent,
@@ -255,6 +256,7 @@ export type {
255
256
  AWSKMSProviderConfiguration,
256
257
  AzureKMSProviderConfiguration,
257
258
  ClientEncryptionDataKeyProvider,
259
+ CredentialProviders,
258
260
  GCPKMSProviderConfiguration,
259
261
  KMIPKMSProviderConfiguration,
260
262
  KMSProviders,
@@ -13,8 +13,14 @@ import { X509 } from './cmap/auth/x509';
13
13
  import { MongoInvalidArgumentError } from './error';
14
14
 
15
15
  /** @internal */
16
- const AUTH_PROVIDERS = new Map<AuthMechanism | string, (workflow?: Workflow) => AuthProvider>([
17
- [AuthMechanism.MONGODB_AWS, () => new MongoDBAWS()],
16
+ const AUTH_PROVIDERS = new Map<
17
+ AuthMechanism | string,
18
+ (authMechanismProperties: AuthMechanismProperties) => AuthProvider
19
+ >([
20
+ [
21
+ AuthMechanism.MONGODB_AWS,
22
+ ({ AWS_CREDENTIAL_PROVIDER }) => new MongoDBAWS(AWS_CREDENTIAL_PROVIDER)
23
+ ],
18
24
  [
19
25
  AuthMechanism.MONGODB_CR,
20
26
  () => {
@@ -24,7 +30,7 @@ const AUTH_PROVIDERS = new Map<AuthMechanism | string, (workflow?: Workflow) =>
24
30
  }
25
31
  ],
26
32
  [AuthMechanism.MONGODB_GSSAPI, () => new GSSAPI()],
27
- [AuthMechanism.MONGODB_OIDC, (workflow?: Workflow) => new MongoDBOIDC(workflow)],
33
+ [AuthMechanism.MONGODB_OIDC, properties => new MongoDBOIDC(getWorkflow(properties))],
28
34
  [AuthMechanism.MONGODB_PLAIN, () => new Plain()],
29
35
  [AuthMechanism.MONGODB_SCRAM_SHA1, () => new ScramSHA1()],
30
36
  [AuthMechanism.MONGODB_SCRAM_SHA256, () => new ScramSHA256()],
@@ -62,37 +68,28 @@ export class MongoClientAuthProviders {
62
68
  throw new MongoInvalidArgumentError(`authMechanism ${name} not supported`);
63
69
  }
64
70
 
65
- let provider;
66
- if (name === AuthMechanism.MONGODB_OIDC) {
67
- provider = providerFunction(this.getWorkflow(authMechanismProperties));
68
- } else {
69
- provider = providerFunction();
70
- }
71
-
71
+ const provider = providerFunction(authMechanismProperties);
72
72
  this.existingProviders.set(name, provider);
73
73
  return provider;
74
74
  }
75
+ }
75
76
 
76
- /**
77
- * Gets either a device workflow or callback workflow.
78
- */
79
- getWorkflow(authMechanismProperties: AuthMechanismProperties): Workflow {
80
- if (authMechanismProperties.OIDC_HUMAN_CALLBACK) {
81
- return new HumanCallbackWorkflow(
82
- new TokenCache(),
83
- authMechanismProperties.OIDC_HUMAN_CALLBACK
77
+ /**
78
+ * Gets either a device workflow or callback workflow.
79
+ */
80
+ function getWorkflow(authMechanismProperties: AuthMechanismProperties): Workflow {
81
+ if (authMechanismProperties.OIDC_HUMAN_CALLBACK) {
82
+ return new HumanCallbackWorkflow(new TokenCache(), authMechanismProperties.OIDC_HUMAN_CALLBACK);
83
+ } else if (authMechanismProperties.OIDC_CALLBACK) {
84
+ return new AutomatedCallbackWorkflow(new TokenCache(), authMechanismProperties.OIDC_CALLBACK);
85
+ } else {
86
+ const environment = authMechanismProperties.ENVIRONMENT;
87
+ const workflow = OIDC_WORKFLOWS.get(environment)?.();
88
+ if (!workflow) {
89
+ throw new MongoInvalidArgumentError(
90
+ `Could not load workflow for environment ${authMechanismProperties.ENVIRONMENT}`
84
91
  );
85
- } else if (authMechanismProperties.OIDC_CALLBACK) {
86
- return new AutomatedCallbackWorkflow(new TokenCache(), authMechanismProperties.OIDC_CALLBACK);
87
- } else {
88
- const environment = authMechanismProperties.ENVIRONMENT;
89
- const workflow = OIDC_WORKFLOWS.get(environment)?.();
90
- if (!workflow) {
91
- throw new MongoInvalidArgumentError(
92
- `Could not load workflow for environment ${authMechanismProperties.ENVIRONMENT}`
93
- );
94
- }
95
- return workflow;
96
92
  }
93
+ return workflow;
97
94
  }
98
95
  }
@@ -48,6 +48,7 @@ import {
48
48
  maxWireVersion,
49
49
  type MongoDBNamespace,
50
50
  noop,
51
+ squashError,
51
52
  supportsRetryableWrites
52
53
  } from '../utils';
53
54
  import { throwIfWriteConcernError } from '../write_concern';
@@ -345,9 +346,10 @@ export class Server extends TypedEventEmitter<ServerEvents> {
345
346
  operationError instanceof MongoError &&
346
347
  operationError.code === MONGODB_ERROR_CODES.Reauthenticate
347
348
  ) {
348
- reauthPromise = this.pool.reauthenticate(conn).catch(error => {
349
+ reauthPromise = this.pool.reauthenticate(conn);
350
+ reauthPromise.then(undefined, error => {
349
351
  reauthPromise = null;
350
- throw error;
352
+ squashError(error);
351
353
  });
352
354
 
353
355
  await abortable(reauthPromise, options);
@@ -368,9 +370,10 @@ export class Server extends TypedEventEmitter<ServerEvents> {
368
370
  if (session?.pinnedConnection !== conn) {
369
371
  if (reauthPromise != null) {
370
372
  // The reauth promise only exists if it hasn't thrown.
371
- void reauthPromise.finally(() => {
373
+ const checkBackIn = () => {
372
374
  this.pool.checkIn(conn);
373
- });
375
+ };
376
+ void reauthPromise.then(checkBackIn, checkBackIn);
374
377
  } else {
375
378
  this.pool.checkIn(conn);
376
379
  }
package/src/timeout.ts CHANGED
@@ -3,7 +3,7 @@ import { clearTimeout, setTimeout } from 'timers';
3
3
  import { type Document } from './bson';
4
4
  import { MongoInvalidArgumentError, MongoOperationTimeoutError, MongoRuntimeError } from './error';
5
5
  import { type ClientSession } from './sessions';
6
- import { csotMin, noop } from './utils';
6
+ import { csotMin, noop, squashError } from './utils';
7
7
 
8
8
  /** @internal */
9
9
  export class TimeoutError extends Error {
@@ -102,7 +102,13 @@ export class Timeout extends Promise<never> {
102
102
  }
103
103
 
104
104
  throwIfExpired(): void {
105
- if (this.timedOut) throw new TimeoutError('Timed out', { duration: this.duration });
105
+ if (this.timedOut) {
106
+ // This method is invoked when someone wants to throw immediately instead of await the result of this promise
107
+ // Since they won't be handling the rejection from the promise (because we're about to throw here)
108
+ // attach handling to prevent this from bubbling up to Node.js
109
+ this.then(undefined, squashError);
110
+ throw new TimeoutError('Timed out', { duration: this.duration });
111
+ }
106
112
  }
107
113
 
108
114
  public static expires(duration: number, unref?: true): Timeout {