mongodb-data-service 21.18.0 → 21.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 (41) hide show
  1. package/lib/connect-mongo-client.d.ts +7 -6
  2. package/lib/connect-mongo-client.d.ts.map +1 -1
  3. package/lib/connect-mongo-client.js +44 -11
  4. package/lib/connect-mongo-client.js.map +1 -1
  5. package/lib/connect.d.ts +1 -1
  6. package/lib/connect.d.ts.map +1 -1
  7. package/lib/connect.js +2 -5
  8. package/lib/connect.js.map +1 -1
  9. package/lib/connection-options.d.ts +7 -0
  10. package/lib/connection-options.d.ts.map +1 -1
  11. package/lib/connection-secrets.d.ts +2 -0
  12. package/lib/connection-secrets.d.ts.map +1 -1
  13. package/lib/connection-secrets.js +21 -1
  14. package/lib/connection-secrets.js.map +1 -1
  15. package/lib/connection-storage.d.ts +2 -1
  16. package/lib/connection-storage.d.ts.map +1 -1
  17. package/lib/connection-storage.js +56 -12
  18. package/lib/connection-storage.js.map +1 -1
  19. package/lib/connection-title.d.ts.map +1 -1
  20. package/lib/connection-title.js +0 -3
  21. package/lib/connection-title.js.map +1 -1
  22. package/lib/csfle-collection-tracker.d.ts +39 -0
  23. package/lib/csfle-collection-tracker.d.ts.map +1 -0
  24. package/lib/csfle-collection-tracker.js +205 -0
  25. package/lib/csfle-collection-tracker.js.map +1 -0
  26. package/lib/data-service.d.ts +129 -12
  27. package/lib/data-service.d.ts.map +1 -1
  28. package/lib/data-service.js +217 -68
  29. package/lib/data-service.js.map +1 -1
  30. package/lib/index.d.ts +3 -2
  31. package/lib/index.d.ts.map +1 -1
  32. package/lib/index.js +5 -3
  33. package/lib/index.js.map +1 -1
  34. package/lib/instance-detail-helper.d.ts +10 -2
  35. package/lib/instance-detail-helper.d.ts.map +1 -1
  36. package/lib/instance-detail-helper.js +31 -2
  37. package/lib/instance-detail-helper.js.map +1 -1
  38. package/lib/legacy/legacy-connection-model.d.ts.map +1 -1
  39. package/lib/legacy/legacy-connection-model.js +25 -1
  40. package/lib/legacy/legacy-connection-model.js.map +1 -1
  41. package/package.json +21 -17
@@ -1,8 +1,28 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
11
+ }) : function(o, v) {
12
+ o["default"] = v;
13
+ });
14
+ var __importStar = (this && this.__importStar) || function (mod) {
15
+ if (mod && mod.__esModule) return mod;
16
+ var result = {};
17
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18
+ __setModuleDefault(result, mod);
19
+ return result;
20
+ };
2
21
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
22
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
23
  };
5
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.DataServiceImpl = void 0;
6
26
  const util_1 = require("util");
7
27
  const async_1 = __importDefault(require("async"));
8
28
  const compass_logging_1 = __importDefault(require("@mongodb-js/compass-logging"));
@@ -14,6 +34,10 @@ const instance_detail_helper_1 = require("./instance-detail-helper");
14
34
  const redact_1 = require("./redact");
15
35
  const connect_mongo_client_1 = __importDefault(require("./connect-mongo-client"));
16
36
  const run_command_1 = require("./run-command");
37
+ const csfle_collection_tracker_1 = require("./csfle-collection-tracker");
38
+ const mongodb = __importStar(require("mongodb"));
39
+ const mongodb_client_encryption_1 = require("mongodb-client-encryption");
40
+ const ClientEncryption = (0, mongodb_client_encryption_1.extension)(mongodb).ClientEncryption;
17
41
  const { fetch: getIndexes } = require('mongodb-index-model');
18
42
  const { log, mongoLogId, debug } = (0, compass_logging_1.default)('COMPASS-DATA-SERVICE');
