mongodb 6.16.0 → 6.17.0-dev.20250605.sha.57ef31be

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 (130) hide show
  1. package/README.md +2 -0
  2. package/lib/beta.d.ts +160 -49
  3. package/lib/bulk/common.js +4 -4
  4. package/lib/bulk/common.js.map +1 -1
  5. package/lib/change_stream.js.map +1 -1
  6. package/lib/client-side-encryption/auto_encrypter.js +5 -2
  7. package/lib/client-side-encryption/auto_encrypter.js.map +1 -1
  8. package/lib/client-side-encryption/client_encryption.js.map +1 -1
  9. package/lib/client-side-encryption/state_machine.js +1 -1
  10. package/lib/client-side-encryption/state_machine.js.map +1 -1
  11. package/lib/cmap/auth/mongodb_oidc/automated_callback_workflow.js +6 -0
  12. package/lib/cmap/auth/mongodb_oidc/automated_callback_workflow.js.map +1 -1
  13. package/lib/cmap/auth/mongodb_oidc/azure_machine_workflow.js +21 -33
  14. package/lib/cmap/auth/mongodb_oidc/azure_machine_workflow.js.map +1 -1
  15. package/lib/cmap/auth/mongodb_oidc/gcp_machine_workflow.js +14 -21
  16. package/lib/cmap/auth/mongodb_oidc/gcp_machine_workflow.js.map +1 -1
  17. package/lib/cmap/auth/mongodb_oidc/k8s_machine_workflow.js +19 -26
  18. package/lib/cmap/auth/mongodb_oidc/k8s_machine_workflow.js.map +1 -1
  19. package/lib/cmap/auth/mongodb_oidc/token_machine_workflow.js +12 -24
  20. package/lib/cmap/auth/mongodb_oidc/token_machine_workflow.js.map +1 -1
  21. package/lib/cmap/auth/mongodb_oidc.js +5 -4
  22. package/lib/cmap/auth/mongodb_oidc.js.map +1 -1
  23. package/lib/cmap/commands.js +10 -8
  24. package/lib/cmap/commands.js.map +1 -1
  25. package/lib/cmap/connect.js +4 -3
  26. package/lib/cmap/connect.js.map +1 -1
  27. package/lib/cmap/connection.js +8 -3
  28. package/lib/cmap/connection.js.map +1 -1
  29. package/lib/cmap/connection_pool.js +6 -1
  30. package/lib/cmap/connection_pool.js.map +1 -1
  31. package/lib/cmap/handshake/client_metadata.js +1 -1
  32. package/lib/cmap/handshake/client_metadata.js.map +1 -1
  33. package/lib/cmap/wire_protocol/compression.js.map +1 -1
  34. package/lib/cmap/wire_protocol/constants.js +2 -2
  35. package/lib/cmap/wire_protocol/on_data.js +4 -0
  36. package/lib/cmap/wire_protocol/on_data.js.map +1 -1
  37. package/lib/cmap/wire_protocol/on_demand/document.js +16 -15
  38. package/lib/cmap/wire_protocol/on_demand/document.js.map +1 -1
  39. package/lib/cmap/wire_protocol/responses.js +11 -4
  40. package/lib/cmap/wire_protocol/responses.js.map +1 -1
  41. package/lib/collection.js.map +1 -1
  42. package/lib/connection_string.js +4 -0
  43. package/lib/connection_string.js.map +1 -1
  44. package/lib/constants.js +0 -1
  45. package/lib/constants.js.map +1 -1
  46. package/lib/cursor/abstract_cursor.js.map +1 -1
  47. package/lib/encrypter.js +3 -7
  48. package/lib/encrypter.js.map +1 -1
  49. package/lib/error.js +28 -1
  50. package/lib/error.js.map +1 -1
  51. package/lib/index.js +4 -3
  52. package/lib/index.js.map +1 -1
  53. package/lib/mongo_client.js +66 -20
  54. package/lib/mongo_client.js.map +1 -1
  55. package/lib/operations/aggregate.js +0 -1
  56. package/lib/operations/aggregate.js.map +1 -1
  57. package/lib/operations/client_bulk_write/command_builder.js +20 -13
  58. package/lib/operations/client_bulk_write/command_builder.js.map +1 -1
  59. package/lib/operations/distinct.js +1 -0
  60. package/lib/operations/distinct.js.map +1 -1
  61. package/lib/operations/find_and_modify.js +1 -1
  62. package/lib/operations/find_and_modify.js.map +1 -1
  63. package/lib/operations/rename.js.map +1 -1
  64. package/lib/operations/run_command.js.map +1 -1
  65. package/lib/operations/search_indexes/create.js.map +1 -1
  66. package/lib/operations/search_indexes/drop.js.map +1 -1
  67. package/lib/operations/search_indexes/update.js.map +1 -1
  68. package/lib/operations/update.js +6 -2
  69. package/lib/operations/update.js.map +1 -1
  70. package/lib/sdam/server.js +4 -1
  71. package/lib/sdam/server.js.map +1 -1
  72. package/lib/sdam/topology.js +9 -4
  73. package/lib/sdam/topology.js.map +1 -1
  74. package/lib/sort.js +13 -6
  75. package/lib/sort.js.map +1 -1
  76. package/lib/utils.js +15 -2
  77. package/lib/utils.js.map +1 -1
  78. package/lib/write_concern.js +2 -4
  79. package/lib/write_concern.js.map +1 -1
  80. package/mongodb.d.ts +160 -49
  81. package/package.json +21 -21
  82. package/src/bulk/common.ts +14 -11
  83. package/src/change_stream.ts +38 -13
  84. package/src/client-side-encryption/auto_encrypter.ts +10 -2
  85. package/src/client-side-encryption/client_encryption.ts +5 -0
  86. package/src/client-side-encryption/state_machine.ts +8 -5
  87. package/src/cmap/auth/mongodb_oidc/automated_callback_workflow.ts +6 -0
  88. package/src/cmap/auth/mongodb_oidc/azure_machine_workflow.ts +23 -35
  89. package/src/cmap/auth/mongodb_oidc/gcp_machine_workflow.ts +16 -23
  90. package/src/cmap/auth/mongodb_oidc/k8s_machine_workflow.ts +17 -25
  91. package/src/cmap/auth/mongodb_oidc/token_machine_workflow.ts +11 -24
  92. package/src/cmap/auth/mongodb_oidc.ts +13 -8
  93. package/src/cmap/commands.ts +31 -16
  94. package/src/cmap/connect.ts +4 -3
  95. package/src/cmap/connection.ts +11 -4
  96. package/src/cmap/connection_pool.ts +8 -1
  97. package/src/cmap/handshake/client_metadata.ts +5 -1
  98. package/src/cmap/wire_protocol/compression.ts +2 -1
  99. package/src/cmap/wire_protocol/constants.ts +2 -2
  100. package/src/cmap/wire_protocol/on_data.ts +5 -0
  101. package/src/cmap/wire_protocol/on_demand/document.ts +20 -15
  102. package/src/cmap/wire_protocol/responses.ts +10 -10
  103. package/src/collection.ts +2 -1
  104. package/src/connection_string.ts +4 -0
  105. package/src/constants.ts +0 -1
  106. package/src/cursor/abstract_cursor.ts +6 -4
  107. package/src/encrypter.ts +3 -10
  108. package/src/error.ts +28 -0
  109. package/src/index.ts +3 -0
  110. package/src/mongo_client.ts +73 -21
  111. package/src/operations/aggregate.ts +0 -1
  112. package/src/operations/client_bulk_write/command_builder.ts +32 -14
  113. package/src/operations/client_bulk_write/common.ts +5 -0
  114. package/src/operations/distinct.ts +1 -0
  115. package/src/operations/find_and_modify.ts +1 -1
  116. package/src/operations/rename.ts +8 -5
  117. package/src/operations/run_command.ts +17 -4
  118. package/src/operations/search_indexes/create.ts +6 -4
  119. package/src/operations/search_indexes/drop.ts +6 -4
  120. package/src/operations/search_indexes/update.ts +8 -5
  121. package/src/operations/update.ts +12 -3
  122. package/src/sdam/server.ts +5 -1
  123. package/src/sdam/topology.ts +10 -4
  124. package/src/sort.ts +32 -23
  125. package/src/utils.ts +29 -9
  126. package/src/write_concern.ts +2 -4
  127. package/tsconfig.json +2 -1
  128. package/lib/cmap/auth/mongodb_oidc/machine_workflow.js +0 -110
  129. package/lib/cmap/auth/mongodb_oidc/machine_workflow.js.map +0 -1
  130. package/src/cmap/auth/mongodb_oidc/machine_workflow.ts +0 -142
@@ -19,6 +19,7 @@ import { makeUpdateStatement, UpdateOperation, type UpdateStatement } from '../o
19
19
  import type { Server } from '../sdam/server';
20
20
  import type { Topology } from '../sdam/topology';
21
21
  import type { ClientSession } from '../sessions';
22
+ import { type Sort } from '../sort';
22
23
  import { type TimeoutContext } from '../timeout';
23
24
  import {
24
25
  applyRetryableWrites,
@@ -68,7 +69,7 @@ export interface DeleteManyModel<TSchema extends Document = Document> {
68
69
 
69
70
  /** @public */
70
71
  export interface ReplaceOneModel<TSchema extends Document = Document> {
71
- /** The filter to limit the replaced document. */
72
+ /** The filter that specifies which document to replace. In the case of multiple matches, the first document matched is replaced. */
72
73
  filter: Filter<TSchema>;
73
74
  /** The document with which to replace the matched document. */
74
75
  replacement: WithoutId<TSchema>;
@@ -78,11 +79,13 @@ export interface ReplaceOneModel<TSchema extends Document = Document> {
78
79
  hint?: Hint;
79
80
  /** When true, creates a new document if no document matches the query. */
80
81
  upsert?: boolean;
82
+ /** Specifies the sort order for the documents matched by the filter. */
83
+ sort?: Sort;
81
84
  }
82
85
 
83
86
  /** @public */
84
87
  export interface UpdateOneModel<TSchema extends Document = Document> {
85
- /** The filter to limit the updated documents. */
88
+ /** The filter that specifies which document to update. In the case of multiple matches, the first document matched is updated. */
86
89
  filter: Filter<TSchema>;
87
90
  /**
88
91
  * The modifications to apply. The value can be either:
@@ -98,6 +101,8 @@ export interface UpdateOneModel<TSchema extends Document = Document> {
98
101
  hint?: Hint;
99
102
  /** When true, creates a new document if no document matches the query. */
100
103
  upsert?: boolean;
104
+ /** Specifies the sort order for the documents matched by the filter. */
105
+ sort?: Sort;
101
106
  }
102
107
 
103
108
  /** @public */
@@ -252,7 +257,7 @@ export class BulkWriteResult {
252
257
  return this.result.writeErrors.length > 0;
253
258
  }
254
259
 
255
- /** Returns the number of write errors off the bulk operation */
260
+ /** Returns the number of write errors from the bulk operation */
256
261
  getWriteErrorCount(): number {
257
262
  return this.result.writeErrors.length;
258
263
  }
@@ -700,7 +705,7 @@ export class FindOperators {
700
705
 
701
706
  /** Add a single update operation to the bulk operation */
702
707
  updateOne(updateDocument: Document | Document[]): BulkOperationBase {
703
- if (!hasAtomicOperators(updateDocument)) {
708
+ if (!hasAtomicOperators(updateDocument, this.bulkOperation.bsonOptions)) {
704
709
  throw new MongoInvalidArgumentError('Update document requires atomic operators');
705
710
  }
706
711
 
@@ -889,16 +894,14 @@ export abstract class BulkOperationBase {
889
894
  /** @internal */
890
895
  s: BulkOperationPrivate;
891
896
  operationId?: number;
897
+ private collection: Collection;
892
898
 
893
899
  /**
894
900
  * Create a new OrderedBulkOperation or UnorderedBulkOperation instance
895
901
  * @internal
896
902
  */
897
- constructor(
898
- private collection: Collection,
899
- options: BulkWriteOptions,
900
- isOrdered: boolean
901
- ) {
903
+ constructor(collection: Collection, options: BulkWriteOptions, isOrdered: boolean) {
904
+ this.collection = collection;
902
905
  // determine whether bulkOperation is ordered or unordered
903
906
  this.isOrdered = isOrdered;
904
907
 
@@ -1110,7 +1113,7 @@ export abstract class BulkOperationBase {
1110
1113
  ...op.updateOne,
1111
1114
  multi: false
1112
1115
  });
1113
- if (!hasAtomicOperators(updateStatement.u)) {
1116
+ if (!hasAtomicOperators(updateStatement.u, this.bsonOptions)) {
1114
1117
  throw new MongoInvalidArgumentError('Update document requires atomic operators');
1115
1118
  }
1116
1119
  return this.addToOperationsList(BatchType.UPDATE, updateStatement);
@@ -1124,7 +1127,7 @@ export abstract class BulkOperationBase {
1124
1127
  ...op.updateMany,
1125
1128
  multi: true
1126
1129
  });
1127
- if (!hasAtomicOperators(updateStatement.u)) {
1130
+ if (!hasAtomicOperators(updateStatement.u, this.bsonOptions)) {
1128
1131
  throw new MongoInvalidArgumentError('Update document requires atomic operators');
1129
1132
  }
1130
1133
  return this.addToOperationsList(BatchType.UPDATE, updateStatement);
@@ -205,6 +205,16 @@ export interface ChangeStreamDocumentCommon {
205
205
  splitEvent?: ChangeStreamSplitEvent;
206
206
  }
207
207
 
208
+ /** @public */
209
+ export interface ChangeStreamDocumentWallTime {
210
+ /**
211
+ * The server date and time of the database operation.
212
+ * wallTime differs from clusterTime in that clusterTime is a timestamp taken from the oplog entry associated with the database operation event.
213
+ * @sinceServerVersion 6.0.0
214
+ */
215
+ wallTime?: Date;
216
+ }
217
+
208
218
  /** @public */
209
219
  export interface ChangeStreamDocumentCollectionUUID {
210
220
  /**
@@ -239,7 +249,8 @@ export interface ChangeStreamDocumentOperationDescription {
239
249
  export interface ChangeStreamInsertDocument<TSchema extends Document = Document>
240
250
  extends ChangeStreamDocumentCommon,
241
251
  ChangeStreamDocumentKey<TSchema>,
242
- ChangeStreamDocumentCollectionUUID {
252
+ ChangeStreamDocumentCollectionUUID,
253
+ ChangeStreamDocumentWallTime {
243
254
  /** Describes the type of operation represented in this change notification */
244
255
  operationType: 'insert';
245
256
  /** This key will contain the document being inserted */
@@ -255,7 +266,8 @@ export interface ChangeStreamInsertDocument<TSchema extends Document = Document>
255
266
  export interface ChangeStreamUpdateDocument<TSchema extends Document = Document>
256
267
  extends ChangeStreamDocumentCommon,
257
268
  ChangeStreamDocumentKey<TSchema>,
258
- ChangeStreamDocumentCollectionUUID {
269
+ ChangeStreamDocumentCollectionUUID,
270
+ ChangeStreamDocumentWallTime {
259
271
  /** Describes the type of operation represented in this change notification */
260
272
  operationType: 'update';
261
273
  /**
@@ -285,7 +297,8 @@ export interface ChangeStreamUpdateDocument<TSchema extends Document = Document>
285
297
  */
286
298
  export interface ChangeStreamReplaceDocument<TSchema extends Document = Document>
287
299
  extends ChangeStreamDocumentCommon,
288
- ChangeStreamDocumentKey<TSchema> {
300
+ ChangeStreamDocumentKey<TSchema>,
301
+ ChangeStreamDocumentWallTime {
289
302
  /** Describes the type of operation represented in this change notification */
290
303
  operationType: 'replace';
291
304
  /** The fullDocument of a replace event represents the document after the insert of the replacement document */
@@ -309,7 +322,8 @@ export interface ChangeStreamReplaceDocument<TSchema extends Document = Document
309
322
  export interface ChangeStreamDeleteDocument<TSchema extends Document = Document>
310
323
  extends ChangeStreamDocumentCommon,
311
324
  ChangeStreamDocumentKey<TSchema>,
312
- ChangeStreamDocumentCollectionUUID {
325
+ ChangeStreamDocumentCollectionUUID,
326
+ ChangeStreamDocumentWallTime {
313
327
  /** Describes the type of operation represented in this change notification */
314
328
  operationType: 'delete';
315
329
  /** Namespace the delete event occurred on */
@@ -330,7 +344,8 @@ export interface ChangeStreamDeleteDocument<TSchema extends Document = Document>
330
344
  */
331
345
  export interface ChangeStreamDropDocument
332
346
  extends ChangeStreamDocumentCommon,
333
- ChangeStreamDocumentCollectionUUID {
347
+ ChangeStreamDocumentCollectionUUID,
348
+ ChangeStreamDocumentWallTime {
334
349
  /** Describes the type of operation represented in this change notification */
335
350
  operationType: 'drop';
336
351
  /** Namespace the drop event occurred on */
@@ -343,7 +358,8 @@ export interface ChangeStreamDropDocument
343
358
  */
344
359
  export interface ChangeStreamRenameDocument
345
360
  extends ChangeStreamDocumentCommon,
346
- ChangeStreamDocumentCollectionUUID {
361
+ ChangeStreamDocumentCollectionUUID,
362
+ ChangeStreamDocumentWallTime {
347
363
  /** Describes the type of operation represented in this change notification */
348
364
  operationType: 'rename';
349
365
  /** The new name for the `ns.coll` collection */
@@ -356,7 +372,9 @@ export interface ChangeStreamRenameDocument
356
372
  * @public
357
373
  * @see https://www.mongodb.com/docs/manual/reference/change-events/#dropdatabase-event
358
374
  */
359
- export interface ChangeStreamDropDatabaseDocument extends ChangeStreamDocumentCommon {
375
+ export interface ChangeStreamDropDatabaseDocument
376
+ extends ChangeStreamDocumentCommon,
377
+ ChangeStreamDocumentWallTime {
360
378
  /** Describes the type of operation represented in this change notification */
361
379
  operationType: 'dropDatabase';
362
380
  /** The database dropped */
@@ -367,7 +385,9 @@ export interface ChangeStreamDropDatabaseDocument extends ChangeStreamDocumentCo
367
385
  * @public
368
386
  * @see https://www.mongodb.com/docs/manual/reference/change-events/#invalidate-event
369
387
  */
370
- export interface ChangeStreamInvalidateDocument extends ChangeStreamDocumentCommon {
388
+ export interface ChangeStreamInvalidateDocument
389
+ extends ChangeStreamDocumentCommon,
390
+ ChangeStreamDocumentWallTime {
371
391
  /** Describes the type of operation represented in this change notification */
372
392
  operationType: 'invalidate';
373
393
  }
@@ -380,7 +400,8 @@ export interface ChangeStreamInvalidateDocument extends ChangeStreamDocumentComm
380
400
  export interface ChangeStreamCreateIndexDocument
381
401
  extends ChangeStreamDocumentCommon,
382
402
  ChangeStreamDocumentCollectionUUID,
383
- ChangeStreamDocumentOperationDescription {
403
+ ChangeStreamDocumentOperationDescription,
404
+ ChangeStreamDocumentWallTime {
384
405
  /** Describes the type of operation represented in this change notification */
385
406
  operationType: 'createIndexes';
386
407
  }
@@ -393,7 +414,8 @@ export interface ChangeStreamCreateIndexDocument
393
414
  export interface ChangeStreamDropIndexDocument
394
415
  extends ChangeStreamDocumentCommon,
395
416
  ChangeStreamDocumentCollectionUUID,
396
- ChangeStreamDocumentOperationDescription {
417
+ ChangeStreamDocumentOperationDescription,
418
+ ChangeStreamDocumentWallTime {
397
419
  /** Describes the type of operation represented in this change notification */
398
420
  operationType: 'dropIndexes';
399
421
  }
@@ -405,7 +427,8 @@ export interface ChangeStreamDropIndexDocument
405
427
  */
406
428
  export interface ChangeStreamCollModDocument
407
429
  extends ChangeStreamDocumentCommon,
408
- ChangeStreamDocumentCollectionUUID {
430
+ ChangeStreamDocumentCollectionUUID,
431
+ ChangeStreamDocumentWallTime {
409
432
  /** Describes the type of operation represented in this change notification */
410
433
  operationType: 'modify';
411
434
  }
@@ -416,7 +439,8 @@ export interface ChangeStreamCollModDocument
416
439
  */
417
440
  export interface ChangeStreamCreateDocument
418
441
  extends ChangeStreamDocumentCommon,
419
- ChangeStreamDocumentCollectionUUID {
442
+ ChangeStreamDocumentCollectionUUID,
443
+ ChangeStreamDocumentWallTime {
420
444
  /** Describes the type of operation represented in this change notification */
421
445
  operationType: 'create';
422
446
 
@@ -435,7 +459,8 @@ export interface ChangeStreamCreateDocument
435
459
  export interface ChangeStreamShardCollectionDocument
436
460
  extends ChangeStreamDocumentCommon,
437
461
  ChangeStreamDocumentCollectionUUID,
438
- ChangeStreamDocumentOperationDescription {
462
+ ChangeStreamDocumentOperationDescription,
463
+ ChangeStreamDocumentWallTime {
439
464
  /** Describes the type of operation represented in this change notification */
440
465
  operationType: 'shardCollection';
441
466
  }
@@ -52,6 +52,10 @@ export interface AutoEncryptionOptions {
52
52
  bypassAutoEncryption?: boolean;
53
53
  /** Allows users to bypass query analysis */
54
54
  bypassQueryAnalysis?: boolean;
55
+ /**
56
+ * Sets the expiration time for the DEK in the cache in milliseconds. Defaults to 60000. 0 means no timeout.
57
+ */
58
+ keyExpirationMS?: number;
55
59
  options?: {
56
60
  /** An optional hook to catch logging messages from the underlying encryption engine */
57
61
  logger?: (level: AutoEncryptionLoggerLevel, message: string) => void;
@@ -285,6 +289,10 @@ export class AutoEncrypter {
285
289
  mongoCryptOptions.bypassQueryAnalysis = options.bypassQueryAnalysis;
286
290
  }
287
291
 
292
+ if (options.keyExpirationMS != null) {
293
+ mongoCryptOptions.keyExpirationMS = options.keyExpirationMS;
294
+ }
295
+
288
296
  this._bypassMongocryptdAndCryptShared = this._bypassEncryption || !!options.bypassQueryAnalysis;
289
297
 
290
298
  if (options.extraOptions && options.extraOptions.cryptSharedLibSearchPaths) {
@@ -375,8 +383,8 @@ export class AutoEncrypter {
375
383
  /**
376
384
  * Cleans up the `_mongocryptdClient`, if present.
377
385
  */
378
- async teardown(force: boolean): Promise<void> {
379
- await this._mongocryptdClient?.close(force);
386
+ async close(): Promise<void> {
387
+ await this._mongocryptdClient?.close();
380
388
  }
381
389
 
382
390
  /**
@@ -885,6 +885,11 @@ export interface ClientEncryptionOptions {
885
885
  */
886
886
  tlsOptions?: CSFLEKMSTlsOptions;
887
887
 
888
+ /**
889
+ * Sets the expiration time for the DEK in the cache in milliseconds. Defaults to 60000. 0 means no timeout.
890
+ */
891
+ keyExpirationMS?: number;
892
+
888
893
  /**
889
894
  * @experimental
890
895
  *
@@ -186,10 +186,13 @@ export type StateMachineOptions = {
186
186
  */
187
187
  // TODO(DRIVERS-2671): clarify CSOT behavior for FLE APIs
188
188
  export class StateMachine {
189
- constructor(
190
- private options: StateMachineOptions,
191
- private bsonOptions = pluckBSONSerializeOptions(options)
192
- ) {}
189
+ private options: StateMachineOptions;
190
+ private bsonOptions: BSONSerializeOptions;
191
+
192
+ constructor(options: StateMachineOptions, bsonOptions = pluckBSONSerializeOptions(options)) {
193
+ this.options = options;
194
+ this.bsonOptions = bsonOptions;
195
+ }
193
196
 
194
197
  /**
195
198
  * Executes the state machine according to the specification
@@ -275,7 +278,7 @@ export class StateMachine {
275
278
  // See docs on EMPTY_V
276
279
  result = EMPTY_V ??= serialize({ v: [] });
277
280
  }
278
- for await (const key of keys) {
281
+ for (const key of keys) {
279
282
  context.addMongoOperationResponse(serialize(key));
280
283
  }
281
284
 
@@ -34,6 +34,9 @@ export class AutomatedCallbackWorkflow extends CallbackWorkflow {
34
34
  // If the server fails for any other reason, do not clear the cache.
35
35
  if (this.cache.hasAccessToken) {
36
36
  const token = this.cache.getAccessToken();
37
+ if (!connection.accessToken) {
38
+ connection.accessToken = token;
39
+ }
37
40
  try {
38
41
  return await this.finishAuthentication(connection, credentials, token);
39
42
  } catch (error) {
@@ -66,6 +69,9 @@ export class AutomatedCallbackWorkflow extends CallbackWorkflow {
66
69
  if (credentials.username) {
67
70
  params.username = credentials.username;
68
71
  }
72
+ if (credentials.mechanismProperties.TOKEN_RESOURCE) {
73
+ params.tokenAudience = credentials.mechanismProperties.TOKEN_RESOURCE;
74
+ }
69
75
  const timeout = Timeout.expires(AUTOMATED_TIMEOUT_MS);
70
76
  try {
71
77
  return await Promise.race([this.executeAndValidateCallback(params), timeout]);
@@ -1,9 +1,7 @@
1
1
  import { addAzureParams, AZURE_BASE_URL } from '../../../client-side-encryption/providers/azure';
2
2
  import { MongoAzureError } from '../../../error';
3
3
  import { get } from '../../../utils';
4
- import type { MongoCredentials } from '../mongo_credentials';
5
- import { type AccessToken, MachineWorkflow } from './machine_workflow';
6
- import { type TokenCache } from './token_cache';
4
+ import type { OIDCCallbackFunction, OIDCCallbackParams, OIDCResponse } from '../mongodb_oidc';
7
5
 
8
6
  /** Azure request headers. */
9
7
  const AZURE_HEADERS = Object.freeze({ Metadata: 'true', Accept: 'application/json' });
@@ -17,39 +15,29 @@ const TOKEN_RESOURCE_MISSING_ERROR =
17
15
  'TOKEN_RESOURCE must be set in the auth mechanism properties when ENVIRONMENT is azure.';
18
16
 
19
17
  /**
20
- * Device workflow implementation for Azure.
21
- *
22
- * @internal
18
+ * The callback function to be used in the automated callback workflow.
19
+ * @param params - The OIDC callback parameters.
20
+ * @returns The OIDC response.
23
21
  */
24
- export class AzureMachineWorkflow extends MachineWorkflow {
25
- /**
26
- * Instantiate the machine workflow.
27
- */
28
- constructor(cache: TokenCache) {
29
- super(cache);
22
+ export const callback: OIDCCallbackFunction = async (
23
+ params: OIDCCallbackParams
24
+ ): Promise<OIDCResponse> => {
25
+ const tokenAudience = params.tokenAudience;
26
+ const username = params.username;
27
+ if (!tokenAudience) {
28
+ throw new MongoAzureError(TOKEN_RESOURCE_MISSING_ERROR);
30
29
  }
31
-
32
- /**
33
- * Get the token from the environment.
34
- */
35
- async getToken(credentials?: MongoCredentials): Promise<AccessToken> {
36
- const tokenAudience = credentials?.mechanismProperties.TOKEN_RESOURCE;
37
- const username = credentials?.username;
38
- if (!tokenAudience) {
39
- throw new MongoAzureError(TOKEN_RESOURCE_MISSING_ERROR);
40
- }
41
- const response = await getAzureTokenData(tokenAudience, username);
42
- if (!isEndpointResultValid(response)) {
43
- throw new MongoAzureError(ENDPOINT_RESULT_ERROR);
44
- }
45
- return response;
30
+ const response = await getAzureTokenData(tokenAudience, username);
31
+ if (!isEndpointResultValid(response)) {
32
+ throw new MongoAzureError(ENDPOINT_RESULT_ERROR);
46
33
  }
47
- }
34
+ return response;
35
+ };
48
36
 
49
37
  /**
50
38
  * Hit the Azure endpoint to get the token data.
51
39
  */
52
- async function getAzureTokenData(tokenAudience: string, username?: string): Promise<AccessToken> {
40
+ async function getAzureTokenData(tokenAudience: string, username?: string): Promise<OIDCResponse> {
53
41
  const url = new URL(AZURE_BASE_URL);
54
42
  addAzureParams(url, tokenAudience, username);
55
43
  const response = await get(url, {
@@ -62,8 +50,8 @@ async function getAzureTokenData(tokenAudience: string, username?: string): Prom
62
50
  }
63
51
  const result = JSON.parse(response.body);
64
52
  return {
65
- access_token: result.access_token,
66
- expires_in: Number(result.expires_in)
53
+ accessToken: result.access_token,
54
+ expiresInSeconds: Number(result.expires_in)
67
55
  };
68
56
  }
69
57
 
@@ -77,9 +65,9 @@ function isEndpointResultValid(
77
65
  ): token is { access_token: unknown; expires_in: unknown } {
78
66
  if (token == null || typeof token !== 'object') return false;
79
67
  return (
80
- 'access_token' in token &&
81
- typeof token.access_token === 'string' &&
82
- 'expires_in' in token &&
83
- typeof token.expires_in === 'number'
68
+ 'accessToken' in token &&
69
+ typeof token.accessToken === 'string' &&
70
+ 'expiresInSeconds' in token &&
71
+ typeof token.expiresInSeconds === 'number'
84
72
  );
85
73
  }
@@ -1,8 +1,6 @@
1
1
  import { MongoGCPError } from '../../../error';
2
2
  import { get } from '../../../utils';
3
- import { type MongoCredentials } from '../mongo_credentials';
4
- import { type AccessToken, MachineWorkflow } from './machine_workflow';
5
- import { type TokenCache } from './token_cache';
3
+ import type { OIDCCallbackFunction, OIDCCallbackParams, OIDCResponse } from '../mongodb_oidc';
6
4
 
7
5
  /** GCP base URL. */
8
6
  const GCP_BASE_URL =
@@ -15,30 +13,25 @@ const GCP_HEADERS = Object.freeze({ 'Metadata-Flavor': 'Google' });
15
13
  const TOKEN_RESOURCE_MISSING_ERROR =
16
14
  'TOKEN_RESOURCE must be set in the auth mechanism properties when ENVIRONMENT is gcp.';
17
15
 
18
- export class GCPMachineWorkflow extends MachineWorkflow {
19
- /**
20
- * Instantiate the machine workflow.
21
- */
22
- constructor(cache: TokenCache) {
23
- super(cache);
24
- }
25
-
26
- /**
27
- * Get the token from the environment.
28
- */
29
- async getToken(credentials?: MongoCredentials): Promise<AccessToken> {
30
- const tokenAudience = credentials?.mechanismProperties.TOKEN_RESOURCE;
31
- if (!tokenAudience) {
32
- throw new MongoGCPError(TOKEN_RESOURCE_MISSING_ERROR);
33
- }
34
- return await getGcpTokenData(tokenAudience);
16
+ /**
17
+ * The callback function to be used in the automated callback workflow.
18
+ * @param params - The OIDC callback parameters.
19
+ * @returns The OIDC response.
20
+ */
21
+ export const callback: OIDCCallbackFunction = async (
22
+ params: OIDCCallbackParams
23
+ ): Promise<OIDCResponse> => {
24
+ const tokenAudience = params.tokenAudience;
25
+ if (!tokenAudience) {
26
+ throw new MongoGCPError(TOKEN_RESOURCE_MISSING_ERROR);
35
27
  }
36
- }
28
+ return await getGcpTokenData(tokenAudience);
29
+ };
37
30
 
38
31
  /**
39
32
  * Hit the GCP endpoint to get the token data.
40
33
  */
41
- async function getGcpTokenData(tokenAudience: string): Promise<AccessToken> {
34
+ async function getGcpTokenData(tokenAudience: string): Promise<OIDCResponse> {
42
35
  const url = new URL(GCP_BASE_URL);
43
36
  url.searchParams.append('audience', tokenAudience);
44
37
  const response = await get(url, {
@@ -49,5 +42,5 @@ async function getGcpTokenData(tokenAudience: string): Promise<AccessToken> {
49
42
  `Status code ${response.status} returned from the GCP endpoint. Response body: ${response.body}`
50
43
  );
51
44
  }
52
- return { access_token: response.body };
45
+ return { accessToken: response.body };
53
46
  }
@@ -1,7 +1,6 @@
1
1
  import { readFile } from 'fs/promises';
2
2
 
3
- import { type AccessToken, MachineWorkflow } from './machine_workflow';
4
- import { type TokenCache } from './token_cache';
3
+ import type { OIDCCallbackFunction, OIDCResponse } from '../mongodb_oidc';
5
4
 
6
5
  /** The fallback file name */
7
6
  const FALLBACK_FILENAME = '/var/run/secrets/kubernetes.io/serviceaccount/token';
@@ -12,27 +11,20 @@ const AZURE_FILENAME = 'AZURE_FEDERATED_TOKEN_FILE';
12
11
  /** The AWS environment variable for the file name. */
13
12
  const AWS_FILENAME = 'AWS_WEB_IDENTITY_TOKEN_FILE';
14
13
 
15
- export class K8SMachineWorkflow extends MachineWorkflow {
16
- /**
17
- * Instantiate the machine workflow.
18
- */
19
- constructor(cache: TokenCache) {
20
- super(cache);
14
+ /**
15
+ * The callback function to be used in the automated callback workflow.
16
+ * @param params - The OIDC callback parameters.
17
+ * @returns The OIDC response.
18
+ */
19
+ export const callback: OIDCCallbackFunction = async (): Promise<OIDCResponse> => {
20
+ let filename: string;
21
+ if (process.env[AZURE_FILENAME]) {
22
+ filename = process.env[AZURE_FILENAME];
23
+ } else if (process.env[AWS_FILENAME]) {
24
+ filename = process.env[AWS_FILENAME];
25
+ } else {
26
+ filename = FALLBACK_FILENAME;
21
27
  }
22
-
23
- /**
24
- * Get the token from the environment.
25
- */
26
- async getToken(): Promise<AccessToken> {
27
- let filename: string;
28
- if (process.env[AZURE_FILENAME]) {
29
- filename = process.env[AZURE_FILENAME];
30
- } else if (process.env[AWS_FILENAME]) {
31
- filename = process.env[AWS_FILENAME];
32
- } else {
33
- filename = FALLBACK_FILENAME;
34
- }
35
- const token = await readFile(filename, 'utf8');
36
- return { access_token: token };
37
- }
38
- }
28
+ const token = await readFile(filename, 'utf8');
29
+ return { accessToken: token };
30
+ };
@@ -1,34 +1,21 @@
1
1
  import * as fs from 'fs';
2
2
 
3
3
  import { MongoAWSError } from '../../../error';
4
- import { type AccessToken, MachineWorkflow } from './machine_workflow';
5
- import { type TokenCache } from './token_cache';
4
+ import type { OIDCCallbackFunction, OIDCResponse } from '../mongodb_oidc';
6
5
 
7
6
  /** Error for when the token is missing in the environment. */
8
7
  const TOKEN_MISSING_ERROR = 'OIDC_TOKEN_FILE must be set in the environment.';
9
8
 
10
9
  /**
11
- * Device workflow implementation for AWS.
12
- *
13
- * @internal
10
+ * The callback function to be used in the automated callback workflow.
11
+ * @param params - The OIDC callback parameters.
12
+ * @returns The OIDC response.
14
13
  */
15
- export class TokenMachineWorkflow extends MachineWorkflow {
16
- /**
17
- * Instantiate the machine workflow.
18
- */
19
- constructor(cache: TokenCache) {
20
- super(cache);
14
+ export const callback: OIDCCallbackFunction = async (): Promise<OIDCResponse> => {
15
+ const tokenFile = process.env.OIDC_TOKEN_FILE;
16
+ if (!tokenFile) {
17
+ throw new MongoAWSError(TOKEN_MISSING_ERROR);
21
18
  }
22
-
23
- /**
24
- * Get the token from the environment.
25
- */
26
- async getToken(): Promise<AccessToken> {
27
- const tokenFile = process.env.OIDC_TOKEN_FILE;
28
- if (!tokenFile) {
29
- throw new MongoAWSError(TOKEN_MISSING_ERROR);
30
- }
31
- const token = await fs.promises.readFile(tokenFile, 'utf8');
32
- return { access_token: token };
33
- }
34
- }
19
+ const token = await fs.promises.readFile(tokenFile, 'utf8');
20
+ return { accessToken: token };
21
+ };
@@ -4,11 +4,12 @@ import type { HandshakeDocument } from '../connect';
4
4
  import type { Connection } from '../connection';
5
5
  import { type AuthContext, AuthProvider } from './auth_provider';
6
6
  import type { MongoCredentials } from './mongo_credentials';
7
- import { AzureMachineWorkflow } from './mongodb_oidc/azure_machine_workflow';
8
- import { GCPMachineWorkflow } from './mongodb_oidc/gcp_machine_workflow';
9
- import { K8SMachineWorkflow } from './mongodb_oidc/k8s_machine_workflow';
7
+ import { AutomatedCallbackWorkflow } from './mongodb_oidc/automated_callback_workflow';
8
+ import { callback as azureCallback } from './mongodb_oidc/azure_machine_workflow';
9
+ import { callback as gcpCallback } from './mongodb_oidc/gcp_machine_workflow';
10
+ import { callback as k8sCallback } from './mongodb_oidc/k8s_machine_workflow';
10
11
  import { TokenCache } from './mongodb_oidc/token_cache';
11
- import { TokenMachineWorkflow } from './mongodb_oidc/token_machine_workflow';
12
+ import { callback as testCallback } from './mongodb_oidc/token_machine_workflow';
12
13
 
13
14
  /** Error when credentials are missing. */
14
15
  const MISSING_CREDENTIALS_ERROR = 'AuthContext must provide credentials.';
@@ -78,6 +79,8 @@ export interface OIDCCallbackParams {
78
79
  idpInfo?: IdPInfo;
79
80
  /** The refresh token, if applicable, to be used by the callback to request a new token from the issuer. */
80
81
  refreshToken?: string;
82
+ /** The token audience for GCP and Azure. */
83
+ tokenAudience?: string;
81
84
  }
82
85
 
83
86
  /**
@@ -93,6 +96,8 @@ type EnvironmentName = 'test' | 'azure' | 'gcp' | 'k8s' | undefined;
93
96
 
94
97
  /** @internal */
95
98
  export interface Workflow {
99
+ cache: TokenCache;
100
+
96
101
  /**
97
102
  * All device workflows must implement this method in order to get the access
98
103
  * token and then call authenticate with it.
@@ -116,10 +121,10 @@ export interface Workflow {
116
121
 
117
122
  /** @internal */
118
123
  export const OIDC_WORKFLOWS: Map<EnvironmentName, () => Workflow> = new Map();
119
- OIDC_WORKFLOWS.set('test', () => new TokenMachineWorkflow(new TokenCache()));
120
- OIDC_WORKFLOWS.set('azure', () => new AzureMachineWorkflow(new TokenCache()));
121
- OIDC_WORKFLOWS.set('gcp', () => new GCPMachineWorkflow(new TokenCache()));
122
- OIDC_WORKFLOWS.set('k8s', () => new K8SMachineWorkflow(new TokenCache()));
124
+ OIDC_WORKFLOWS.set('test', () => new AutomatedCallbackWorkflow(new TokenCache(), testCallback));
125
+ OIDC_WORKFLOWS.set('azure', () => new AutomatedCallbackWorkflow(new TokenCache(), azureCallback));
126
+ OIDC_WORKFLOWS.set('gcp', () => new AutomatedCallbackWorkflow(new TokenCache(), gcpCallback));
127
+ OIDC_WORKFLOWS.set('k8s', () => new AutomatedCallbackWorkflow(new TokenCache(), k8sCallback));
123
128
 
124
129
  /**
125
130
  * OIDC auth provider.