19
43
  function uniqueBy(values, key) {
@@ -23,10 +47,12 @@ function isEmptyObject(obj) {
23
47
  return Object.keys(obj).length === 0;
24
48
  }
25
49
  let id = 0;
26
- class DataService extends events_1.EventEmitter {
50
+ const kSessionClientType = Symbol('kSessionClientType');
51
+ class DataServiceImpl extends events_1.EventEmitter {
27
52
  constructor(connectionOptions) {
28
53
  super();
29
54
  this._isConnecting = false;
55
+ this._useCRUDClient = true;
30
56
  this._lastSeenTopology = null;
31
57
  this._isWritable = false;
32
58
  this._topologyType = 'Unknown';
@@ -46,7 +72,26 @@ class DataService extends events_1.EventEmitter {
46
72
  return new mongodb_connection_string_url_1.default(this._connectionOptions.connectionString);
47
73
  }
48
74
  getReadPreference() {
49
- return this._initializedClient.readPreference;
75
+ return this._initializedClient('CRUD').readPreference;
76
+ }
77
+ setCSFLEEnabled(enabled) {
78
+ log.info(mongoLogId(1001000117), this._logCtx(), 'Setting CSFLE mode', {
79
+ enabled,
80
+ });
81
+ this._useCRUDClient = enabled;
82
+ }
83
+ getCSFLEMode() {
84
+ if (this._crudClient && (0, instance_detail_helper_1.checkIsCSFLEConnection)(this._crudClient)) {
85
+ if (this._useCRUDClient) {
86
+ return 'enabled';
87
+ }
88
+ else {
89
+ return 'disabled';
90
+ }
91
+ }
92
+ else {
93
+ return 'unavailable';
94
+ }
50
95
  }
51
96
  collection(ns, options, callback) {
52
97
  async_1.default.parallel({
@@ -76,7 +121,7 @@ class DataService extends events_1.EventEmitter {
76
121
  }
77
122
  collectionStats(databaseName, collectionName, callback) {
78
123
  const logop = this._startLogOp(mongoLogId(1001000031), 'Fetching collection info', { ns: `${databaseName}.${collectionName}` });
79
- const db = this._initializedClient.db(databaseName);
124
+ const db = this._initializedClient('META').db(databaseName);
80
125
  db.command({ collStats: collectionName, verbose: true }, (error, data) => {
81
126
  logop(error);
82
127
  if (error && !error.message.includes('is a view, not a collection')) {
@@ -95,7 +140,7 @@ class DataService extends events_1.EventEmitter {
95
140
  }
96
141
  }
97
142
  command(databaseName, comm, callback) {
98
- const db = this._initializedClient.db(databaseName);
143
+ const db = this._initializedClient('META').db(databaseName);
99
144
  db.command(comm, (error, result) => {
100
145
  if (error) {
101
146
  return callback(this._translateMessage(error));
@@ -115,7 +160,7 @@ class DataService extends events_1.EventEmitter {
115
160
  async connectionStatus() {
116
161
  const logop = this._startLogOp(mongoLogId(1001000100), 'Running connectionStatus');
117
162
  try {
118
- const adminDb = this._initializedClient.db('admin');
163
+ const adminDb = this._initializedClient('META').db('admin');
119
164
  const result = await (0, run_command_1.runCommand)(adminDb, {
120
165
  connectionStatus: 1,
121
166
  showPrivileges: true,
@@ -135,12 +180,25 @@ class DataService extends events_1.EventEmitter {
135
180
  const { authInfo: { authenticatedUserPrivileges }, } = await this.connectionStatus();
136
181
  return authenticatedUserPrivileges;
137
182
  }
183
+ async _getRolesOrFallback(roles = null) {
184
+ if (roles) {
185
+ return roles;
186
+ }
187
+ const { authInfo: { authenticatedUserRoles }, } = await this.connectionStatus();
188
+ return authenticatedUserRoles;
189
+ }
138
190
  async listCollections(databaseName, filter = {}, { nameOnly, privileges = null, } = {}) {
139
191
  const logop = this._startLogOp(mongoLogId(1001000032), 'Running listCollections', { db: databaseName, nameOnly: nameOnly !== null && nameOnly !== void 0 ? nameOnly : false });
140
- const db = this._initializedClient.db(databaseName);
192
+ const db = this._initializedClient('CRUD').db(databaseName);
141
193
  const listCollections = async () => {
142
194
  try {
143
- return await db.listCollections(filter, { nameOnly }).toArray();
195
+ const cursor = db.listCollections(filter, { nameOnly });
196
+ const results = [];
197
+ for await (const result of cursor) {
198
+ this.emit('collectionInfoFetched', { databaseName, nameOnly }, result);
199
+ results.push(result);
200
+ }
201
+ return results;
144
202
  }
145
203
  catch (err) {
146
204
  log.warn(mongoLogId(1001000099), this._logCtx(), 'Failed to run listCollections', { message: err.message });
@@ -167,9 +225,9 @@ class DataService extends events_1.EventEmitter {
167
225
  throw err;
168
226
  }
169
227
  }
170
- async listDatabases({ nameOnly, privileges = null, } = {}) {
228
+ async listDatabases({ nameOnly, privileges = null, roles = null, } = {}) {
171
229
  const logop = this._startLogOp(mongoLogId(1001000033), 'Running listDatabases', { nameOnly: nameOnly !== null && nameOnly !== void 0 ? nameOnly : false });
172
- const adminDb = this._initializedClient.db('admin');
230
+ const adminDb = this._initializedClient('CRUD').db('admin');
173
231
  const listDatabases = async () => {
174
232
  try {
175
233
  const { databases } = await (0, run_command_1.runCommand)(adminDb, {
@@ -189,12 +247,17 @@ class DataService extends events_1.EventEmitter {
189
247
  .filter(Boolean)
190
248
  .map((name) => ({ name }));
191
249
  };
250
+ const getDatabasesFromRoles = async () => {
251
+ const databases = (0, instance_detail_helper_1.getDatabasesByRoles)(await this._getRolesOrFallback(roles), ['read', 'readWrite', 'dbAdmin', 'dbOwner']);
252
+ return databases.map((name) => ({ name }));
253
+ };
192
254
  try {
193
- const [listedDatabases, databasesFromPrivileges] = await Promise.all([
255
+ const [listedDatabases, databasesFromPrivileges, databasesFromRoles] = await Promise.all([
194
256
  listDatabases(),
195
257
  getDatabasesFromPrivileges(),
258
+ getDatabasesFromRoles(),
196
259
  ]);
197
- const databases = uniqueBy([...databasesFromPrivileges, ...listedDatabases], 'name').map((db) => {
260
+ const databases = uniqueBy([...databasesFromRoles, ...databasesFromPrivileges, ...listedDatabases], 'name').map((db) => {
198
261
  return { _id: db.name, name: db.name, ...(0, instance_detail_helper_1.adaptDatabaseInfo)(db) };
199
262
  });
200
263
  logop(null, { databasesCount: databases.length });
@@ -206,7 +269,7 @@ class DataService extends events_1.EventEmitter {
206
269
  }
207
270
  }
208
271
  async connect() {
209
- if (this._client) {
272
+ if (this._metadataClient) {
210
273
  debug('already connected');
211
274
  return;
212
275
  }
@@ -218,18 +281,21 @@ class DataService extends events_1.EventEmitter {
218
281
  this._isConnecting = true;
219
282
  log.info(mongoLogId(1001000014), this._logCtx(), 'Connecting', {
220
283
  url: (0, redact_1.redactConnectionString)(this._connectionOptions.connectionString),
284
+ csfle: this._csfleLogInformation(this._connectionOptions.fleOptions),
221
285
  });
222
286
  try {
223
- const [client, tunnel, connectionOptions] = await (0, connect_mongo_client_1.default)(this._connectionOptions, this.setupListeners.bind(this));
287
+ const [metadataClient, crudClient, tunnel, connectionOptions] = await (0, connect_mongo_client_1.default)(this._connectionOptions, this.setupListeners.bind(this));
224
288
  const attr = {
225
289
  isWritable: this.isWritable(),
226
290
  isMongos: this.isMongos(),
227
291
  };
228
292
  log.info(mongoLogId(1001000015), this._logCtx(), 'Connected', attr);
229
293
  debug('connected!', attr);
230
- this._client = client;
294
+ this._metadataClient = metadataClient;
295
+ this._crudClient = crudClient;
231
296
  this._tunnel = tunnel;
232
297
  this._mongoClientConnectionOptions = connectionOptions;
298
+ this._csfleCollectionTracker = new csfle_collection_tracker_1.CSFLECollectionTrackerImpl(this, this._crudClient);
233
299
  }
234
300
  finally {
235
301
  this._isConnecting = false;
@@ -237,21 +303,21 @@ class DataService extends events_1.EventEmitter {
237
303
  }
238
304
  estimatedCount(ns, options, callback) {
239
305
  const logop = this._startLogOp(mongoLogId(1001000034), 'Running estimatedCount', { ns });
240
- this._collection(ns).estimatedDocumentCount(options, (err, result) => {
306
+ this._collection(ns, 'CRUD').estimatedDocumentCount(options, (err, result) => {
241
307
  logop(err, result);
242
308
  callback(err, result);
243
309
  });
244
310
  }
245
311
  count(ns, filter, options, callback) {
246
312
  const logop = this._startLogOp(mongoLogId(1001000035), 'Running countDocuments', { ns });
247
- this._collection(ns).countDocuments(filter, options, (err, result) => {
313
+ this._collection(ns, 'CRUD').countDocuments(filter, options, (err, result) => {
248
314
  logop(err, result);
249
315
  callback(err, result);
250
316
  });
251
317
  }
252
318
  createCollection(ns, options, callback) {
253
319
  const collectionName = this._collectionName(ns);
254
- const db = this._initializedClient.db(this._databaseName(ns));
320
+ const db = this._initializedClient('CRUD').db(this._databaseName(ns));
255
321
  const logop = this._startLogOp(mongoLogId(1001000036), 'Running createCollection', { ns, options });
256
322
  db.createCollection(collectionName, options, (error, result) => {
257
323
  logop(error);
@@ -263,7 +329,7 @@ class DataService extends events_1.EventEmitter {
263
329
  }
264
330
  createIndex(ns, spec, options, callback) {
265
331
  const logop = this._startLogOp(mongoLogId(1001000037), 'Running createIndex', { ns, spec, options });
266
- this._collection(ns).createIndex(spec, options, (error, result) => {
332
+ this._collection(ns, 'CRUD').createIndex(spec, options, (error, result) => {
267
333
  logop(error);
268
334
  if (error) {
269
335
  return callback(this._translateMessage(error));
@@ -281,7 +347,7 @@ class DataService extends events_1.EventEmitter {
281
347
  }
282
348
  deleteOne(ns, filter, options, callback) {
283
349
  const logop = this._startLogOp(mongoLogId(1001000038), 'Running deleteOne', { ns });
284
- this._collection(ns).deleteOne(filter, options, (error, result) => {
350
+ this._collection(ns, 'CRUD').deleteOne(filter, options, (error, result) => {
285
351
  logop(error, result);
286
352
  if (error) {
287
353
  return callback(this._translateMessage(error));
@@ -291,7 +357,7 @@ class DataService extends events_1.EventEmitter {
291
357
  }
292
358
  deleteMany(ns, filter, options, callback) {
293
359
  const logop = this._startLogOp(mongoLogId(1001000039), 'Running deleteMany', { ns });
294
- this._collection(ns).deleteMany(filter, options, (error, result) => {
360
+ this._collection(ns, 'CRUD').deleteMany(filter, options, (error, result) => {
295
361
  logop(error, result);
296
362
  if (error) {
297
363
  return callback(this._translateMessage(error));
@@ -300,11 +366,15 @@ class DataService extends events_1.EventEmitter {
300
366
  });
301
367
  }
302
368
  async disconnect() {
303
- var _a, _b;
369
+ var _a, _b, _c;
304
370
  log.info(mongoLogId(1001000016), this._logCtx(), 'Disconnecting');
305
371
  try {
306
- await ((_a = this._client) === null || _a === void 0 ? void 0 : _a.close(true).catch((err) => debug('failed to close MongoClient', err)));
307
- await ((_b = this._tunnel) === null || _b === void 0 ? void 0 : _b.close().catch((err) => debug('failed to close tunnel', err)));
372
+ await Promise.all([
373
+ (_a = this._metadataClient) === null || _a === void 0 ? void 0 : _a.close(true).catch((err) => debug('failed to close MongoClient', err)),
374
+ this._crudClient !== this._metadataClient &&
375
+ ((_b = this._crudClient) === null || _b === void 0 ? void 0 : _b.close(true).catch((err) => debug('failed to close MongoClient', err))),
376
+ (_c = this._tunnel) === null || _c === void 0 ? void 0 : _c.close().catch((err) => debug('failed to close tunnel', err)),
377
+ ]);
308
378
  }
309
379
  finally {
310
380
  this._cleanup();
@@ -313,7 +383,7 @@ class DataService extends events_1.EventEmitter {
313
383
  }
314
384
  dropCollection(ns, callback) {
315
385
  const logop = this._startLogOp(mongoLogId(1001000059), 'Running dropCollection', { ns });
316
- this._collection(ns).drop((error, result) => {
386
+ this._collection(ns, 'CRUD').drop((error, result) => {
317
387
  logop(error, result);
318
388
  if (error) {
319
389
  return callback(this._translateMessage(error));
@@ -323,7 +393,7 @@ class DataService extends events_1.EventEmitter {
323
393
  }
324
394
  dropDatabase(name, callback) {
325
395
  const logop = this._startLogOp(mongoLogId(1001000040), 'Running dropDatabase', { db: name });
326
- this._initializedClient
396
+ this._initializedClient('CRUD')
327
397
  .db(this._databaseName(name))
328
398
  .dropDatabase((error, result) => {
329
399
  logop(error, result);
@@ -335,7 +405,7 @@ class DataService extends events_1.EventEmitter {
335
405
  }
336
406
  dropIndex(ns, name, callback) {
337
407
  const logop = this._startLogOp(mongoLogId(1001000060), 'Running dropIndex', { ns, name });
338
- this._collection(ns).dropIndex(name, (error, result) => {
408
+ this._collection(ns, 'CRUD').dropIndex(name, (error, result) => {
339
409
  logop(error, result);
340
410
  if (error) {
341
411
  return callback(this._translateMessage(error));
@@ -352,7 +422,7 @@ class DataService extends events_1.EventEmitter {
352
422
  callback = options;
353
423
  options = undefined;
354
424
  }
355
- const cursor = this._collection(ns).aggregate(pipeline, options);
425
+ const cursor = this._collection(ns, 'CRUD').aggregate(pipeline, options);
356
426
  if ((0, lodash_1.isFunction)(callback)) {
357
427
  process.nextTick(callback, null, cursor);
358
428
  return;
@@ -363,7 +433,7 @@ class DataService extends events_1.EventEmitter {
363
433
  const logop = this._startLogOp(mongoLogId(1001000042), 'Running find', {
364
434
  ns,
365
435
  });
366
- const cursor = this._collection(ns).find(filter, options);
436
+ const cursor = this._collection(ns, 'CRUD').find(filter, options);
367
437
  cursor.toArray((error, documents) => {
368
438
  logop(error);
369
439
  if (error) {
@@ -375,11 +445,11 @@ class DataService extends events_1.EventEmitter {
375
445
  fetch(ns, filter, options) {
376
446
  const logop = this._startLogOp(mongoLogId(1001000043), 'Running raw find', { ns });
377
447
  logop(null);
378
- return this._collection(ns).find(filter, options);
448
+ return this._collection(ns, 'CRUD').find(filter, options);
379
449
  }
380
450
  findOneAndReplace(ns, filter, replacement, options, callback) {
381
451
  const logop = this._startLogOp(mongoLogId(1001000044), 'Running findOneAndReplace', { ns });
382
- this._collection(ns).findOneAndReplace(filter, replacement, options, (error, result) => {
452
+ this._collection(ns, 'CRUD').findOneAndReplace(filter, replacement, options, (error, result) => {
383
453
  logop(error);
384
454
  if (error) {
385
455
  return callback(this._translateMessage(error));
@@ -389,7 +459,7 @@ class DataService extends events_1.EventEmitter {
389
459
  }
390
460
  findOneAndUpdate(ns, filter, update, options, callback) {
391
461
  const logop = this._startLogOp(mongoLogId(1001000045), 'Running findOneAndUpdate', { ns });
392
- this._collection(ns).findOneAndUpdate(filter, update, options, (error, result) => {
462
+ this._collection(ns, 'CRUD').findOneAndUpdate(filter, update, options, (error, result) => {
393
463
  logop(error);
394
464
  if (error) {
395
465
  return callback(this._translateMessage(error));
@@ -399,7 +469,7 @@ class DataService extends events_1.EventEmitter {
399
469
  }
400
470
  explain(ns, filter, options, callback) {
401
471
  const logop = this._startLogOp(mongoLogId(1001000046), 'Running find explain', { ns });
402
- this._collection(ns)
472
+ this._collection(ns, 'CRUD')
403
473
  .find(filter, options)
404
474
  .explain((error, explanation) => {
405
475
  logop(error);
@@ -411,7 +481,7 @@ class DataService extends events_1.EventEmitter {
411
481
  }
412
482
  indexes(ns, options, callback) {
413
483
  const logop = this._startLogOp(mongoLogId(1001000047), 'Listing indexes', { ns });
414
- getIndexes(this._initializedClient, ns, (error, data) => {
484
+ getIndexes(this._initializedClient('META'), ns, (error, data) => {
415
485
  logop(error);
416
486
  if (error) {
417
487
  return callback(this._translateMessage(error));
@@ -421,7 +491,10 @@ class DataService extends events_1.EventEmitter {
421
491
  }
422
492
  async instance() {
423
493
  try {
424
- const instanceData = await (0, instance_detail_helper_1.getInstance)(this._initializedClient);
494
+ const instanceData = {
495
+ ...(await (0, instance_detail_helper_1.getInstance)(this._initializedClient('META'))),
496
+ csfleMode: this.getCSFLEMode(),
497
+ };
425
498
  log.info(mongoLogId(1001000024), this._logCtx(), 'Fetched instance information', {
426
499
  serverVersion: instanceData.build.version,
427
500
  genuineMongoDB: instanceData.genuineMongoDB,
@@ -436,7 +509,7 @@ class DataService extends events_1.EventEmitter {
436
509
  }
437
510
  insertOne(ns, doc, options, callback) {
438
511
  const logop = this._startLogOp(mongoLogId(1001000048), 'Running insertOne', { ns });
439
- this._collection(ns).insertOne(doc, options, (error, result) => {
512
+ this._collection(ns, 'CRUD').insertOne(doc, options, (error, result) => {
440
513
  logop(error, { acknowledged: result === null || result === void 0 ? void 0 : result.acknowledged });
441
514
  if (error) {
442
515
  return callback(this._translateMessage(error));
@@ -446,7 +519,7 @@ class DataService extends events_1.EventEmitter {
446
519
  }
447
520
  insertMany(ns, docs, options, callback) {
448
521
  const logop = this._startLogOp(mongoLogId(1001000049), 'Running insertOne', { ns });
449
- this._collection(ns).insertMany(docs, options, (error, result) => {
522
+ this._collection(ns, 'CRUD').insertMany(docs, options, (error, result) => {
450
523
  logop(error, {
451
524
  acknowledged: result === null || result === void 0 ? void 0 : result.acknowledged,
452
525
  insertedCount: result === null || result === void 0 ? void 0 : result.insertedCount,
@@ -458,12 +531,12 @@ class DataService extends events_1.EventEmitter {
458
531
  });
459
532
  }
460
533
  putMany(ns, docs, options) {
461
- return this._collection(ns).insertMany(docs, options);
534
+ return this._collection(ns, 'CRUD').insertMany(docs, options);
462
535
  }
463
536
  updateCollection(ns, flags, callback) {
464
537
  const logop = this._startLogOp(mongoLogId(1001000050), 'Running updateCollection', { ns });
465
538
  const collectionName = this._collectionName(ns);
466
- const db = this._initializedClient.db(this._databaseName(ns));
539
+ const db = this._initializedClient('CRUD').db(this._databaseName(ns));
467
540
  const command = {
468
541
  collMod: collectionName,
469
542
  ...flags,
@@ -478,7 +551,7 @@ class DataService extends events_1.EventEmitter {
478
551
  }
479
552
  updateOne(ns, filter, update, options, callback) {
480
553
  const logop = this._startLogOp(mongoLogId(1001000051), 'Running updateOne', { ns });
481
- this._collection(ns).updateOne(filter, update, options, (error, result) => {
554
+ this._collection(ns, 'CRUD').updateOne(filter, update, options, (error, result) => {
482
555
  logop(error, result);
483
556
  if (error) {
484
557
  return callback(this._translateMessage(error));
@@ -488,7 +561,7 @@ class DataService extends events_1.EventEmitter {
488
561
  }
489
562
  updateMany(ns, filter, update, options, callback) {
490
563
  const logop = this._startLogOp(mongoLogId(1001000052), 'Running updateMany', { ns });
491
- this._collection(ns).updateMany(filter, update, options, (error, result) => {
564
+ this._collection(ns, 'CRUD').updateMany(filter, update, options, (error, result) => {
492
565
  logop(error, result);
493
566
  if (error) {
494
567
  return callback(this._translateMessage(error));
@@ -498,13 +571,13 @@ class DataService extends events_1.EventEmitter {
498
571
  }
499
572
  currentOp(includeAll, callback) {
500
573
  const logop = this._startLogOp(mongoLogId(1001000053), 'Running currentOp');
501
- this._initializedClient
574
+ this._initializedClient('META')
502
575
  .db('admin')
503
576
  .command({ currentOp: 1, $all: includeAll }, (error, result) => {
504
577
  logop(error);
505
578
  if (error) {
506
579
  const logop = this._startLogOp(mongoLogId(1001000054), 'Searching $cmd.sys.inprog manually');
507
- this._initializedClient
580
+ this._initializedClient('META')
508
581
  .db('admin')
509
582
  .collection('$cmd.sys.inprog')
510
583
  .findOne({ $all: includeAll }, (error2, result2) => {
@@ -524,7 +597,10 @@ class DataService extends events_1.EventEmitter {
524
597
  }
525
598
  serverstats(callback) {
526
599
  const logop = this._startLogOp(mongoLogId(1001000061), 'Running serverStats');
527
- this._defaultDb.admin().serverStatus((error, result) => {
600
+ this._initializedClient('META')
601
+ .db()
602
+ .admin()
603
+ .serverStatus((error, result) => {
528
604
  logop(error);
529
605
  if (error) {
530
606
  return callback(this._translateMessage(error));
@@ -534,7 +610,10 @@ class DataService extends events_1.EventEmitter {
534
610
  }
535
611
  top(callback) {
536
612
  const logop = this._startLogOp(mongoLogId(1001000062), 'Running top');
537
- this._defaultDb.admin().command({ top: 1 }, (error, result) => {
613
+ this._initializedClient('META')
614
+ .db()
615
+ .admin()
616
+ .command({ top: 1 }, (error, result) => {
538
617
  logop(error);
539
618
  if (error) {
540
619
  return callback(this._translateMessage(error));
@@ -551,7 +630,7 @@ class DataService extends events_1.EventEmitter {
551
630
  stages: pipeline.map((stage) => Object.keys(stage)[0]),
552
631
  options,
553
632
  });
554
- this._initializedClient
633
+ this._initializedClient('CRUD')
555
634
  .db(this._databaseName(sourceNs))
556
635
  .createCollection(name, options, (error, result) => {
557
636
  logop(error, result);
@@ -568,7 +647,7 @@ class DataService extends events_1.EventEmitter {
568
647
  collMod: name,
569
648
  ...options,
570
649
  };
571
- const db = this._initializedClient.db(this._databaseName(sourceNs));
650
+ const db = this._initializedClient('META').db(this._databaseName(sourceNs));
572
651
  const logop = this._startLogOp(mongoLogId(1001000056), 'Running updateView', {
573
652
  name,
574
653
  sourceNs,
@@ -608,21 +687,30 @@ class DataService extends events_1.EventEmitter {
608
687
  ...options,
609
688
  });
610
689
  }
611
- startSession() {
612
- return this._initializedClient.startSession();
690
+ startSession(clientType) {
691
+ const session = this._initializedClient(clientType).startSession();
692
+ session[kSessionClientType] = clientType;
693
+ return session;
613
694
  }
614
695
  killSessions(sessions) {
615
- return this._initializedClient.db('admin').command({
616
- killSessions: Array.isArray(sessions)
617
- ? sessions.map((s) => s.id)
618
- : [sessions.id],
696
+ const sessionsArray = Array.isArray(sessions) ? sessions : [sessions];
697
+ const clientTypes = new Set(sessionsArray.map((s) => s[kSessionClientType]));
698
+ if (clientTypes.size !== 1) {
699
+ throw new Error(`Cannot kill sessions without a specific client type: [${[
700
+ ...clientTypes,
701
+ ].join(', ')}]`);
702
+ }
703
+ const [clientType] = clientTypes;
704
+ return this._initializedClient(clientType)
705
+ .db('admin')
706
+ .command({
707
+ killSessions: sessionsArray.map((s) => s.id),
619
708
  });
620
709
  }
621
710
  isConnected() {
622
- return !!this._client;
711
+ return !!this._metadataClient;
623
712
  }
624
713
  setupListeners(client) {
625
- this._client = client;
626
714
  if (client) {
627
715
  client.on('serverDescriptionChanged', (evt) => {
628
716
  var _a, _b;
@@ -743,19 +831,28 @@ class DataService extends events_1.EventEmitter {
743
831
  });
744
832
  }
745
833
  }
746
- get _initializedClient() {
747
- if (!this._client) {
748
- throw new Error('client not yet initialized');
834
+ _initializedClient(type) {
835
+ if (type !== 'CRUD' && type !== 'META') {
836
+ throw new Error(`Invalid client type: ${type}`);
749
837
  }
750
- return this._client;
838
+ const client = type === 'CRUD' && this._useCRUDClient
839
+ ? this._crudClient
840
+ : this._metadataClient;
841
+ if (!client) {
842
+ throw new Error('Client not yet initialized');
843
+ }
844
+ return client;
751
845
  }
752
- get _defaultDb() {
753
- return this._initializedClient.db();
846
+ getCSFLECollectionTracker() {
847
+ if (!this._csfleCollectionTracker) {
848
+ throw new Error('Client not yet initialized');
849
+ }
850
+ return this._csfleCollectionTracker;
754
851
  }
755
852
  async databaseStats(name) {
756
853
  const logop = this._startLogOp(mongoLogId(1001000057), 'Running databaseStats', { db: name });
757
854
  try {
758
- const db = this._initializedClient.db(name);
855
+ const db = this._initializedClient('META').db(name);
759
856
  const stats = await (0, run_command_1.runCommand)(db, { dbStats: 1 });
760
857
  const normalized = (0, instance_detail_helper_1.adaptDatabaseInfo)(stats);
761
858
  return { name, ...normalized };
@@ -809,8 +906,8 @@ class DataService extends events_1.EventEmitter {
809
906
  collections: db.collections,
810
907
  };
811
908
  }
812
- _collection(ns) {
813
- return this._initializedClient
909
+ _collection(ns, type) {
910
+ return this._initializedClient(type)
814
911
  .db(this._databaseName(ns))
815
912
  .collection(this._collectionName(ns));
816
913
  }
@@ -841,10 +938,11 @@ class DataService extends events_1.EventEmitter {
841
938
  return error;
842
939
  }
843
940
  _cleanup() {
844
- if (this._client) {
845
- this._client.removeAllListeners();
846
- }
847
- this._client = undefined;
941
+ var _a, _b, _c, _d;
942
+ (_b = (_a = this._metadataClient) === null || _a === void 0 ? void 0 : _a.removeAllListeners) === null || _b === void 0 ? void 0 : _b.call(_a);
943
+ (_d = (_c = this._crudClient) === null || _c === void 0 ? void 0 : _c.removeAllListeners) === null || _d === void 0 ? void 0 : _d.call(_c);
944
+ this._metadataClient = undefined;
945
+ this._crudClient = undefined;
848
946
  this._tunnel = undefined;
849
947
  this._mongoClientConnectionOptions = undefined;
850
948
  this._isWritable = false;
@@ -874,6 +972,57 @@ class DataService extends events_1.EventEmitter {
874
972
  }
875
973
  };
876
974
  }
975
+ configuredKMSProviders() {
976
+ var _a;
977
+ return (0, instance_detail_helper_1.configuredKMSProviders)((_a = this._connectionOptions.fleOptions) === null || _a === void 0 ? void 0 : _a.autoEncryption);
978
+ }
979
+ _csfleLogInformation(fleOptions) {
980
+ var _a, _b, _c;
981
+ const kmsProviders = (0, instance_detail_helper_1.configuredKMSProviders)(fleOptions === null || fleOptions === void 0 ? void 0 : fleOptions.autoEncryption);
982
+ if (kmsProviders.length === 0)
983
+ return null;
984
+ return {
985
+ storeCredentials: fleOptions === null || fleOptions === void 0 ? void 0 : fleOptions.storeCredentials,
986
+ encryptedFieldsMapNamespaces: Object.keys({
987
+ ...(_a = fleOptions === null || fleOptions === void 0 ? void 0 : fleOptions.autoEncryption) === null || _a === void 0 ? void 0 : _a.encryptedFieldsMap,
988
+ ...(_b = fleOptions === null || fleOptions === void 0 ? void 0 : fleOptions.autoEncryption) === null || _b === void 0 ? void 0 : _b.schemaMap,
989
+ }),
990
+ keyVaultNamespace: (_c = fleOptions === null || fleOptions === void 0 ? void 0 : fleOptions.autoEncryption) === null || _c === void 0 ? void 0 : _c.keyVaultNamespace,
991
+ kmsProviders,
992
+ };
993
+ }
994
+ async createDataKey(provider, options) {
995
+ const logop = this._startLogOp(mongoLogId(1001000123), 'Running createDataKey', { provider });
996
+ const clientEncryption = this._getClientEncryption();
997
+ let result;
998
+ try {
999
+ result = await clientEncryption.createDataKey(provider, options !== null && options !== void 0 ? options : {});
1000
+ }
1001
+ catch (err) {
1002
+ logop(err);
1003
+ throw err;
1004
+ }
1005
+ logop(null);
1006
+ return result;
1007
+ }
1008
+ _getClientEncryption() {
1009
+ const crudClient = this._initializedClient('CRUD');
1010
+ const autoEncryptionOptions = crudClient.options.autoEncryption;
1011
+ const { proxyHost, proxyPort, proxyUsername, proxyPassword } = crudClient.options;
1012
+ return new ClientEncryption(crudClient, {
1013
+ keyVaultNamespace: autoEncryptionOptions.keyVaultNamespace,
1014
+ kmsProviders: autoEncryptionOptions.kmsProviders,
1015
+ tlsOptions: autoEncryptionOptions.tlsOptions,
1016
+ proxyOptions: proxyHost
1017
+ ? {
1018
+ proxyHost,
1019
+ proxyPort,
1020
+ proxyUsername,
1021
+ proxyPassword,
1022
+ }
1023
+ : undefined,
1024
+ });
1025
+ }
877
1026
  }
878
- exports.default = DataService;
1027
+ exports.DataServiceImpl = DataServiceImpl;
879
1028
  //# sourceMappingURL=data-service.js.map