mongodb-data-service 22.37.2 → 22.38.1

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.
@@ -137,7 +137,6 @@ function op(logId, pickLogAttrs = maybePickNs) {
137
137
  };
138
138
  }
139
139
  let DataServiceImpl = (() => {
140
- var _a;
141
140
  let _classSuper = logger_1.WithLogContext;
142
141
  let _instanceExtraInitializers = [];
143
142
  let _collectionStats_decorators;
@@ -188,1589 +187,1608 @@ let DataServiceImpl = (() => {
188
187
  let _startStreamProcessor_decorators;
189
188
  let _stopStreamProcessor_decorators;
190
189
  let _dropStreamProcessor_decorators;
191
- return _a = class DataServiceImpl extends _classSuper {
192
- _getOptionsWithFallbackReadPreference(options, executionOptions) {
193
- const readPreferencesOverride = isReadPreferenceSet(this._connectionOptions.connectionString)
194
- ? undefined
195
- : executionOptions?.fallbackReadPreference;
196
- if (!readPreferencesOverride) {
197
- return options;
190
+ return class DataServiceImpl extends _classSuper {
191
+ static {
192
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
193
+ _collectionStats_decorators = [op((0, logger_1.mongoLogId)(1_001_000_178), ([dbName, collName], result) => {
194
+ return { ns: `${dbName}.${collName}`, ...(result && { result }) };
195
+ })];
196
+ _collectionInfo_decorators = [op((0, logger_1.mongoLogId)(1_001_000_179))];
197
+ _killOp_decorators = [op((0, logger_1.mongoLogId)(1_001_000_031))];
198
+ __connectionStatus_decorators = [op((0, logger_1.mongoLogId)(1_001_000_100))];
199
+ _listCollections_decorators = [op((0, logger_1.mongoLogId)(1_001_000_032), ([databaseName, , options], colls) => {
200
+ return {
201
+ db: databaseName,
202
+ nameOnly: options?.nameOnly ?? false,
203
+ ...(colls && { collectionsCount: colls.length }),
204
+ };
205
+ })];
206
+ _listDatabases_decorators = [op((0, logger_1.mongoLogId)(1_001_000_033), ([options], dbs) => {
207
+ return {
208
+ nameOnly: options?.nameOnly ?? false,
209
+ ...(dbs && { databasesCount: dbs.length }),
210
+ };
211
+ })];
212
+ _estimatedCount_decorators = [op((0, logger_1.mongoLogId)(1_001_000_034), ([ns, options]) => {
213
+ return { ns, maxTimeMS: options?.maxTimeMS };
214
+ })];
215
+ _count_decorators = [op((0, logger_1.mongoLogId)(1_001_000_035))];
216
+ _createCollection_decorators = [op((0, logger_1.mongoLogId)(1_001_000_036), ([ns, options], result) => {
217
+ return { ns, options, ...(result && { result }) };
218
+ })];
219
+ _createIndex_decorators = [op((0, logger_1.mongoLogId)(1_001_000_037), ([ns, spec, options], result) => {
220
+ return { ns, spec, options, ...(result && { result }) };
221
+ })];
222
+ _deleteOne_decorators = [op((0, logger_1.mongoLogId)(1_001_000_038), ([ns], result) => {
223
+ return { ns, ...(result && { result }) };
224
+ })];
225
+ _deleteMany_decorators = [op((0, logger_1.mongoLogId)(1_001_000_039), ([ns], result) => {
226
+ return { ns, ...(result && { result }) };
227
+ })];
228
+ _dropCollection_decorators = [op((0, logger_1.mongoLogId)(1_001_000_059), ([ns], result) => {
229
+ return { ns, ...(result && { result }) };
230
+ })];
231
+ _renameCollection_decorators = [op((0, logger_1.mongoLogId)(1_001_000_276))];
232
+ _dropDatabase_decorators = [op((0, logger_1.mongoLogId)(1_001_000_040), ([db], result) => {
233
+ return { db, ...(result && { result }) };
234
+ })];
235
+ _dropIndex_decorators = [op((0, logger_1.mongoLogId)(1_001_000_182), ([ns, name], result) => {
236
+ return { ns, name, ...(result && { result }) };
237
+ })];
238
+ _isListSearchIndexesSupported_decorators = [op((0, logger_1.mongoLogId)(1_001_000_237))];
239
+ _getSearchIndexes_decorators = [op((0, logger_1.mongoLogId)(1_001_000_238))];
240
+ _createSearchIndex_decorators = [op((0, logger_1.mongoLogId)(1_001_000_239))];
241
+ _updateSearchIndex_decorators = [op((0, logger_1.mongoLogId)(1_001_000_240))];
242
+ _dropSearchIndex_decorators = [op((0, logger_1.mongoLogId)(1_001_000_241))];
243
+ _aggregateCursor_decorators = [op((0, logger_1.mongoLogId)(1_001_000_041), ([ns, pipeline, options]) => {
244
+ return {
245
+ ns,
246
+ stages: pipeline.map((stage) => Object.keys(stage)[0]),
247
+ maxTimeMS: options?.maxTimeMS,
248
+ };
249
+ })];
250
+ _aggregate_decorators = [op((0, logger_1.mongoLogId)(1_001_000_181), ([ns, pipeline, options]) => {
251
+ return {
252
+ ns,
253
+ stages: pipeline.map((stage) => Object.keys(stage)[0]),
254
+ maxTimeMS: options?.maxTimeMS,
255
+ };
256
+ })];
257
+ _find_decorators = [op((0, logger_1.mongoLogId)(1_001_000_060), ([ns, , options]) => {
258
+ return { ns, maxTimeMS: options?.maxTimeMS };
259
+ })];
260
+ _findCursor_decorators = [op((0, logger_1.mongoLogId)(1_001_000_043))];
261
+ _findOneAndReplace_decorators = [op((0, logger_1.mongoLogId)(1_001_000_044))];
262
+ _findOneAndUpdate_decorators = [op((0, logger_1.mongoLogId)(1_001_000_045))];
263
+ _updateOne_decorators = [op((0, logger_1.mongoLogId)(1_001_000_183))];
264
+ _replaceOne_decorators = [op((0, logger_1.mongoLogId)(1_001_000_191))];
265
+ _explainFind_decorators = [op((0, logger_1.mongoLogId)(1_001_000_046), ([ns, , , executionOptions]) => {
266
+ return {
267
+ ns,
268
+ verbosity: executionOptions?.explainVerbosity || mongodb_1.ExplainVerbosity.executionStats,
269
+ };
270
+ })];
271
+ _explainAggregate_decorators = [op((0, logger_1.mongoLogId)(1_001_000_177), ([ns, , , executionOptions]) => {
272
+ return {
273
+ ns,
274
+ verbosity: executionOptions?.explainVerbosity || mongodb_1.ExplainVerbosity.executionStats,
275
+ };
276
+ })];
277
+ _fetchShardKey_decorators = [op((0, logger_1.mongoLogId)(1_001_000_381))];
278
+ _indexes_decorators = [op((0, logger_1.mongoLogId)(1_001_000_047))];
279
+ _instance_decorators = [op((0, logger_1.mongoLogId)(1_001_000_024), (_, instanceData) => {
280
+ if (instanceData) {
281
+ return {
282
+ serverVersion: instanceData.build.version,
283
+ genuineMongoDB: instanceData.genuineMongoDB,
284
+ dataLake: instanceData.dataLake,
285
+ featureCompatibilityVersion: instanceData.featureCompatibilityVersion,
286
+ };
287
+ }
288
+ })];
289
+ _insertOne_decorators = [op((0, logger_1.mongoLogId)(1_001_000_048), ([ns], result) => {
290
+ return { ns, ...(result && { acknowledged: result.acknowledged }) };
291
+ })];
292
+ _insertMany_decorators = [op((0, logger_1.mongoLogId)(1_001_000_049), ([ns], result) => {
293
+ return {
294
+ ns,
295
+ ...(result && {
296
+ acknowledged: result.acknowledged,
297
+ insertedCount: result.insertedCount,
298
+ }),
299
+ };
300
+ })];
301
+ _updateCollection_decorators = [op((0, logger_1.mongoLogId)(1_001_000_050), ([ns], result) => {
302
+ return { ns, ...(result && { result }) };
303
+ })];
304
+ _currentOp_decorators = [op((0, logger_1.mongoLogId)(1_001_000_053))];
305
+ _serverStatus_decorators = [op((0, logger_1.mongoLogId)(1_001_000_061), (_, result) => {
306
+ return result ? { result } : undefined;
307
+ })];
308
+ _top_decorators = [op((0, logger_1.mongoLogId)(1_001_000_062), (_, result) => {
309
+ return result ? { result } : undefined;
310
+ })];
311
+ _createView_decorators = [op((0, logger_1.mongoLogId)(1_001_000_055), ([name, sourceNs, pipeline, options], result) => {
312
+ return {
313
+ name,
314
+ sourceNs,
315
+ stages: pipeline.map((stage) => Object.keys(stage)[0]),
316
+ options,
317
+ ...(result && { result }),
318
+ };
319
+ })];
320
+ _databaseStats_decorators = [op((0, logger_1.mongoLogId)(1_001_000_057))];
321
+ _previewUpdate_decorators = [op((0, logger_1.mongoLogId)(1_001_000_266))];
322
+ _createDataKey_decorators = [op((0, logger_1.mongoLogId)(1_001_000_123), ([provider]) => {
323
+ return { provider };
324
+ })];
325
+ _listStreamProcessors_decorators = [op((0, logger_1.mongoLogId)(1_001_000_284))];
326
+ _startStreamProcessor_decorators = [op((0, logger_1.mongoLogId)(1_001_000_285))];
327
+ _stopStreamProcessor_decorators = [op((0, logger_1.mongoLogId)(1_001_000_286))];
328
+ _dropStreamProcessor_decorators = [op((0, logger_1.mongoLogId)(1_001_000_287))];
329
+ __esDecorate(this, null, _collectionStats_decorators, { kind: "method", name: "collectionStats", static: false, private: false, access: { has: obj => "collectionStats" in obj, get: obj => obj.collectionStats }, metadata: _metadata }, null, _instanceExtraInitializers);
330
+ __esDecorate(this, null, _collectionInfo_decorators, { kind: "method", name: "collectionInfo", static: false, private: false, access: { has: obj => "collectionInfo" in obj, get: obj => obj.collectionInfo }, metadata: _metadata }, null, _instanceExtraInitializers);
331
+ __esDecorate(this, null, _killOp_decorators, { kind: "method", name: "killOp", static: false, private: false, access: { has: obj => "killOp" in obj, get: obj => obj.killOp }, metadata: _metadata }, null, _instanceExtraInitializers);
332
+ __esDecorate(this, null, __connectionStatus_decorators, { kind: "method", name: "_connectionStatus", static: false, private: false, access: { has: obj => "_connectionStatus" in obj, get: obj => obj._connectionStatus }, metadata: _metadata }, null, _instanceExtraInitializers);
333
+ __esDecorate(this, null, _listCollections_decorators, { kind: "method", name: "listCollections", static: false, private: false, access: { has: obj => "listCollections" in obj, get: obj => obj.listCollections }, metadata: _metadata }, null, _instanceExtraInitializers);
334
+ __esDecorate(this, null, _listDatabases_decorators, { kind: "method", name: "listDatabases", static: false, private: false, access: { has: obj => "listDatabases" in obj, get: obj => obj.listDatabases }, metadata: _metadata }, null, _instanceExtraInitializers);
335
+ __esDecorate(this, null, _estimatedCount_decorators, { kind: "method", name: "estimatedCount", static: false, private: false, access: { has: obj => "estimatedCount" in obj, get: obj => obj.estimatedCount }, metadata: _metadata }, null, _instanceExtraInitializers);
336
+ __esDecorate(this, null, _count_decorators, { kind: "method", name: "count", static: false, private: false, access: { has: obj => "count" in obj, get: obj => obj.count }, metadata: _metadata }, null, _instanceExtraInitializers);
337
+ __esDecorate(this, null, _createCollection_decorators, { kind: "method", name: "createCollection", static: false, private: false, access: { has: obj => "createCollection" in obj, get: obj => obj.createCollection }, metadata: _metadata }, null, _instanceExtraInitializers);
338
+ __esDecorate(this, null, _createIndex_decorators, { kind: "method", name: "createIndex", static: false, private: false, access: { has: obj => "createIndex" in obj, get: obj => obj.createIndex }, metadata: _metadata }, null, _instanceExtraInitializers);
339
+ __esDecorate(this, null, _deleteOne_decorators, { kind: "method", name: "deleteOne", static: false, private: false, access: { has: obj => "deleteOne" in obj, get: obj => obj.deleteOne }, metadata: _metadata }, null, _instanceExtraInitializers);
340
+ __esDecorate(this, null, _deleteMany_decorators, { kind: "method", name: "deleteMany", static: false, private: false, access: { has: obj => "deleteMany" in obj, get: obj => obj.deleteMany }, metadata: _metadata }, null, _instanceExtraInitializers);
341
+ __esDecorate(this, null, _dropCollection_decorators, { kind: "method", name: "dropCollection", static: false, private: false, access: { has: obj => "dropCollection" in obj, get: obj => obj.dropCollection }, metadata: _metadata }, null, _instanceExtraInitializers);
342
+ __esDecorate(this, null, _renameCollection_decorators, { kind: "method", name: "renameCollection", static: false, private: false, access: { has: obj => "renameCollection" in obj, get: obj => obj.renameCollection }, metadata: _metadata }, null, _instanceExtraInitializers);
343
+ __esDecorate(this, null, _dropDatabase_decorators, { kind: "method", name: "dropDatabase", static: false, private: false, access: { has: obj => "dropDatabase" in obj, get: obj => obj.dropDatabase }, metadata: _metadata }, null, _instanceExtraInitializers);
344
+ __esDecorate(this, null, _dropIndex_decorators, { kind: "method", name: "dropIndex", static: false, private: false, access: { has: obj => "dropIndex" in obj, get: obj => obj.dropIndex }, metadata: _metadata }, null, _instanceExtraInitializers);
345
+ __esDecorate(this, null, _isListSearchIndexesSupported_decorators, { kind: "method", name: "isListSearchIndexesSupported", static: false, private: false, access: { has: obj => "isListSearchIndexesSupported" in obj, get: obj => obj.isListSearchIndexesSupported }, metadata: _metadata }, null, _instanceExtraInitializers);
346
+ __esDecorate(this, null, _getSearchIndexes_decorators, { kind: "method", name: "getSearchIndexes", static: false, private: false, access: { has: obj => "getSearchIndexes" in obj, get: obj => obj.getSearchIndexes }, metadata: _metadata }, null, _instanceExtraInitializers);
347
+ __esDecorate(this, null, _createSearchIndex_decorators, { kind: "method", name: "createSearchIndex", static: false, private: false, access: { has: obj => "createSearchIndex" in obj, get: obj => obj.createSearchIndex }, metadata: _metadata }, null, _instanceExtraInitializers);
348
+ __esDecorate(this, null, _updateSearchIndex_decorators, { kind: "method", name: "updateSearchIndex", static: false, private: false, access: { has: obj => "updateSearchIndex" in obj, get: obj => obj.updateSearchIndex }, metadata: _metadata }, null, _instanceExtraInitializers);
349
+ __esDecorate(this, null, _dropSearchIndex_decorators, { kind: "method", name: "dropSearchIndex", static: false, private: false, access: { has: obj => "dropSearchIndex" in obj, get: obj => obj.dropSearchIndex }, metadata: _metadata }, null, _instanceExtraInitializers);
350
+ __esDecorate(this, null, _aggregateCursor_decorators, { kind: "method", name: "aggregateCursor", static: false, private: false, access: { has: obj => "aggregateCursor" in obj, get: obj => obj.aggregateCursor }, metadata: _metadata }, null, _instanceExtraInitializers);
351
+ __esDecorate(this, null, _aggregate_decorators, { kind: "method", name: "aggregate", static: false, private: false, access: { has: obj => "aggregate" in obj, get: obj => obj.aggregate }, metadata: _metadata }, null, _instanceExtraInitializers);
352
+ __esDecorate(this, null, _find_decorators, { kind: "method", name: "find", static: false, private: false, access: { has: obj => "find" in obj, get: obj => obj.find }, metadata: _metadata }, null, _instanceExtraInitializers);
353
+ __esDecorate(this, null, _findCursor_decorators, { kind: "method", name: "findCursor", static: false, private: false, access: { has: obj => "findCursor" in obj, get: obj => obj.findCursor }, metadata: _metadata }, null, _instanceExtraInitializers);
354
+ __esDecorate(this, null, _findOneAndReplace_decorators, { kind: "method", name: "findOneAndReplace", static: false, private: false, access: { has: obj => "findOneAndReplace" in obj, get: obj => obj.findOneAndReplace }, metadata: _metadata }, null, _instanceExtraInitializers);
355
+ __esDecorate(this, null, _findOneAndUpdate_decorators, { kind: "method", name: "findOneAndUpdate", static: false, private: false, access: { has: obj => "findOneAndUpdate" in obj, get: obj => obj.findOneAndUpdate }, metadata: _metadata }, null, _instanceExtraInitializers);
356
+ __esDecorate(this, null, _updateOne_decorators, { kind: "method", name: "updateOne", static: false, private: false, access: { has: obj => "updateOne" in obj, get: obj => obj.updateOne }, metadata: _metadata }, null, _instanceExtraInitializers);
357
+ __esDecorate(this, null, _replaceOne_decorators, { kind: "method", name: "replaceOne", static: false, private: false, access: { has: obj => "replaceOne" in obj, get: obj => obj.replaceOne }, metadata: _metadata }, null, _instanceExtraInitializers);
358
+ __esDecorate(this, null, _explainFind_decorators, { kind: "method", name: "explainFind", static: false, private: false, access: { has: obj => "explainFind" in obj, get: obj => obj.explainFind }, metadata: _metadata }, null, _instanceExtraInitializers);
359
+ __esDecorate(this, null, _explainAggregate_decorators, { kind: "method", name: "explainAggregate", static: false, private: false, access: { has: obj => "explainAggregate" in obj, get: obj => obj.explainAggregate }, metadata: _metadata }, null, _instanceExtraInitializers);
360
+ __esDecorate(this, null, _fetchShardKey_decorators, { kind: "method", name: "fetchShardKey", static: false, private: false, access: { has: obj => "fetchShardKey" in obj, get: obj => obj.fetchShardKey }, metadata: _metadata }, null, _instanceExtraInitializers);
361
+ __esDecorate(this, null, _indexes_decorators, { kind: "method", name: "indexes", static: false, private: false, access: { has: obj => "indexes" in obj, get: obj => obj.indexes }, metadata: _metadata }, null, _instanceExtraInitializers);
362
+ __esDecorate(this, null, _instance_decorators, { kind: "method", name: "instance", static: false, private: false, access: { has: obj => "instance" in obj, get: obj => obj.instance }, metadata: _metadata }, null, _instanceExtraInitializers);
363
+ __esDecorate(this, null, _insertOne_decorators, { kind: "method", name: "insertOne", static: false, private: false, access: { has: obj => "insertOne" in obj, get: obj => obj.insertOne }, metadata: _metadata }, null, _instanceExtraInitializers);
364
+ __esDecorate(this, null, _insertMany_decorators, { kind: "method", name: "insertMany", static: false, private: false, access: { has: obj => "insertMany" in obj, get: obj => obj.insertMany }, metadata: _metadata }, null, _instanceExtraInitializers);
365
+ __esDecorate(this, null, _updateCollection_decorators, { kind: "method", name: "updateCollection", static: false, private: false, access: { has: obj => "updateCollection" in obj, get: obj => obj.updateCollection }, metadata: _metadata }, null, _instanceExtraInitializers);
366
+ __esDecorate(this, null, _currentOp_decorators, { kind: "method", name: "currentOp", static: false, private: false, access: { has: obj => "currentOp" in obj, get: obj => obj.currentOp }, metadata: _metadata }, null, _instanceExtraInitializers);
367
+ __esDecorate(this, null, _serverStatus_decorators, { kind: "method", name: "serverStatus", static: false, private: false, access: { has: obj => "serverStatus" in obj, get: obj => obj.serverStatus }, metadata: _metadata }, null, _instanceExtraInitializers);
368
+ __esDecorate(this, null, _top_decorators, { kind: "method", name: "top", static: false, private: false, access: { has: obj => "top" in obj, get: obj => obj.top }, metadata: _metadata }, null, _instanceExtraInitializers);
369
+ __esDecorate(this, null, _createView_decorators, { kind: "method", name: "createView", static: false, private: false, access: { has: obj => "createView" in obj, get: obj => obj.createView }, metadata: _metadata }, null, _instanceExtraInitializers);
370
+ __esDecorate(this, null, _databaseStats_decorators, { kind: "method", name: "databaseStats", static: false, private: false, access: { has: obj => "databaseStats" in obj, get: obj => obj.databaseStats }, metadata: _metadata }, null, _instanceExtraInitializers);
371
+ __esDecorate(this, null, _previewUpdate_decorators, { kind: "method", name: "previewUpdate", static: false, private: false, access: { has: obj => "previewUpdate" in obj, get: obj => obj.previewUpdate }, metadata: _metadata }, null, _instanceExtraInitializers);
372
+ __esDecorate(this, null, _createDataKey_decorators, { kind: "method", name: "createDataKey", static: false, private: false, access: { has: obj => "createDataKey" in obj, get: obj => obj.createDataKey }, metadata: _metadata }, null, _instanceExtraInitializers);
373
+ __esDecorate(this, null, _listStreamProcessors_decorators, { kind: "method", name: "listStreamProcessors", static: false, private: false, access: { has: obj => "listStreamProcessors" in obj, get: obj => obj.listStreamProcessors }, metadata: _metadata }, null, _instanceExtraInitializers);
374
+ __esDecorate(this, null, _startStreamProcessor_decorators, { kind: "method", name: "startStreamProcessor", static: false, private: false, access: { has: obj => "startStreamProcessor" in obj, get: obj => obj.startStreamProcessor }, metadata: _metadata }, null, _instanceExtraInitializers);
375
+ __esDecorate(this, null, _stopStreamProcessor_decorators, { kind: "method", name: "stopStreamProcessor", static: false, private: false, access: { has: obj => "stopStreamProcessor" in obj, get: obj => obj.stopStreamProcessor }, metadata: _metadata }, null, _instanceExtraInitializers);
376
+ __esDecorate(this, null, _dropStreamProcessor_decorators, { kind: "method", name: "dropStreamProcessor", static: false, private: false, access: { has: obj => "dropStreamProcessor" in obj, get: obj => obj.dropStreamProcessor }, metadata: _metadata }, null, _instanceExtraInitializers);
377
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
378
+ }
379
+ _connectionOptions = __runInitializers(this, _instanceExtraInitializers);
380
+ _proxyOptions;
381
+ _isConnecting = false;
382
+ _mongoClientConnectionOptions;
383
+ // Use two separate clients in the CSFLE case, one with CSFLE
384
+ // enabled, one disabled. _initializedClient() can be used
385
+ // to fetch the right one. _useCRUDClient can be used to control
386
+ // this behavior after connecting, i.e. for disabling and
387
+ // enabling CSFLE on an already-connected DataService instance.
388
+ _metadataClient;
389
+ _crudClient;
390
+ _useCRUDClient = true;
391
+ _csfleCollectionTracker;
392
+ _tunnel;
393
+ _state;
394
+ _reauthenticationHandlers = new Set();
395
+ /**
396
+ * Stores the most recent topology description from the server's SDAM events:
397
+ * https://github.com/mongodb/specifications/blob/master/source/server-discovery-and-monitoring/server-discovery-and-monitoring-monitoring.rst#events
398
+ */
399
+ _lastSeenTopology = null;
400
+ _isWritable = false;
401
+ _id;
402
+ _emitter = new events_1.EventEmitter();
403
+ /**
404
+ * Directly used during data-service runtime, auto sets component and context
405
+ * with a connection id
406
+ */
407
+ _logger;
408
+ /**
409
+ * To be passed to the connect-mongo-client
410
+ */
411
+ _unboundLogger;
412
+ _getOptionsWithFallbackReadPreference(options, executionOptions) {
413
+ const readPreferencesOverride = isReadPreferenceSet(this._connectionOptions.connectionString)
414
+ ? undefined
415
+ : executionOptions?.fallbackReadPreference;
416
+ if (!readPreferencesOverride) {
417
+ return options;
418
+ }
419
+ return {
420
+ ...options,
421
+ readPreference: readPreferencesOverride,
422
+ };
423
+ }
424
+ constructor(connectionOptions, logger, proxyOptions) {
425
+ super();
426
+ this._id = id++;
427
+ this._connectionOptions = connectionOptions;
428
+ this._proxyOptions = proxyOptions ?? {};
429
+ const logComponent = 'COMPASS-DATA-SERVICE';
430
+ const logCtx = `Connection ${this._id}`;
431
+ this._logger = {
432
+ debug: (logId, ...args) => {
433
+ return logger?.debug(logComponent, logId, logCtx, ...args);
434
+ },
435
+ info: (logId, ...args) => {
436
+ return logger?.info(logComponent, logId, logCtx, ...args);
437
+ },
438
+ warn: (logId, ...args) => {
439
+ return logger?.warn(logComponent, logId, logCtx, ...args);
440
+ },
441
+ error: (logId, ...args) => {
442
+ return logger?.error(logComponent, logId, logCtx, ...args);
443
+ },
444
+ fatal: (logId, ...args) => {
445
+ return logger?.fatal(logComponent, logId, logCtx, ...args);
446
+ },
447
+ };
448
+ if (logger) {
449
+ this._unboundLogger = Object.assign(logger, { mongoLogId: logger_1.mongoLogId });
450
+ }
451
+ }
452
+ get id() {
453
+ return this._id;
454
+ }
455
+ on(...args) {
456
+ this._emitter.on(...args);
457
+ return this;
458
+ }
459
+ off(...args) {
460
+ this._emitter.off(...args);
461
+ return this;
462
+ }
463
+ removeListener(...args) {
464
+ this._emitter.off(...args);
465
+ return this;
466
+ }
467
+ once(...args) {
468
+ this._emitter.once(...args);
469
+ return this;
470
+ }
471
+ getMongoClientConnectionOptions() {
472
+ // `notifyDeviceFlow` is a function which cannot be serialized for inclusion
473
+ // in the shell, `signal` is an abortSignal, and `allowedFlows` is turned
474
+ // into a function by the connection code.
475
+ return (0, lodash_1.omit)(this._mongoClientConnectionOptions, 'options.oidc.notifyDeviceFlow', 'options.oidc.signal', 'options.oidc.allowedFlows', 'options.oidc.customFetch', 'options.oidc.customHttpOptions');
476
+ }
477
+ getConnectionOptions() {
478
+ return this._connectionOptions;
479
+ }
480
+ getConnectionString() {
481
+ return new mongodb_connection_string_url_1.default(this._connectionOptions.connectionString);
482
+ }
483
+ setCSFLEEnabled(enabled) {
484
+ this._logger.info((0, logger_1.mongoLogId)(1_001_000_117), 'Setting CSFLE mode', {
485
+ enabled,
486
+ });
487
+ this._useCRUDClient = enabled;
488
+ }
489
+ getCSFLEMode() {
490
+ if (this._crudClient && (0, instance_detail_helper_2.checkIsCSFLEConnection)(this._crudClient)) {
491
+ if (this._useCRUDClient) {
492
+ return 'enabled';
493
+ }
494
+ else {
495
+ return 'disabled';
198
496
  }
199
- return {
200
- ...options,
201
- readPreference: readPreferencesOverride,
202
- };
203
497
  }
204
- constructor(connectionOptions, logger, proxyOptions) {
205
- super();
206
- this._connectionOptions = __runInitializers(this, _instanceExtraInitializers);
207
- this._isConnecting = false;
208
- this._useCRUDClient = true;
209
- this._reauthenticationHandlers = new Set();
210
- /**
211
- * Stores the most recent topology description from the server's SDAM events:
212
- * https://github.com/mongodb/specifications/blob/master/source/server-discovery-and-monitoring/server-discovery-and-monitoring-monitoring.rst#events
213
- */
214
- this._lastSeenTopology = null;
215
- this._isWritable = false;
216
- this._emitter = new events_1.EventEmitter();
217
- this._id = id++;
218
- this._connectionOptions = connectionOptions;
219
- this._proxyOptions = proxyOptions ?? {};
220
- const logComponent = 'COMPASS-DATA-SERVICE';
221
- const logCtx = `Connection ${this._id}`;
222
- this._logger = {
223
- debug: (logId, ...args) => {
224
- return logger?.debug(logComponent, logId, logCtx, ...args);
225
- },
226
- info: (logId, ...args) => {
227
- return logger?.info(logComponent, logId, logCtx, ...args);
498
+ else {
499
+ return 'unavailable';
500
+ }
501
+ }
502
+ async collectionStats(databaseName, collectionName, collectionType) {
503
+ const ns = `${databaseName}.${collectionName}`;
504
+ try {
505
+ const coll = this._collection(ns, 'CRUD');
506
+ // Build the aggregation pipeline dynamically based on collection type
507
+ const groupStage = {
508
+ _id: null,
509
+ capped: { $first: '$storageStats.capped' },
510
+ count: { $sum: '$storageStats.count' },
511
+ size: { $sum: { $toDouble: '$storageStats.size' } },
512
+ storageSize: {
513
+ $sum: { $toDouble: '$storageStats.storageSize' },
228
514
  },
229
- warn: (logId, ...args) => {
230
- return logger?.warn(logComponent, logId, logCtx, ...args);
515
+ totalIndexSize: {
516
+ $sum: { $toDouble: '$storageStats.totalIndexSize' },
231
517
  },
232
- error: (logId, ...args) => {
233
- return logger?.error(logComponent, logId, logCtx, ...args);
518
+ freeStorageSize: {
519
+ $sum: { $toDouble: '$storageStats.freeStorageSize' },
234
520
  },
235
- fatal: (logId, ...args) => {
236
- return logger?.fatal(logComponent, logId, logCtx, ...args);
521
+ unscaledCollSize: {
522
+ $sum: {
523
+ $multiply: [
524
+ { $toDouble: '$storageStats.avgObjSize' },
525
+ { $toDouble: '$storageStats.count' },
526
+ ],
527
+ },
237
528
  },
529
+ nindexes: { $max: '$storageStats.nindexes' },
238
530
  };
239
- if (logger) {
240
- this._unboundLogger = Object.assign(logger, { mongoLogId: logger_1.mongoLogId });
241
- }
242
- }
243
- get id() {
244
- return this._id;
245
- }
246
- on(...args) {
247
- this._emitter.on(...args);
248
- return this;
249
- }
250
- off(...args) {
251
- this._emitter.off(...args);
252
- return this;
253
- }
254
- removeListener(...args) {
255
- this._emitter.off(...args);
256
- return this;
257
- }
258
- once(...args) {
259
- this._emitter.once(...args);
260
- return this;
261
- }
262
- getMongoClientConnectionOptions() {
263
- // `notifyDeviceFlow` is a function which cannot be serialized for inclusion
264
- // in the shell, `signal` is an abortSignal, and `allowedFlows` is turned
265
- // into a function by the connection code.
266
- return (0, lodash_1.omit)(this._mongoClientConnectionOptions, 'options.oidc.notifyDeviceFlow', 'options.oidc.signal', 'options.oidc.allowedFlows', 'options.oidc.customFetch', 'options.oidc.customHttpOptions');
267
- }
268
- getConnectionOptions() {
269
- return this._connectionOptions;
270
- }
271
- getConnectionString() {
272
- return new mongodb_connection_string_url_1.default(this._connectionOptions.connectionString);
273
- }
274
- setCSFLEEnabled(enabled) {
275
- this._logger.info((0, logger_1.mongoLogId)(1_001_000_117), 'Setting CSFLE mode', {
276
- enabled,
277
- });
278
- this._useCRUDClient = enabled;
279
- }
280
- getCSFLEMode() {
281
- if (this._crudClient && (0, instance_detail_helper_2.checkIsCSFLEConnection)(this._crudClient)) {
282
- if (this._useCRUDClient) {
283
- return 'enabled';
284
- }
285
- else {
286
- return 'disabled';
287
- }
288
- }
289
- else {
290
- return 'unavailable';
291
- }
292
- }
293
- async collectionStats(databaseName, collectionName, collectionType) {
294
- const ns = `${databaseName}.${collectionName}`;
295
- try {
296
- const coll = this._collection(ns, 'CRUD');
297
- // Build the aggregation pipeline dynamically based on collection type
298
- const groupStage = {
299
- _id: null,
300
- capped: { $first: '$storageStats.capped' },
301
- count: { $sum: '$storageStats.count' },
302
- size: { $sum: { $toDouble: '$storageStats.size' } },
303
- storageSize: {
304
- $sum: { $toDouble: '$storageStats.storageSize' },
305
- },
306
- totalIndexSize: {
307
- $sum: { $toDouble: '$storageStats.totalIndexSize' },
308
- },
309
- freeStorageSize: {
310
- $sum: { $toDouble: '$storageStats.freeStorageSize' },
311
- },
312
- unscaledCollSize: {
313
- $sum: {
314
- $multiply: [
315
- { $toDouble: '$storageStats.avgObjSize' },
316
- { $toDouble: '$storageStats.count' },
317
- ],
318
- },
319
- },
320
- nindexes: { $max: '$storageStats.nindexes' },
531
+ // Only extract bucket statistics for time series collections
532
+ if (collectionType === 'timeseries') {
533
+ groupStage.timeseriesBucketCount = {
534
+ $first: '$storageStats.timeseries.bucketCount',
321
535
  };
322
- // Only extract bucket statistics for time series collections
323
- if (collectionType === 'timeseries') {
324
- groupStage.timeseriesBucketCount = {
325
- $first: '$storageStats.timeseries.bucketCount',
326
- };
327
- groupStage.timeseriesAvgBucketSize = {
328
- $first: '$storageStats.timeseries.avgBucketSize',
329
- };
330
- }
331
- const addFieldsStage = {
332
- // `avgObjSize` is the average of per-shard `avgObjSize` weighted by `count`
333
- __proto__: null,
334
- avgObjSize: {
335
- $cond: {
336
- if: { $ne: ['$count', 0] },
337
- then: {
338
- $divide: ['$unscaledCollSize', { $toDouble: '$count' }],
339
- },
340
- else: 0,
536
+ groupStage.timeseriesAvgBucketSize = {
537
+ $first: '$storageStats.timeseries.avgBucketSize',
538
+ };
539
+ }
540
+ const addFieldsStage = {
541
+ // `avgObjSize` is the average of per-shard `avgObjSize` weighted by `count`
542
+ __proto__: null,
543
+ avgObjSize: {
544
+ $cond: {
545
+ if: { $ne: ['$count', 0] },
546
+ then: {
547
+ $divide: ['$unscaledCollSize', { $toDouble: '$count' }],
341
548
  },
549
+ else: 0,
342
550
  },
343
- };
344
- // Only calculate bucket stats for time series collections
345
- if (collectionType === 'timeseries') {
346
- addFieldsStage.bucket_count = '$timeseriesBucketCount';
347
- addFieldsStage.avg_bucket_size = '$timeseriesAvgBucketSize';
348
- }
349
- const collStats = await coll
350
- .aggregate([
351
- { $collStats: { storageStats: {} } },
352
- { $group: groupStage },
353
- { $addFields: addFieldsStage },
354
- ], { enableUtf8Validation: false })
355
- .toArray();
356
- if (!collStats || collStats[0] === undefined) {
357
- throw new Error(`Error running $collStats aggregation stage on ${ns}`);
358
- }
359
- collStats[0].ns = ns;
360
- return this._buildCollectionStats(databaseName, collectionName, collStats[0]);
551
+ },
552
+ };
553
+ // Only calculate bucket stats for time series collections
554
+ if (collectionType === 'timeseries') {
555
+ addFieldsStage.bucket_count = '$timeseriesBucketCount';
556
+ addFieldsStage.avg_bucket_size = '$timeseriesAvgBucketSize';
361
557
  }
362
- catch (error) {
363
- const message = error.message;
364
- if (
365
- // We ignore errors for fetching collStats when requesting on an
366
- // unsupported collection type: either a view or a ADF
367
- message.includes('not valid for Data Lake') ||
368
- message.includes('is a view, not a collection') ||
369
- // When trying to fetch collectionStats for a collection whose db
370
- // does not exist or the collection itself does not exist, the
371
- // server throws an error. This happens because we show collections
372
- // to the user from their privileges.
373
- message.includes(`Database [${databaseName}] not found`) ||
374
- message.includes(`Collection [${databaseName}.${collectionName}] not found`)) {
375
- return this._buildCollectionStats(databaseName, collectionName, {});
376
- }
377
- throw error;
558
+ const collStats = await coll
559
+ .aggregate([
560
+ { $collStats: { storageStats: {} } },
561
+ { $group: groupStage },
562
+ { $addFields: addFieldsStage },
563
+ ], { enableUtf8Validation: false })
564
+ .toArray();
565
+ if (!collStats || collStats[0] === undefined) {
566
+ throw new Error(`Error running $collStats aggregation stage on ${ns}`);
378
567
  }
568
+ collStats[0].ns = ns;
569
+ return this._buildCollectionStats(databaseName, collectionName, collStats[0]);
379
570
  }
380
- async collectionInfo(dbName, collName) {
381
- const [collInfo] = await this._listCollections(dbName, { name: collName });
382
- return ((0, instance_detail_helper_2.adaptCollectionInfo)({
383
- db: dbName,
384
- ...collInfo,
385
- }) ?? null);
386
- }
387
- async killOp(id, comment) {
388
- const db = this._database('admin', 'META');
389
- return (0, run_command_1.runCommand)(db, { killOp: 1, id, comment }, { enableUtf8Validation: false });
390
- }
391
- isWritable() {
392
- return this._isWritable;
393
- }
394
- isMongos() {
395
- return this.getCurrentTopologyType() === 'Sharded';
571
+ catch (error) {
572
+ const message = error.message;
573
+ if (
574
+ // We ignore errors for fetching collStats when requesting on an
575
+ // unsupported collection type: either a view or a ADF
576
+ message.includes('not valid for Data Lake') ||
577
+ message.includes('is a view, not a collection') ||
578
+ // When trying to fetch collectionStats for a collection whose db
579
+ // does not exist or the collection itself does not exist, the
580
+ // server throws an error. This happens because we show collections
581
+ // to the user from their privileges.
582
+ message.includes(`Database [${databaseName}] not found`) ||
583
+ message.includes(`Collection [${databaseName}.${collectionName}] not found`)) {
584
+ return this._buildCollectionStats(databaseName, collectionName, {});
585
+ }
586
+ throw error;
396
587
  }
397
- getCurrentTopologyType() {
398
- return this.getLastSeenTopology()?.type ?? 'Unknown';
588
+ }
589
+ async collectionInfo(dbName, collName) {
590
+ const [collInfo] = await this._listCollections(dbName, { name: collName });
591
+ return ((0, instance_detail_helper_2.adaptCollectionInfo)({
592
+ db: dbName,
593
+ ...collInfo,
594
+ }) ?? null);
595
+ }
596
+ async killOp(id, comment) {
597
+ const db = this._database('admin', 'META');
598
+ return (0, run_command_1.runCommand)(db, { killOp: 1, id, comment }, { enableUtf8Validation: false });
599
+ }
600
+ isWritable() {
601
+ return this._isWritable;
602
+ }
603
+ isMongos() {
604
+ return this.getCurrentTopologyType() === 'Sharded';
605
+ }
606
+ getCurrentTopologyType() {
607
+ return this.getLastSeenTopology()?.type ?? 'Unknown';
608
+ }
609
+ async _connectionStatus() {
610
+ const adminDb = this._database('admin', 'META');
611
+ return await (0, run_command_1.runCommand)(adminDb, {
612
+ connectionStatus: 1,
613
+ showPrivileges: true,
614
+ }, { enableUtf8Validation: false });
615
+ }
616
+ async _getPrivilegesOrFallback(privileges = null) {
617
+ if (privileges) {
618
+ return privileges;
399
619
  }
400
- async _connectionStatus() {
401
- const adminDb = this._database('admin', 'META');
402
- return await (0, run_command_1.runCommand)(adminDb, {
403
- connectionStatus: 1,
404
- showPrivileges: true,
405
- }, { enableUtf8Validation: false });
620
+ const { authInfo: { authenticatedUserPrivileges }, } = await this._connectionStatus();
621
+ return authenticatedUserPrivileges;
622
+ }
623
+ async _getRolesOrFallback(roles = null) {
624
+ if (roles) {
625
+ return roles;
406
626
  }
407
- async _getPrivilegesOrFallback(privileges = null) {
408
- if (privileges) {
409
- return privileges;
627
+ const { authInfo: { authenticatedUserRoles }, } = await this._connectionStatus();
628
+ return authenticatedUserRoles;
629
+ }
630
+ async _listCollections(databaseName, filter = {}, { nameOnly } = {}) {
631
+ try {
632
+ const cursor = this._database(databaseName, 'CRUD').listCollections(filter, {
633
+ nameOnly,
634
+ ...maybeOverrideReadPreference(this.isMongos(), this._crudClient?.readPreference),
635
+ });
636
+ // Iterate instead of using .toArray() so we can emit
637
+ // collection info update events as they come in.
638
+ const results = [];
639
+ for await (const result of cursor) {
640
+ if (!nameOnly) {
641
+ this._csfleCollectionTracker?.updateCollectionInfo(`${databaseName}.${result.name}`, result);
642
+ }
643
+ results.push(result);
410
644
  }
411
- const { authInfo: { authenticatedUserPrivileges }, } = await this._connectionStatus();
412
- return authenticatedUserPrivileges;
645
+ return results;
646
+ }
647
+ catch (err) {
648
+ // Currently Compass should not fail if listCollections failed for
649
+ // any possible reason to preserve current behavior. We probably
650
+ // want this to check at least that what we got back is a server
651
+ // error and not a weird runtime issue on our side that can be
652
+ // swallowed in this case, ideally we know exactly what server
653
+ // errors we want to handle here and only avoid throwing in these
654
+ // cases
655
+ //
656
+ // TODO: https://jira.mongodb.org/browse/COMPASS-5275
657
+ this._logger.warn((0, logger_1.mongoLogId)(1_001_000_099), 'Failed to run listCollections', { message: err.message });
658
+ return [];
413
659
  }
414
- async _getRolesOrFallback(roles = null) {
415
- if (roles) {
416
- return roles;
660
+ }
661
+ async listCollections(databaseName, filter = {}, { nameOnly, fetchNamespacesFromPrivileges = true, privileges = null, } = {}) {
662
+ const listCollections = async () => {
663
+ const colls = await this._listCollections(databaseName, filter, {
664
+ nameOnly,
665
+ });
666
+ return colls.map((coll) => ({
667
+ inferred_from_privileges: false,
668
+ ...coll,
669
+ }));
670
+ };
671
+ const getCollectionsFromPrivileges = async () => {
672
+ if (!fetchNamespacesFromPrivileges) {
673
+ return [];
417
674
  }
418
- const { authInfo: { authenticatedUserRoles }, } = await this._connectionStatus();
419
- return authenticatedUserRoles;
420
- }
421
- async _listCollections(databaseName, filter = {}, { nameOnly } = {}) {
675
+ const databases = (0, instance_detail_helper_2.getPrivilegesByDatabaseAndCollection)(await this._getPrivilegesOrFallback(privileges), ['find']);
676
+ return Object.keys(
677
+ // Privileges might not have a database we are looking for
678
+ databases[databaseName] || {})
679
+ .filter(
680
+ // Privileges can have collection name '' that indicates
681
+ // privileges on all collections in the database, we don't want
682
+ // those registered as "real" collection names
683
+ Boolean)
684
+ .map((name) => ({ name, inferred_from_privileges: true }));
685
+ };
686
+ const [listedCollections, collectionsFromPrivileges] = await Promise.all([
687
+ listCollections(),
688
+ // If the filter is not empty, we can't meaningfully derive collections
689
+ // from privileges and filter them as the criteria might include any key
690
+ // from the listCollections result object and there is no such info in
691
+ // privileges. Because of that we are ignoring privileges completely if
692
+ // listCollections was called with a filter.
693
+ isEmptyObject(filter) ? getCollectionsFromPrivileges() : [],
694
+ ]);
695
+ const collections = uniqueBy(
696
+ // NB: Order is important, we want listed collections to take precedence
697
+ // if they were fetched successfully
698
+ [...collectionsFromPrivileges, ...listedCollections], 'name').map(({ inferred_from_privileges, ...coll }) => ({
699
+ inferred_from_privileges,
700
+ ...(0, instance_detail_helper_2.adaptCollectionInfo)({ db: databaseName, ...coll }),
701
+ }));
702
+ return collections;
703
+ }
704
+ async listDatabases({ nameOnly, fetchNamespacesFromPrivileges = true, privileges = null, roles = null, } = {}) {
705
+ const adminDb = this._database('admin', 'CRUD');
706
+ const listDatabases = async () => {
422
707
  try {
423
- const cursor = this._database(databaseName, 'CRUD').listCollections(filter, {
708
+ const { databases } = await (0, run_command_1.runCommand)(adminDb, {
709
+ listDatabases: 1,
424
710
  nameOnly,
711
+ }, {
712
+ enableUtf8Validation: false,
425
713
  ...maybeOverrideReadPreference(this.isMongos(), this._crudClient?.readPreference),
426
714
  });
427
- // Iterate instead of using .toArray() so we can emit
428
- // collection info update events as they come in.
429
- const results = [];
430
- for await (const result of cursor) {
431
- if (!nameOnly) {
432
- this._csfleCollectionTracker?.updateCollectionInfo(`${databaseName}.${result.name}`, result);
433
- }
434
- results.push(result);
435
- }
436
- return results;
715
+ return databases.map((x) => ({
716
+ ...x,
717
+ inferred_from_privileges: false,
718
+ }));
437
719
  }
438
720
  catch (err) {
439
- // Currently Compass should not fail if listCollections failed for
440
- // any possible reason to preserve current behavior. We probably
441
- // want this to check at least that what we got back is a server
442
- // error and not a weird runtime issue on our side that can be
443
- // swallowed in this case, ideally we know exactly what server
444
- // errors we want to handle here and only avoid throwing in these
445
- // cases
721
+ // Currently Compass should not fail if listDatabase failed for any
722
+ // possible reason to preserve current behavior. We probably want this
723
+ // to check at least that what we got back is a server error and not a
724
+ // weird runtime issue on our side that can be swallowed in this case,
725
+ // ideally we know exactly what server errors we want to handle here
726
+ // and only avoid throwing in these cases
446
727
  //
447
728
  // TODO: https://jira.mongodb.org/browse/COMPASS-5275
448
- this._logger.warn((0, logger_1.mongoLogId)(1_001_000_099), 'Failed to run listCollections', { message: err.message });
729
+ this._logger.warn((0, logger_1.mongoLogId)(1_001_000_098), 'Failed to run listDatabases', { message: err.message });
449
730
  return [];
450
731
  }
451
- }
452
- async listCollections(databaseName, filter = {}, { nameOnly, fetchNamespacesFromPrivileges = true, privileges = null, } = {}) {
453
- const listCollections = async () => {
454
- const colls = await this._listCollections(databaseName, filter, {
455
- nameOnly,
456
- });
457
- return colls.map((coll) => ({
458
- inferred_from_privileges: false,
459
- ...coll,
460
- }));
461
- };
462
- const getCollectionsFromPrivileges = async () => {
463
- if (!fetchNamespacesFromPrivileges) {
464
- return [];
465
- }
466
- const databases = (0, instance_detail_helper_2.getPrivilegesByDatabaseAndCollection)(await this._getPrivilegesOrFallback(privileges), ['find']);
467
- return Object.keys(
468
- // Privileges might not have a database we are looking for
469
- databases[databaseName] || {})
470
- .filter(
471
- // Privileges can have collection name '' that indicates
472
- // privileges on all collections in the database, we don't want
473
- // those registered as "real" collection names
474
- Boolean)
475
- .map((name) => ({ name, inferred_from_privileges: true }));
476
- };
477
- const [listedCollections, collectionsFromPrivileges] = await Promise.all([
478
- listCollections(),
479
- // If the filter is not empty, we can't meaningfully derive collections
480
- // from privileges and filter them as the criteria might include any key
481
- // from the listCollections result object and there is no such info in
482
- // privileges. Because of that we are ignoring privileges completely if
483
- // listCollections was called with a filter.
484
- isEmptyObject(filter) ? getCollectionsFromPrivileges() : [],
485
- ]);
486
- const collections = uniqueBy(
487
- // NB: Order is important, we want listed collections to take precedence
488
- // if they were fetched successfully
489
- [...collectionsFromPrivileges, ...listedCollections], 'name').map(({ inferred_from_privileges, ...coll }) => ({
490
- inferred_from_privileges,
491
- ...(0, instance_detail_helper_2.adaptCollectionInfo)({ db: databaseName, ...coll }),
732
+ };
733
+ const getDatabasesFromPrivileges = async () => {
734
+ if (!fetchNamespacesFromPrivileges) {
735
+ return [];
736
+ }
737
+ const databases = (0, instance_detail_helper_2.getPrivilegesByDatabaseAndCollection)(await this._getPrivilegesOrFallback(privileges), ['find']);
738
+ return Object.keys(databases)
739
+ .filter(
740
+ // For the roles created in admin database, the database name
741
+ // can be '' meaning that it applies to all databases. We can't
742
+ // meaningfully handle this in the UI so we are filtering these
743
+ // out
744
+ Boolean)
745
+ .map((name) => ({ name, inferred_from_privileges: true }));
746
+ };
747
+ const getDatabasesFromRoles = async () => {
748
+ const databases = (0, instance_detail_helper_2.getDatabasesByRoles)(await this._getRolesOrFallback(roles),
749
+ // https://jira.mongodb.org/browse/HELP-32199
750
+ // Atlas shared tier MongoDB server version v5+ does not return
751
+ // `authenticatedUserPrivileges` as part of the `connectionStatus`.
752
+ // As a workaround we show the databases the user has
753
+ // certain general built-in roles for.
754
+ // This does not cover custom user roles which can
755
+ // have custom privileges that we can't currently fetch.
756
+ ['read', 'readWrite', 'dbAdmin', 'dbOwner']);
757
+ return databases.map((name) => ({
758
+ name,
759
+ inferred_from_privileges: true,
492
760
  }));
493
- return collections;
494
- }
495
- async listDatabases({ nameOnly, fetchNamespacesFromPrivileges = true, privileges = null, roles = null, } = {}) {
496
- const adminDb = this._database('admin', 'CRUD');
497
- const listDatabases = async () => {
498
- try {
499
- const { databases } = await (0, run_command_1.runCommand)(adminDb, {
500
- listDatabases: 1,
501
- nameOnly,
502
- }, {
503
- enableUtf8Validation: false,
504
- ...maybeOverrideReadPreference(this.isMongos(), this._crudClient?.readPreference),
505
- });
506
- return databases.map((x) => ({
507
- ...x,
508
- inferred_from_privileges: false,
509
- }));
510
- }
511
- catch (err) {
512
- // Currently Compass should not fail if listDatabase failed for any
513
- // possible reason to preserve current behavior. We probably want this
514
- // to check at least that what we got back is a server error and not a
515
- // weird runtime issue on our side that can be swallowed in this case,
516
- // ideally we know exactly what server errors we want to handle here
517
- // and only avoid throwing in these cases
518
- //
519
- // TODO: https://jira.mongodb.org/browse/COMPASS-5275
520
- this._logger.warn((0, logger_1.mongoLogId)(1_001_000_098), 'Failed to run listDatabases', { message: err.message });
521
- return [];
522
- }
523
- };
524
- const getDatabasesFromPrivileges = async () => {
525
- if (!fetchNamespacesFromPrivileges) {
526
- return [];
527
- }
528
- const databases = (0, instance_detail_helper_2.getPrivilegesByDatabaseAndCollection)(await this._getPrivilegesOrFallback(privileges), ['find']);
529
- return Object.keys(databases)
530
- .filter(
531
- // For the roles created in admin database, the database name
532
- // can be '' meaning that it applies to all databases. We can't
533
- // meaningfully handle this in the UI so we are filtering these
534
- // out
535
- Boolean)
536
- .map((name) => ({ name, inferred_from_privileges: true }));
537
- };
538
- const getDatabasesFromRoles = async () => {
539
- const databases = (0, instance_detail_helper_2.getDatabasesByRoles)(await this._getRolesOrFallback(roles),
540
- // https://jira.mongodb.org/browse/HELP-32199
541
- // Atlas shared tier MongoDB server version v5+ does not return
542
- // `authenticatedUserPrivileges` as part of the `connectionStatus`.
543
- // As a workaround we show the databases the user has
544
- // certain general built-in roles for.
545
- // This does not cover custom user roles which can
546
- // have custom privileges that we can't currently fetch.
547
- ['read', 'readWrite', 'dbAdmin', 'dbOwner']);
548
- return databases.map((name) => ({
549
- name,
550
- inferred_from_privileges: true,
551
- }));
761
+ };
762
+ const [listedDatabases, databasesFromPrivileges, databasesFromRoles] = await Promise.all([
763
+ listDatabases(),
764
+ getDatabasesFromPrivileges(),
765
+ getDatabasesFromRoles(),
766
+ ]);
767
+ const databases = uniqueBy(
768
+ // NB: Order is important, we want listed collections to take precedence
769
+ // if they were fetched successfully
770
+ [...databasesFromRoles, ...databasesFromPrivileges, ...listedDatabases], 'name').map(({ name, inferred_from_privileges, ...db }) => {
771
+ return {
772
+ _id: name,
773
+ name,
774
+ inferred_from_privileges,
775
+ ...(0, instance_detail_helper_2.adaptDatabaseInfo)(db),
552
776
  };
553
- const [listedDatabases, databasesFromPrivileges, databasesFromRoles] = await Promise.all([
554
- listDatabases(),
555
- getDatabasesFromPrivileges(),
556
- getDatabasesFromRoles(),
557
- ]);
558
- const databases = uniqueBy(
559
- // NB: Order is important, we want listed collections to take precedence
560
- // if they were fetched successfully
561
- [...databasesFromRoles, ...databasesFromPrivileges, ...listedDatabases], 'name').map(({ name, inferred_from_privileges, ...db }) => {
562
- return {
563
- _id: name,
564
- name,
565
- inferred_from_privileges,
566
- ...(0, instance_detail_helper_2.adaptDatabaseInfo)(db),
567
- };
568
- });
569
- return databases;
570
- }
571
- addReauthenticationHandler(handler) {
572
- this._reauthenticationHandlers.add(handler);
777
+ });
778
+ return databases;
779
+ }
780
+ addReauthenticationHandler(handler) {
781
+ this._reauthenticationHandlers.add(handler);
782
+ }
783
+ async _requestReauthenticationFromUser() {
784
+ this._logger.info((0, logger_1.mongoLogId)(1_001_000_194), 'Requesting re-authentication from user');
785
+ let threw = true;
786
+ try {
787
+ for (const handler of this._reauthenticationHandlers)
788
+ await handler();
789
+ threw = false;
573
790
  }
574
- async _requestReauthenticationFromUser() {
575
- this._logger.info((0, logger_1.mongoLogId)(1_001_000_194), 'Requesting re-authentication from user');
576
- let threw = true;
577
- try {
578
- for (const handler of this._reauthenticationHandlers)
579
- await handler();
580
- threw = false;
581
- }
582
- finally {
583
- this._logger.info((0, logger_1.mongoLogId)(1_001_000_193), 'Completed re-authentication request', {
584
- wantsReauth: !threw,
585
- });
586
- }
791
+ finally {
792
+ this._logger.info((0, logger_1.mongoLogId)(1_001_000_193), 'Completed re-authentication request', {
793
+ wantsReauth: !threw,
794
+ });
587
795
  }
588
- async connect({ signal, productName, productDocsLink, } = {}) {
589
- if (this._metadataClient) {
590
- (0, logger_1.debug)('already connected');
591
- return;
592
- }
593
- if (this._isConnecting) {
594
- (0, logger_1.debug)('connect method called more than once');
595
- return;
596
- }
597
- (0, logger_1.debug)('connecting...');
598
- this._isConnecting = true;
599
- const clusterName = this._connectionOptions.lookup?.().clusterName;
600
- this._logger.info((0, logger_1.mongoLogId)(1_001_000_014), 'Connecting Started', {
796
+ }
797
+ async connect({ signal, productName, productDocsLink, } = {}) {
798
+ if (this._metadataClient) {
799
+ (0, logger_1.debug)('already connected');
800
+ return;
801
+ }
802
+ if (this._isConnecting) {
803
+ (0, logger_1.debug)('connect method called more than once');
804
+ return;
805
+ }
806
+ (0, logger_1.debug)('connecting...');
807
+ this._isConnecting = true;
808
+ const clusterName = this._connectionOptions.lookup?.().clusterName;
809
+ this._logger.info((0, logger_1.mongoLogId)(1_001_000_014), 'Connecting Started', {
810
+ connectionId: this._id,
811
+ url: (0, redact_1.redactConnectionString)(this._connectionOptions.connectionString),
812
+ csfle: this._csfleLogInformation(this._connectionOptions.fleOptions),
813
+ ...(clusterName && { clusterName }),
814
+ });
815
+ try {
816
+ const [metadataClient, crudClient, tunnel, state, connectionOptions] = await (0, connect_mongo_client_1.connectMongoClientDataService)({
817
+ connectionOptions: this._connectionOptions,
818
+ proxyOptions: this._proxyOptions,
819
+ setupListeners: this._setupListeners.bind(this),
820
+ signal,
821
+ logger: this._unboundLogger,
822
+ productName,
823
+ productDocsLink,
824
+ reauthenticationHandler: this._requestReauthenticationFromUser.bind(this),
825
+ });
826
+ const attr = {
601
827
  connectionId: this._id,
602
- url: (0, redact_1.redactConnectionString)(this._connectionOptions.connectionString),
603
- csfle: this._csfleLogInformation(this._connectionOptions.fleOptions),
828
+ isWritable: this.isWritable(),
829
+ isMongos: this.isMongos(),
604
830
  ...(clusterName && { clusterName }),
831
+ };
832
+ this._logger.info((0, logger_1.mongoLogId)(1_001_000_015), 'Connecting Succeeded', attr);
833
+ (0, logger_1.debug)('connected!', attr);
834
+ state.oidcPlugin.logger.on('mongodb-oidc-plugin:state-updated', () => {
835
+ this._emitter.emit('connectionInfoSecretsChanged');
605
836
  });
606
- try {
607
- const [metadataClient, crudClient, tunnel, state, connectionOptions] = await (0, connect_mongo_client_1.connectMongoClientDataService)({
608
- connectionOptions: this._connectionOptions,
609
- proxyOptions: this._proxyOptions,
610
- setupListeners: this._setupListeners.bind(this),
611
- signal,
612
- logger: this._unboundLogger,
613
- productName,
614
- productDocsLink,
615
- reauthenticationHandler: this._requestReauthenticationFromUser.bind(this),
616
- });
617
- const attr = {
618
- connectionId: this._id,
619
- isWritable: this.isWritable(),
620
- isMongos: this.isMongos(),
621
- ...(clusterName && { clusterName }),
622
- };
623
- this._logger.info((0, logger_1.mongoLogId)(1_001_000_015), 'Connecting Succeeded', attr);
624
- (0, logger_1.debug)('connected!', attr);
625
- state.oidcPlugin.logger.on('mongodb-oidc-plugin:state-updated', () => {
626
- this._emitter.emit('connectionInfoSecretsChanged');
627
- });
628
- state.oidcPlugin.logger.on('mongodb-oidc-plugin:auth-failed', ({ error }) => {
629
- this._emitter.emit('oidcAuthFailed', error);
630
- });
631
- this._metadataClient = metadataClient;
632
- this._crudClient = crudClient;
633
- this._tunnel = tunnel;
634
- this._state = state;
635
- this._mongoClientConnectionOptions = connectionOptions;
636
- this._csfleCollectionTracker = new csfle_collection_tracker_1.CSFLECollectionTrackerImpl(this, this._crudClient);
637
- }
638
- catch (error) {
639
- this._logger.info((0, logger_1.mongoLogId)(1_001_000_359), 'Connecting Failed', {
640
- connectionId: this._id,
641
- error: error && typeof error === 'object' && 'message' in error
642
- ? error?.message
643
- : 'unknown error',
644
- ...(clusterName && { clusterName }),
645
- });
646
- throw error;
647
- }
648
- finally {
649
- this._isConnecting = false;
650
- }
651
- }
652
- estimatedCount(ns, options = {}, executionOptions) {
653
- const maxTimeMS = options.maxTimeMS ?? 500;
654
- return this._cancellableOperation(async (session) => {
655
- return this._collection(ns, 'CRUD').estimatedDocumentCount({
656
- ...options,
657
- maxTimeMS,
658
- session,
659
- });
660
- }, (session) => session.endSession(), executionOptions?.abortSignal);
661
- }
662
- count(ns, filter, options = {}, executionOptions) {
663
- return this._cancellableOperation(async (session) => {
664
- return this._collection(ns, 'CRUD').countDocuments(filter, {
665
- ...this._getOptionsWithFallbackReadPreference(options, executionOptions),
666
- session,
667
- });
668
- }, (session) => session.endSession(), executionOptions?.abortSignal);
669
- }
670
- async createCollection(ns, options) {
671
- const collectionName = this._collectionName(ns);
672
- const db = this._database(ns, 'CRUD');
673
- return await db.createCollection(collectionName, options);
674
- }
675
- async createIndex(ns, spec, options) {
676
- const coll = this._collection(ns, 'CRUD');
677
- return await coll.createIndex(spec, options);
678
- }
679
- async deleteOne(ns, filter, options) {
680
- const coll = this._collection(ns, 'CRUD');
681
- return await coll.deleteOne(filter, options);
837
+ state.oidcPlugin.logger.on('mongodb-oidc-plugin:auth-failed', ({ error }) => {
838
+ this._emitter.emit('oidcAuthFailed', error);
839
+ });
840
+ this._metadataClient = metadataClient;
841
+ this._crudClient = crudClient;
842
+ this._tunnel = tunnel;
843
+ this._state = state;
844
+ this._mongoClientConnectionOptions = connectionOptions;
845
+ this._csfleCollectionTracker = new csfle_collection_tracker_1.CSFLECollectionTrackerImpl(this, this._crudClient);
682
846
  }
683
- async deleteMany(ns, filter, options) {
684
- const coll = this._collection(ns, 'CRUD');
685
- return await coll.deleteMany(filter, options);
847
+ catch (error) {
848
+ this._logger.info((0, logger_1.mongoLogId)(1_001_000_359), 'Connecting Failed', {
849
+ connectionId: this._id,
850
+ error: error && typeof error === 'object' && 'message' in error
851
+ ? error?.message
852
+ : 'unknown error',
853
+ ...(clusterName && { clusterName }),
854
+ });
855
+ throw error;
686
856
  }
687
- async updateMany(ns, filter, update, options) {
688
- const coll = this._collection(ns, 'CRUD');
689
- return await coll.updateMany(filter, update, options);
857
+ finally {
858
+ this._isConnecting = false;
690
859
  }
691
- async disconnect() {
692
- this._logger.info((0, logger_1.mongoLogId)(1_001_000_016), 'Disconnecting');
693
- try {
694
- await Promise.all([
695
- this._metadataClient
860
+ }
861
+ estimatedCount(ns, options = {}, executionOptions) {
862
+ const maxTimeMS = options.maxTimeMS ?? 500;
863
+ return this._cancellableOperation(async (session) => {
864
+ return this._collection(ns, 'CRUD').estimatedDocumentCount({
865
+ ...options,
866
+ maxTimeMS,
867
+ session,
868
+ });
869
+ }, (session) => session.endSession(), executionOptions?.abortSignal);
870
+ }
871
+ count(ns, filter, options = {}, executionOptions) {
872
+ return this._cancellableOperation(async (session) => {
873
+ return this._collection(ns, 'CRUD').countDocuments(filter, {
874
+ ...this._getOptionsWithFallbackReadPreference(options, executionOptions),
875
+ session,
876
+ });
877
+ }, (session) => session.endSession(), executionOptions?.abortSignal);
878
+ }
879
+ async createCollection(ns, options) {
880
+ const collectionName = this._collectionName(ns);
881
+ const db = this._database(ns, 'CRUD');
882
+ return await db.createCollection(collectionName, options);
883
+ }
884
+ async createIndex(ns, spec, options) {
885
+ const coll = this._collection(ns, 'CRUD');
886
+ return await coll.createIndex(spec, options);
887
+ }
888
+ async deleteOne(ns, filter, options) {
889
+ const coll = this._collection(ns, 'CRUD');
890
+ return await coll.deleteOne(filter, options);
891
+ }
892
+ async deleteMany(ns, filter, options) {
893
+ const coll = this._collection(ns, 'CRUD');
894
+ return await coll.deleteMany(filter, options);
895
+ }
896
+ async updateMany(ns, filter, update, options) {
897
+ const coll = this._collection(ns, 'CRUD');
898
+ return await coll.updateMany(filter, update, options);
899
+ }
900
+ async disconnect() {
901
+ this._logger.info((0, logger_1.mongoLogId)(1_001_000_016), 'Disconnecting');
902
+ try {
903
+ await Promise.all([
904
+ this._metadataClient
905
+ ?.close(true)
906
+ .catch((err) => (0, logger_1.debug)('failed to close MongoClient', err)),
907
+ this._crudClient !== this._metadataClient &&
908
+ this._crudClient
696
909
  ?.close(true)
697
910
  .catch((err) => (0, logger_1.debug)('failed to close MongoClient', err)),
698
- this._crudClient !== this._metadataClient &&
699
- this._crudClient
700
- ?.close(true)
701
- .catch((err) => (0, logger_1.debug)('failed to close MongoClient', err)),
702
- this._tunnel
703
- ?.close()
704
- .catch((err) => (0, logger_1.debug)('failed to close tunnel', err)),
705
- this._state
706
- ?.destroy()
707
- .catch((err) => (0, logger_1.debug)('failed to destroy DevtoolsConnectionState', err)),
708
- ]);
709
- }
710
- finally {
711
- this._cleanup();
712
- this._logger.info((0, logger_1.mongoLogId)(1_001_000_017), 'Fully closed');
713
- }
714
- }
715
- async dropCollection(ns) {
716
- const db = this._database(ns, 'CRUD');
717
- const collName = this._collectionName(ns);
718
- const coll = db.collection(collName);
719
- let result = null;
720
- try {
721
- [result] = await db
722
- .listCollections({ name: collName }, { nameOnly: false })
723
- .toArray();
724
- }
725
- catch {
726
- // ignore
727
- }
728
- const options = {};
729
- const encryptedFieldsInfo = result?.options?.encryptedFields;
730
- if (encryptedFieldsInfo) {
731
- options.encryptedFields = encryptedFieldsInfo;
732
- }
733
- return await coll.drop(options);
734
- }
735
- renameCollection(ns, newCollectionName) {
736
- const db = this._database(ns, 'META');
737
- return db.renameCollection(this._collectionName(ns), newCollectionName);
738
- }
739
- async dropDatabase(name) {
740
- const db = this._database(name, 'CRUD');
741
- return await db.dropDatabase();
742
- }
743
- async dropIndex(ns, name) {
744
- const coll = this._collection(ns, 'CRUD');
745
- return await coll.dropIndex(name);
746
- }
747
- async isListSearchIndexesSupported(ns) {
748
- try {
749
- await this.getSearchIndexes(ns);
750
- }
751
- catch {
752
- return false;
753
- }
754
- return true;
755
- }
756
- async getSearchIndexes(ns) {
757
- const coll = this._collection(ns, 'CRUD');
758
- const cursor = coll.listSearchIndexes();
759
- const indexes = await cursor.toArray();
760
- void cursor.close();
761
- return indexes;
762
- }
763
- async createSearchIndex(ns, description) {
764
- const coll = this._collection(ns, 'CRUD');
765
- return coll.createSearchIndex(description);
766
- }
767
- async updateSearchIndex(ns, name, definition) {
768
- const coll = this._collection(ns, 'CRUD');
769
- return coll.updateSearchIndex(name, definition);
770
- }
771
- async dropSearchIndex(ns, name) {
772
- const coll = this._collection(ns, 'CRUD');
773
- return coll.dropSearchIndex(name);
774
- }
775
- aggregateCursor(ns, pipeline, options = {}) {
776
- return this._collection(ns, 'CRUD').aggregate(pipeline, options);
777
- }
778
- // @ts-expect-error generic in the method trips up TS here resulting in
779
- // Promise<unknown> is not assignable to Promise<Document[]>
780
- aggregate(ns, pipeline, options = {}, executionOptions) {
781
- let cursor;
782
- return this._cancellableOperation(async (session) => {
783
- cursor = this._collection(ns, 'CRUD').aggregate(pipeline, {
784
- ...options,
785
- session,
786
- });
787
- const results = await cursor.toArray();
788
- void cursor.close();
789
- return results;
790
- }, () => cursor?.close(), executionOptions?.abortSignal);
791
- }
792
- find(ns, filter, options = {}, executionOptions) {
793
- let cursor;
794
- return this._cancellableOperation(async (session) => {
795
- cursor = this._collection(ns, 'CRUD').find(filter, {
796
- ...options,
797
- session,
798
- });
799
- const results = await cursor.toArray();
800
- void cursor.close();
801
- return results;
802
- }, () => cursor?.close(), executionOptions?.abortSignal);
803
- }
804
- findCursor(ns, filter, options = {}) {
805
- return this._collection(ns, 'CRUD').find(filter, options);
911
+ this._tunnel
912
+ ?.close()
913
+ .catch((err) => (0, logger_1.debug)('failed to close tunnel', err)),
914
+ this._state
915
+ ?.destroy()
916
+ .catch((err) => (0, logger_1.debug)('failed to destroy DevtoolsConnectionState', err)),
917
+ ]);
806
918
  }
807
- async findOneAndReplace(ns, filter, replacement, options) {
808
- const coll = this._collection(ns, 'CRUD');
809
- return await coll.findOneAndReplace(filter, replacement, options);
919
+ finally {
920
+ this._cleanup();
921
+ this._logger.info((0, logger_1.mongoLogId)(1_001_000_017), 'Fully closed');
810
922
  }
811
- async findOneAndUpdate(ns, filter, update, options) {
812
- const coll = this._collection(ns, 'CRUD');
813
- return await coll.findOneAndUpdate(filter, update, options);
923
+ }
924
+ async dropCollection(ns) {
925
+ const db = this._database(ns, 'CRUD');
926
+ const collName = this._collectionName(ns);
927
+ const coll = db.collection(collName);
928
+ let result = null;
929
+ try {
930
+ [result] = await db
931
+ .listCollections({ name: collName }, { nameOnly: false })
932
+ .toArray();
814
933
  }
815
- async updateOne(ns, filter, update, options) {
816
- const coll = this._collection(ns, 'CRUD');
817
- return await coll.updateOne(filter, update, options);
934
+ catch {
935
+ // ignore
818
936
  }
819
- async replaceOne(ns, filter, replacement, options) {
820
- const coll = this._collection(ns, 'CRUD');
821
- return await coll.replaceOne(filter, replacement, options);
937
+ const options = {};
938
+ const encryptedFieldsInfo = result?.options?.encryptedFields;
939
+ if (encryptedFieldsInfo) {
940
+ options.encryptedFields = encryptedFieldsInfo;
822
941
  }
823
- explainFind(ns, filter, options = {}, executionOptions) {
824
- const verbosity = executionOptions?.explainVerbosity || mongodb_1.ExplainVerbosity.executionStats;
825
- let cursor;
826
- return this._cancellableOperation(async (session) => {
827
- cursor = this._collection(ns, 'CRUD').find(filter, {
828
- ...options,
829
- session,
830
- });
831
- const results = await cursor.explain({
832
- verbosity,
833
- maxTimeMS: executionOptions?.maxTimeMS,
834
- });
835
- void cursor.close();
836
- return results;
837
- }, () => cursor?.close(), executionOptions?.abortSignal);
942
+ return await coll.drop(options);
943
+ }
944
+ renameCollection(ns, newCollectionName) {
945
+ const db = this._database(ns, 'META');
946
+ return db.renameCollection(this._collectionName(ns), newCollectionName);
947
+ }
948
+ async dropDatabase(name) {
949
+ const db = this._database(name, 'CRUD');
950
+ return await db.dropDatabase();
951
+ }
952
+ async dropIndex(ns, name) {
953
+ const coll = this._collection(ns, 'CRUD');
954
+ return await coll.dropIndex(name);
955
+ }
956
+ async isListSearchIndexesSupported(ns) {
957
+ try {
958
+ await this.getSearchIndexes(ns);
838
959
  }
839
- explainAggregate(ns, pipeline, options, executionOptions) {
840
- const verbosity = executionOptions?.explainVerbosity || mongodb_1.ExplainVerbosity.executionStats;
841
- let cursor;
842
- return this._cancellableOperation(async (session) => {
843
- cursor = this._collection(ns, 'CRUD').aggregate(pipeline, {
844
- ...options,
845
- session,
846
- });
847
- const results = await cursor.explain({
848
- verbosity,
849
- maxTimeMS: executionOptions?.maxTimeMS,
850
- });
851
- void cursor.close();
852
- return results;
853
- }, () => cursor?.close(), executionOptions?.abortSignal);
960
+ catch {
961
+ return false;
854
962
  }
855
- async _indexStats(ns) {
856
- try {
857
- const stats = await this.aggregate(ns, [
858
- { $indexStats: {} },
859
- {
860
- $project: {
861
- name: 1,
862
- usageHost: '$host',
863
- usageCount: '$accesses.ops',
864
- usageSince: '$accesses.since',
865
- },
963
+ return true;
964
+ }
965
+ async getSearchIndexes(ns) {
966
+ const coll = this._collection(ns, 'CRUD');
967
+ const cursor = coll.listSearchIndexes();
968
+ const indexes = await cursor.toArray();
969
+ void cursor.close();
970
+ return indexes;
971
+ }
972
+ async createSearchIndex(ns, description) {
973
+ const coll = this._collection(ns, 'CRUD');
974
+ return coll.createSearchIndex(description);
975
+ }
976
+ async updateSearchIndex(ns, name, definition) {
977
+ const coll = this._collection(ns, 'CRUD');
978
+ return coll.updateSearchIndex(name, definition);
979
+ }
980
+ async dropSearchIndex(ns, name) {
981
+ const coll = this._collection(ns, 'CRUD');
982
+ return coll.dropSearchIndex(name);
983
+ }
984
+ aggregateCursor(ns, pipeline, options = {}) {
985
+ return this._collection(ns, 'CRUD').aggregate(pipeline, options);
986
+ }
987
+ // @ts-expect-error generic in the method trips up TS here resulting in
988
+ // Promise<unknown> is not assignable to Promise<Document[]>
989
+ aggregate(ns, pipeline, options = {}, executionOptions) {
990
+ let cursor;
991
+ return this._cancellableOperation(async (session) => {
992
+ cursor = this._collection(ns, 'CRUD').aggregate(pipeline, {
993
+ ...options,
994
+ session,
995
+ });
996
+ const results = await cursor.toArray();
997
+ void cursor.close();
998
+ return results;
999
+ }, () => cursor?.close(), executionOptions?.abortSignal);
1000
+ }
1001
+ find(ns, filter, options = {}, executionOptions) {
1002
+ let cursor;
1003
+ return this._cancellableOperation(async (session) => {
1004
+ cursor = this._collection(ns, 'CRUD').find(filter, {
1005
+ ...options,
1006
+ session,
1007
+ });
1008
+ const results = await cursor.toArray();
1009
+ void cursor.close();
1010
+ return results;
1011
+ }, () => cursor?.close(), executionOptions?.abortSignal);
1012
+ }
1013
+ findCursor(ns, filter, options = {}) {
1014
+ return this._collection(ns, 'CRUD').find(filter, options);
1015
+ }
1016
+ async findOneAndReplace(ns, filter, replacement, options) {
1017
+ const coll = this._collection(ns, 'CRUD');
1018
+ return await coll.findOneAndReplace(filter, replacement, options);
1019
+ }
1020
+ async findOneAndUpdate(ns, filter, update, options) {
1021
+ const coll = this._collection(ns, 'CRUD');
1022
+ return await coll.findOneAndUpdate(filter, update, options);
1023
+ }
1024
+ async updateOne(ns, filter, update, options) {
1025
+ const coll = this._collection(ns, 'CRUD');
1026
+ return await coll.updateOne(filter, update, options);
1027
+ }
1028
+ async replaceOne(ns, filter, replacement, options) {
1029
+ const coll = this._collection(ns, 'CRUD');
1030
+ return await coll.replaceOne(filter, replacement, options);
1031
+ }
1032
+ explainFind(ns, filter, options = {}, executionOptions) {
1033
+ const verbosity = executionOptions?.explainVerbosity || mongodb_1.ExplainVerbosity.executionStats;
1034
+ let cursor;
1035
+ return this._cancellableOperation(async (session) => {
1036
+ cursor = this._collection(ns, 'CRUD').find(filter, {
1037
+ ...options,
1038
+ session,
1039
+ });
1040
+ const results = await cursor.explain({
1041
+ verbosity,
1042
+ maxTimeMS: executionOptions?.maxTimeMS,
1043
+ });
1044
+ void cursor.close();
1045
+ return results;
1046
+ }, () => cursor?.close(), executionOptions?.abortSignal);
1047
+ }
1048
+ explainAggregate(ns, pipeline, options, executionOptions) {
1049
+ const verbosity = executionOptions?.explainVerbosity || mongodb_1.ExplainVerbosity.executionStats;
1050
+ let cursor;
1051
+ return this._cancellableOperation(async (session) => {
1052
+ cursor = this._collection(ns, 'CRUD').aggregate(pipeline, {
1053
+ ...options,
1054
+ session,
1055
+ });
1056
+ const results = await cursor.explain({
1057
+ verbosity,
1058
+ maxTimeMS: executionOptions?.maxTimeMS,
1059
+ });
1060
+ void cursor.close();
1061
+ return results;
1062
+ }, () => cursor?.close(), executionOptions?.abortSignal);
1063
+ }
1064
+ async _indexStats(ns) {
1065
+ try {
1066
+ const stats = await this.aggregate(ns, [
1067
+ { $indexStats: {} },
1068
+ {
1069
+ $project: {
1070
+ name: 1,
1071
+ usageHost: '$host',
1072
+ usageCount: '$accesses.ops',
1073
+ usageSince: '$accesses.since',
866
1074
  },
867
- ]);
868
- return Object.fromEntries(stats.map((index) => {
869
- return [index.name, index];
870
- }));
871
- }
872
- catch (err) {
873
- if ((0, instance_detail_helper_1.isNotAuthorized)(err) || (0, instance_detail_helper_1.isNotSupportedPipelineStage)(err)) {
874
- return {};
875
- }
876
- throw err;
877
- }
1075
+ },
1076
+ ]);
1077
+ return Object.fromEntries(stats.map((index) => {
1078
+ return [index.name, index];
1079
+ }));
878
1080
  }
879
- async _indexSizes(ns) {
880
- try {
881
- const coll = this._collection(ns, 'CRUD');
882
- const aggResult = (await coll
883
- .aggregate([
884
- { $collStats: { storageStats: {} } },
885
- {
886
- $project: {
887
- indexSizes: { $objectToArray: '$storageStats.indexSizes' },
888
- },
889
- },
890
- { $unwind: '$indexSizes' },
891
- {
892
- $group: {
893
- _id: '$indexSizes.k',
894
- size: { $sum: { $toDouble: '$indexSizes.v' } },
895
- },
896
- },
897
- ])
898
- .toArray());
899
- return Object.fromEntries(aggResult.map(({ _id, size }) => [_id, size]));
900
- }
901
- catch (err) {
902
- if ((0, instance_detail_helper_1.isNotAuthorized)(err) || (0, instance_detail_helper_1.isNotSupportedPipelineStage)(err)) {
903
- return {};
904
- }
905
- throw err;
1081
+ catch (err) {
1082
+ if ((0, instance_detail_helper_1.isNotAuthorized)(err) || (0, instance_detail_helper_1.isNotSupportedPipelineStage)(err)) {
1083
+ return {};
906
1084
  }
1085
+ throw err;
907
1086
  }
908
- async _indexProgress(ns) {
909
- const currentOp = { $currentOp: { allUsers: true, localOps: false } };
910
- const pipeline = [
911
- // get all ops
912
- currentOp,
1087
+ }
1088
+ async _indexSizes(ns) {
1089
+ try {
1090
+ const coll = this._collection(ns, 'CRUD');
1091
+ const aggResult = (await coll
1092
+ .aggregate([
1093
+ { $collStats: { storageStats: {} } },
913
1094
  {
914
- // filter for createIndexes commands
915
- $match: {
916
- ns,
917
- progress: { $type: 'object' },
918
- 'command.createIndexes': { $exists: true },
1095
+ $project: {
1096
+ indexSizes: { $objectToArray: '$storageStats.indexSizes' },
919
1097
  },
920
1098
  },
1099
+ { $unwind: '$indexSizes' },
921
1100
  {
922
- // explode the "indexes" array for each createIndexes command
923
- $unwind: '$command.indexes',
924
- },
925
- {
926
- // group on index name
927
1101
  $group: {
928
- _id: '$command.indexes.name',
929
- progress: {
930
- $first: {
931
- $cond: {
932
- if: { $gt: ['$progress.total', 0] },
933
- then: { $divide: ['$progress.done', '$progress.total'] },
934
- else: 0,
935
- },
1102
+ _id: '$indexSizes.k',
1103
+ size: { $sum: { $toDouble: '$indexSizes.v' } },
1104
+ },
1105
+ },
1106
+ ])
1107
+ .toArray());
1108
+ return Object.fromEntries(aggResult.map(({ _id, size }) => [_id, size]));
1109
+ }
1110
+ catch (err) {
1111
+ if ((0, instance_detail_helper_1.isNotAuthorized)(err) || (0, instance_detail_helper_1.isNotSupportedPipelineStage)(err)) {
1112
+ return {};
1113
+ }
1114
+ throw err;
1115
+ }
1116
+ }
1117
+ async _indexProgress(ns) {
1118
+ const currentOp = { $currentOp: { allUsers: true, localOps: false } };
1119
+ const pipeline = [
1120
+ // get all ops
1121
+ currentOp,
1122
+ {
1123
+ // filter for createIndexes commands
1124
+ $match: {
1125
+ ns,
1126
+ progress: { $type: 'object' },
1127
+ 'command.createIndexes': { $exists: true },
1128
+ },
1129
+ },
1130
+ {
1131
+ // explode the "indexes" array for each createIndexes command
1132
+ $unwind: '$command.indexes',
1133
+ },
1134
+ {
1135
+ // group on index name
1136
+ $group: {
1137
+ _id: '$command.indexes.name',
1138
+ progress: {
1139
+ $first: {
1140
+ $cond: {
1141
+ if: { $gt: ['$progress.total', 0] },
1142
+ then: { $divide: ['$progress.done', '$progress.total'] },
1143
+ else: 0,
936
1144
  },
937
1145
  },
938
1146
  },
939
1147
  },
940
- ];
941
- let currentOps = [];
942
- const db = this._database('admin', 'META');
1148
+ },
1149
+ ];
1150
+ let currentOps = [];
1151
+ const db = this._database('admin', 'META');
1152
+ try {
1153
+ currentOps = (await db
1154
+ .aggregate(pipeline)
1155
+ .toArray());
1156
+ }
1157
+ catch {
1158
+ // Try limiting the permissions needed:
1159
+ currentOp.$currentOp.allUsers = false;
943
1160
  try {
944
1161
  currentOps = (await db
945
1162
  .aggregate(pipeline)
946
1163
  .toArray());
947
1164
  }
948
1165
  catch {
949
- // Try limiting the permissions needed:
950
- currentOp.$currentOp.allUsers = false;
951
- try {
952
- currentOps = (await db
953
- .aggregate(pipeline)
954
- .toArray());
955
- }
956
- catch {
957
- // ignore errors
958
- }
1166
+ // ignore errors
959
1167
  }
960
- const indexToProgress = Object.create(null);
961
- for (const { _id, progress } of currentOps) {
962
- indexToProgress[_id] = progress;
963
- }
964
- return indexToProgress;
965
1168
  }
966
- async fetchShardKey(ns, options = {}, executionOptions) {
967
- const docs = await this.find('config.collections', {
968
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
969
- _id: ns,
970
- // unsplittable introduced in SPM-3364 to mark unsharded collections
971
- // that are still being tracked in the catalog
972
- unsplittable: { $ne: true },
973
- }, { ...options, projection: { key: 1, _id: 0 } }, { abortSignal: executionOptions?.abortSignal });
974
- return docs.length ? docs[0].key : null;
1169
+ const indexToProgress = Object.create(null);
1170
+ for (const { _id, progress } of currentOps) {
1171
+ indexToProgress[_id] = progress;
975
1172
  }
976
- async _fetchShardKeyWithSilentFail(...args) {
977
- try {
978
- return await this.fetchShardKey(...args);
979
- }
980
- catch (err) {
981
- // Rethrow if we aborted along the way.
982
- if (this.isCancelError(err)) {
983
- throw err;
984
- }
985
- // Return null on error.
986
- // This is oftentimes a lack of permissions to run a find on config.collections.
987
- return null;
988
- }
1173
+ return indexToProgress;
1174
+ }
1175
+ async fetchShardKey(ns, options = {}, executionOptions) {
1176
+ const docs = await this.find('config.collections', {
1177
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1178
+ _id: ns,
1179
+ // unsplittable introduced in SPM-3364 to mark unsharded collections
1180
+ // that are still being tracked in the catalog
1181
+ unsplittable: { $ne: true },
1182
+ }, { ...options, projection: { key: 1, _id: 0 } }, { abortSignal: executionOptions?.abortSignal });
1183
+ return docs.length ? docs[0].key : null;
1184
+ }
1185
+ async _fetchShardKeyWithSilentFail(...args) {
1186
+ try {
1187
+ return await this.fetchShardKey(...args);
989
1188
  }
990
- async indexes(ns, options) {
991
- if (options?.full === false) {
992
- const indexes = Object.entries(await this._collection(ns, 'CRUD').indexes({ ...options, full: false }));
993
- return indexes.map((compactIndexEntry) => {
994
- const [name, keys] = compactIndexEntry;
995
- return (0, index_detail_helper_1.createIndexDefinition)(ns, null, {
996
- name,
997
- key: Object.fromEntries(keys),
998
- });
999
- });
1189
+ catch (err) {
1190
+ // Rethrow if we aborted along the way.
1191
+ if (this.isCancelError(err)) {
1192
+ throw err;
1000
1193
  }
1001
- const [indexes, indexStats, indexSizes, indexProgress, shardKey] = await Promise.all([
1002
- this._collection(ns, 'CRUD').indexes({ ...options, full: true }),
1003
- this._indexStats(ns),
1004
- this._indexSizes(ns),
1005
- this._indexProgress(ns),
1006
- this._fetchShardKeyWithSilentFail(ns),
1007
- ]);
1008
- const maxSize = Math.max(...Object.values(indexSizes));
1009
- return indexes
1010
- .filter((index) => {
1011
- return !!index.name;
1012
- })
1013
- .map((index) => {
1014
- const name = index.name;
1015
- return (0, index_detail_helper_1.createIndexDefinition)(ns, shardKey ?? null, index, indexStats[name], indexSizes[name], maxSize, indexProgress[name]);
1016
- });
1017
- }
1018
- async instance() {
1019
- return {
1020
- ...(await (0, instance_detail_helper_2.getInstance)(this._initializedClient('META'), this._connectionOptions.connectionString)),
1021
- // Need to get the CSFLE flag from the CRUD client, not the META one
1022
- csfleMode: this.getCSFLEMode(),
1023
- };
1024
- }
1025
- async insertOne(ns, doc, options) {
1026
- const coll = this._collection(ns, 'CRUD');
1027
- return await coll.insertOne(doc, options);
1028
- }
1029
- async insertMany(ns, docs, options) {
1030
- const coll = this._collection(ns, 'CRUD');
1031
- return await coll.insertMany(docs, options);
1194
+ // Return null on error.
1195
+ // This is oftentimes a lack of permissions to run a find on config.collections.
1196
+ return null;
1032
1197
  }
1033
- async updateCollection(ns,
1034
- // Collection name to update that will be passed to the collMod command will
1035
- // be derived from the provided namespace, this is why we are explicitly
1036
- // prohibiting to pass collMod flag here
1037
- flags = {}) {
1038
- const collectionName = this._collectionName(ns);
1039
- const db = this._database(ns, 'CRUD');
1040
- const result = await (0, run_command_1.runCommand)(db, {
1041
- // Order of arguments is important here, collMod is a command name and it
1042
- // should always be the first one in the object
1043
- collMod: collectionName,
1044
- ...flags,
1198
+ }
1199
+ async indexes(ns, options) {
1200
+ if (options?.full === false) {
1201
+ const indexes = Object.entries(await this._collection(ns, 'CRUD').indexes({ ...options, full: false }));
1202
+ return indexes.map((compactIndexEntry) => {
1203
+ const [name, keys] = compactIndexEntry;
1204
+ return (0, index_detail_helper_1.createIndexDefinition)(ns, null, {
1205
+ name,
1206
+ key: Object.fromEntries(keys),
1207
+ });
1045
1208
  });
1046
- // Reset the CSFLE-enabled client (if any) to clear any collection
1047
- // metadata caches that might still be active.
1048
- await this._resetCRUDClient();
1049
- return result;
1050
- }
1051
- bulkWrite(ns, operations, options) {
1052
- return this._collection(ns, 'CRUD').bulkWrite(operations, options);
1053
1209
  }
1054
- async currentOp() {
1055
- const db = this._database('admin', 'META');
1056
- const pipelineWithTruncateOps = [
1057
- {
1058
- $currentOp: {
1059
- allUsers: true,
1060
- idleConnections: false,
1061
- truncateOps: false,
1062
- },
1210
+ const [indexes, indexStats, indexSizes, indexProgress, shardKey] = await Promise.all([
1211
+ this._collection(ns, 'CRUD').indexes({ ...options, full: true }),
1212
+ this._indexStats(ns),
1213
+ this._indexSizes(ns),
1214
+ this._indexProgress(ns),
1215
+ this._fetchShardKeyWithSilentFail(ns),
1216
+ ]);
1217
+ const maxSize = Math.max(...Object.values(indexSizes));
1218
+ return indexes
1219
+ .filter((index) => {
1220
+ return !!index.name;
1221
+ })
1222
+ .map((index) => {
1223
+ const name = index.name;
1224
+ return (0, index_detail_helper_1.createIndexDefinition)(ns, shardKey ?? null, index, indexStats[name], indexSizes[name], maxSize, indexProgress[name]);
1225
+ });
1226
+ }
1227
+ async instance() {
1228
+ return {
1229
+ ...(await (0, instance_detail_helper_2.getInstance)(this._initializedClient('META'), this._connectionOptions.connectionString)),
1230
+ // Need to get the CSFLE flag from the CRUD client, not the META one
1231
+ csfleMode: this.getCSFLEMode(),
1232
+ };
1233
+ }
1234
+ async insertOne(ns, doc, options) {
1235
+ const coll = this._collection(ns, 'CRUD');
1236
+ return await coll.insertOne(doc, options);
1237
+ }
1238
+ async insertMany(ns, docs, options) {
1239
+ const coll = this._collection(ns, 'CRUD');
1240
+ return await coll.insertMany(docs, options);
1241
+ }
1242
+ async updateCollection(ns,
1243
+ // Collection name to update that will be passed to the collMod command will
1244
+ // be derived from the provided namespace, this is why we are explicitly
1245
+ // prohibiting to pass collMod flag here
1246
+ flags = {}) {
1247
+ const collectionName = this._collectionName(ns);
1248
+ const db = this._database(ns, 'CRUD');
1249
+ const result = await (0, run_command_1.runCommand)(db, {
1250
+ // Order of arguments is important here, collMod is a command name and it
1251
+ // should always be the first one in the object
1252
+ collMod: collectionName,
1253
+ ...flags,
1254
+ });
1255
+ // Reset the CSFLE-enabled client (if any) to clear any collection
1256
+ // metadata caches that might still be active.
1257
+ await this._resetCRUDClient();
1258
+ return result;
1259
+ }
1260
+ bulkWrite(ns, operations, options) {
1261
+ return this._collection(ns, 'CRUD').bulkWrite(operations, options);
1262
+ }
1263
+ async currentOp() {
1264
+ const db = this._database('admin', 'META');
1265
+ const pipelineWithTruncateOps = [
1266
+ {
1267
+ $currentOp: {
1268
+ allUsers: true,
1269
+ idleConnections: false,
1270
+ truncateOps: false,
1063
1271
  },
1064
- ];
1065
- const currentOp = await db.aggregate(pipelineWithTruncateOps).toArray();
1066
- return { inprog: currentOp };
1067
- }
1068
- getLastSeenTopology() {
1069
- return this._lastSeenTopology;
1070
- }
1071
- async serverStatus() {
1072
- const admin = this._database('admin', 'META');
1073
- return await (0, run_command_1.runCommand)(admin, { serverStatus: 1 }, { enableUtf8Validation: false });
1272
+ },
1273
+ ];
1274
+ const currentOp = await db.aggregate(pipelineWithTruncateOps).toArray();
1275
+ return { inprog: currentOp };
1276
+ }
1277
+ getLastSeenTopology() {
1278
+ return this._lastSeenTopology;
1279
+ }
1280
+ async serverStatus() {
1281
+ const admin = this._database('admin', 'META');
1282
+ return await (0, run_command_1.runCommand)(admin, { serverStatus: 1 }, { enableUtf8Validation: false });
1283
+ }
1284
+ async top() {
1285
+ const adminDb = this._database('admin', 'META');
1286
+ return await (0, run_command_1.runCommand)(adminDb, { top: 1 }, { enableUtf8Validation: false });
1287
+ }
1288
+ async createView(name, sourceNs, pipeline, options = {}) {
1289
+ const createCollectionOptions = {
1290
+ ...options,
1291
+ viewOn: this._collectionName(sourceNs),
1292
+ pipeline,
1293
+ };
1294
+ const db = this._database(sourceNs, 'CRUD');
1295
+ return await db.createCollection(name, createCollectionOptions);
1296
+ }
1297
+ _buildSamplingPipeline({ query, size, fields }) {
1298
+ const pipeline = [];
1299
+ if (query && Object.keys(query).length > 0) {
1300
+ pipeline.push({
1301
+ $match: query,
1302
+ });
1074
1303
  }
1075
- async top() {
1076
- const adminDb = this._database('admin', 'META');
1077
- return await (0, run_command_1.runCommand)(adminDb, { top: 1 }, { enableUtf8Validation: false });
1304
+ pipeline.push({
1305
+ $sample: {
1306
+ size: size === 0 ? 0 : size || 1000,
1307
+ },
1308
+ });
1309
+ // add $project stage if projection (fields) was specified
1310
+ if (fields && Object.keys(fields).length > 0) {
1311
+ pipeline.push({
1312
+ $project: fields,
1313
+ });
1078
1314
  }
1079
- async createView(name, sourceNs, pipeline, options = {}) {
1080
- const createCollectionOptions = {
1081
- ...options,
1082
- viewOn: this._collectionName(sourceNs),
1083
- pipeline,
1315
+ return pipeline;
1316
+ }
1317
+ sampleCursor(ns, samplingOptions = {}, options = {}, executionOptions) {
1318
+ const pipeline = this._buildSamplingPipeline(samplingOptions);
1319
+ return this.aggregateCursor(ns, pipeline, {
1320
+ allowDiskUse: true,
1321
+ // When the read preference isn't set in the connection string explicitly,
1322
+ // then we allow consumers to default to a read preference, for instance
1323
+ // secondaryPreferred to avoid using the primary for analyzing documents.
1324
+ ...this._getOptionsWithFallbackReadPreference(options, executionOptions),
1325
+ });
1326
+ }
1327
+ sample(ns, samplingOptions = {}, options = {}, executionOptions) {
1328
+ const pipeline = this._buildSamplingPipeline(samplingOptions);
1329
+ return this.aggregate(ns, pipeline, {
1330
+ allowDiskUse: true,
1331
+ // When the read preference isn't set in the connection string explicitly,
1332
+ // then we allow consumers to default to a read preference, for instance
1333
+ // secondaryPreferred to avoid using the primary for analyzing documents.
1334
+ ...this._getOptionsWithFallbackReadPreference(options, executionOptions),
1335
+ }, executionOptions);
1336
+ }
1337
+ _startSession(clientType) {
1338
+ const session = this._initializedClient(clientType).startSession();
1339
+ session[kSessionClientType] = clientType;
1340
+ return session;
1341
+ }
1342
+ _killSessions(sessions) {
1343
+ const sessionsArray = Array.isArray(sessions) ? sessions : [sessions];
1344
+ const clientTypes = new Set(sessionsArray.map((s) => s[kSessionClientType]));
1345
+ if (clientTypes.size !== 1) {
1346
+ throw new Error(`Cannot kill sessions without a specific client type: [${[
1347
+ ...clientTypes,
1348
+ ].join(', ')}]`);
1349
+ }
1350
+ const [clientType] = clientTypes;
1351
+ return (0, run_command_1.runCommand)(this._database('admin', clientType), {
1352
+ killSessions: sessionsArray.map((s) => s.id),
1353
+ });
1354
+ }
1355
+ isConnected() {
1356
+ // This is better than just returning internal `_isConnecting` as this
1357
+ // actually shows when the client is available on the NativeClient instance
1358
+ // and connected
1359
+ return !!this._metadataClient;
1360
+ }
1361
+ async _cancellableOperation(start, stop = () => Promise.resolve(), abortSignal) {
1362
+ if (!abortSignal) {
1363
+ return await start();
1364
+ }
1365
+ if (abortSignal.aborted) {
1366
+ // AbortSignal.reason is supported from node v17.2.0.
1367
+ throw abortSignal.reason ?? (0, compass_utils_1.createCancelError)();
1368
+ }
1369
+ const session = this._startSession('CRUD');
1370
+ let result;
1371
+ const abort = async () => {
1372
+ const logAbortError = (error) => {
1373
+ this._logger.warn((0, logger_1.mongoLogId)(1_001_000_140), 'Attempting to kill the operation failed', { error: error.message });
1084
1374
  };
1085
- const db = this._database(sourceNs, 'CRUD');
1086
- return await db.createCollection(name, createCollectionOptions);
1375
+ await stop(session).catch(logAbortError);
1376
+ await this._killSessions(session).catch(logAbortError);
1377
+ };
1378
+ try {
1379
+ result = await (0, compass_utils_1.raceWithAbort)(start(session), abortSignal);
1087
1380
  }
1088
- _buildSamplingPipeline({ query, size, fields }) {
1089
- const pipeline = [];
1090
- if (query && Object.keys(query).length > 0) {
1091
- pipeline.push({
1092
- $match: query,
1093
- });
1381
+ catch (err) {
1382
+ if ((0, compass_utils_1.isCancelError)(err)) {
1383
+ await abort();
1094
1384
  }
1095
- pipeline.push({
1096
- $sample: {
1097
- size: size === 0 ? 0 : size || 1000,
1098
- },
1385
+ throw err;
1386
+ }
1387
+ return result;
1388
+ }
1389
+ isCancelError(error) {
1390
+ return (0, compass_utils_1.isCancelError)(error);
1391
+ }
1392
+ _setupListeners(client) {
1393
+ if (client) {
1394
+ client.on('connectionCreated', (evt) => {
1395
+ const { address, connectionId } = evt;
1396
+ this._logger.info((0, logger_1.mongoLogId)(1_001_000_027), 'Driver connection created', {
1397
+ address,
1398
+ serverConnectionId: connectionId,
1399
+ });
1099
1400
  });
1100
- // add $project stage if projection (fields) was specified
1101
- if (fields && Object.keys(fields).length > 0) {
1102
- pipeline.push({
1103
- $project: fields,
1401
+ client.on('serverDescriptionChanged', (evt) => {
1402
+ this._logger.info((0, logger_1.mongoLogId)(1_001_000_018), 'Server description changed', {
1403
+ address: evt.address,
1404
+ error: evt.newDescription.error?.message ?? null,
1405
+ previousType: evt.previousDescription.type,
1406
+ newType: evt.newDescription.type,
1104
1407
  });
1105
- }
1106
- return pipeline;
1107
- }
1108
- sampleCursor(ns, samplingOptions = {}, options = {}, executionOptions) {
1109
- const pipeline = this._buildSamplingPipeline(samplingOptions);
1110
- return this.aggregateCursor(ns, pipeline, {
1111
- allowDiskUse: true,
1112
- // When the read preference isn't set in the connection string explicitly,
1113
- // then we allow consumers to default to a read preference, for instance
1114
- // secondaryPreferred to avoid using the primary for analyzing documents.
1115
- ...this._getOptionsWithFallbackReadPreference(options, executionOptions),
1116
1408
  });
1117
- }
1118
- sample(ns, samplingOptions = {}, options = {}, executionOptions) {
1119
- const pipeline = this._buildSamplingPipeline(samplingOptions);
1120
- return this.aggregate(ns, pipeline, {
1121
- allowDiskUse: true,
1122
- // When the read preference isn't set in the connection string explicitly,
1123
- // then we allow consumers to default to a read preference, for instance
1124
- // secondaryPreferred to avoid using the primary for analyzing documents.
1125
- ...this._getOptionsWithFallbackReadPreference(options, executionOptions),
1126
- }, executionOptions);
1127
- }
1128
- _startSession(clientType) {
1129
- const session = this._initializedClient(clientType).startSession();
1130
- session[kSessionClientType] = clientType;
1131
- return session;
1132
- }
1133
- _killSessions(sessions) {
1134
- const sessionsArray = Array.isArray(sessions) ? sessions : [sessions];
1135
- const clientTypes = new Set(sessionsArray.map((s) => s[kSessionClientType]));
1136
- if (clientTypes.size !== 1) {
1137
- throw new Error(`Cannot kill sessions without a specific client type: [${[
1138
- ...clientTypes,
1139
- ].join(', ')}]`);
1140
- }
1141
- const [clientType] = clientTypes;
1142
- return (0, run_command_1.runCommand)(this._database('admin', clientType), {
1143
- killSessions: sessionsArray.map((s) => s.id),
1409
+ client.on('serverOpening', (evt) => {
1410
+ this._logger.info((0, logger_1.mongoLogId)(1_001_000_019), 'Server opening', {
1411
+ address: evt.address,
1412
+ });
1144
1413
  });
1145
- }
1146
- isConnected() {
1147
- // This is better than just returning internal `_isConnecting` as this
1148
- // actually shows when the client is available on the NativeClient instance
1149
- // and connected
1150
- return !!this._metadataClient;
1151
- }
1152
- async _cancellableOperation(start, stop = () => Promise.resolve(), abortSignal) {
1153
- if (!abortSignal) {
1154
- return await start();
1155
- }
1156
- if (abortSignal.aborted) {
1157
- // AbortSignal.reason is supported from node v17.2.0.
1158
- throw abortSignal.reason ?? (0, compass_utils_1.createCancelError)();
1159
- }
1160
- const session = this._startSession('CRUD');
1161
- let result;
1162
- const abort = async () => {
1163
- const logAbortError = (error) => {
1164
- this._logger.warn((0, logger_1.mongoLogId)(1_001_000_140), 'Attempting to kill the operation failed', { error: error.message });
1414
+ client.on('close', () => {
1415
+ this._logger.info((0, logger_1.mongoLogId)(1_001_000_315), 'Client is closed');
1416
+ this._emitter.emit('close');
1417
+ });
1418
+ client.on('serverClosed', (evt) => {
1419
+ this._logger.info((0, logger_1.mongoLogId)(1_001_000_020), 'Server closed', {
1420
+ address: evt.address,
1421
+ });
1422
+ });
1423
+ client.on('topologyDescriptionChanged', (evt) => {
1424
+ this._isWritable = this._checkIsWritable(evt);
1425
+ const attr = {
1426
+ isWritable: this.isWritable(),
1427
+ isMongos: this.isMongos(),
1428
+ previousType: evt.previousDescription.type,
1429
+ newType: evt.newDescription.type,
1165
1430
  };
1166
- await stop(session).catch(logAbortError);
1167
- await this._killSessions(session).catch(logAbortError);
1431
+ this._logger.info((0, logger_1.mongoLogId)(1_001_000_021), 'Topology description changed', attr);
1432
+ this._lastSeenTopology = evt.newDescription;
1433
+ this._emitter.emit('topologyDescriptionChanged', evt);
1434
+ });
1435
+ // Heartbeat events are fairly noisy. We put some effort into
1436
+ // making sure that we only log events that actually contain
1437
+ // meaningful information.
1438
+ const heartbeatStatusMap = new Map();
1439
+ const isSignificantDurationChange = (before, after) => {
1440
+ // Changes in pings below 200ms are not particularly concerning here.
1441
+ before = Math.max(before, 200);
1442
+ after = Math.max(after, 200);
1443
+ // Check if changes is at least 2× (in either direction).
1444
+ return Math.abs(Math.log2(before / after)) >= 1;
1168
1445
  };
1169
- try {
1170
- result = await (0, compass_utils_1.raceWithAbort)(start(session), abortSignal);
1171
- }
1172
- catch (err) {
1173
- if ((0, compass_utils_1.isCancelError)(err)) {
1174
- await abort();
1175
- }
1176
- throw err;
1177
- }
1178
- return result;
1179
- }
1180
- isCancelError(error) {
1181
- return (0, compass_utils_1.isCancelError)(error);
1182
- }
1183
- _setupListeners(client) {
1184
- if (client) {
1185
- client.on('connectionCreated', (evt) => {
1186
- const { address, connectionId } = evt;
1187
- this._logger.info((0, logger_1.mongoLogId)(1_001_000_027), 'Driver connection created', {
1188
- address,
1189
- serverConnectionId: connectionId,
1190
- });
1191
- });
1192
- client.on('serverDescriptionChanged', (evt) => {
1193
- this._logger.info((0, logger_1.mongoLogId)(1_001_000_018), 'Server description changed', {
1194
- address: evt.address,
1195
- error: evt.newDescription.error?.message ?? null,
1196
- previousType: evt.previousDescription.type,
1197
- newType: evt.newDescription.type,
1446
+ client.on('serverHeartbeatSucceeded', (evt) => {
1447
+ const previousStatus = heartbeatStatusMap.get(evt.connectionId);
1448
+ if (!previousStatus ||
1449
+ previousStatus.failure ||
1450
+ isSignificantDurationChange(previousStatus.duration, evt.duration)) {
1451
+ heartbeatStatusMap.set(evt.connectionId, {
1452
+ failure: null,
1453
+ duration: evt.duration,
1198
1454
  });
1199
- });
1200
- client.on('serverOpening', (evt) => {
1201
- this._logger.info((0, logger_1.mongoLogId)(1_001_000_019), 'Server opening', {
1202
- address: evt.address,
1455
+ this._logger.debug((0, logger_1.mongoLogId)(1_001_000_022), 'Server heartbeat succeeded', {
1456
+ connectionId: evt.connectionId,
1457
+ duration: evt.duration,
1203
1458
  });
1204
- });
1205
- client.on('close', () => {
1206
- this._logger.info((0, logger_1.mongoLogId)(1_001_000_315), 'Client is closed');
1207
- this._emitter.emit('close');
1208
- });
1209
- client.on('serverClosed', (evt) => {
1210
- this._logger.info((0, logger_1.mongoLogId)(1_001_000_020), 'Server closed', {
1211
- address: evt.address,
1459
+ }
1460
+ });
1461
+ client.on('serverHeartbeatFailed', (evt) => {
1462
+ const previousStatus = heartbeatStatusMap.get(evt.connectionId);
1463
+ if (!previousStatus ||
1464
+ !previousStatus.failure ||
1465
+ isSignificantDurationChange(previousStatus.duration, evt.duration)) {
1466
+ heartbeatStatusMap.set(evt.connectionId, {
1467
+ failure: evt.failure.message,
1468
+ duration: evt.duration,
1212
1469
  });
1213
- });
1214
- client.on('topologyDescriptionChanged', (evt) => {
1215
- this._isWritable = this._checkIsWritable(evt);
1216
- const attr = {
1217
- isWritable: this.isWritable(),
1218
- isMongos: this.isMongos(),
1219
- previousType: evt.previousDescription.type,
1220
- newType: evt.newDescription.type,
1221
- };
1222
- this._logger.info((0, logger_1.mongoLogId)(1_001_000_021), 'Topology description changed', attr);
1223
- this._lastSeenTopology = evt.newDescription;
1224
- this._emitter.emit('topologyDescriptionChanged', evt);
1225
- });
1226
- // Heartbeat events are fairly noisy. We put some effort into
1227
- // making sure that we only log events that actually contain
1228
- // meaningful information.
1229
- const heartbeatStatusMap = new Map();
1230
- const isSignificantDurationChange = (before, after) => {
1231
- // Changes in pings below 200ms are not particularly concerning here.
1232
- before = Math.max(before, 200);
1233
- after = Math.max(after, 200);
1234
- // Check if changes is at least 2× (in either direction).
1235
- return Math.abs(Math.log2(before / after)) >= 1;
1236
- };
1237
- client.on('serverHeartbeatSucceeded', (evt) => {
1238
- const previousStatus = heartbeatStatusMap.get(evt.connectionId);
1239
- if (!previousStatus ||
1240
- previousStatus.failure ||
1241
- isSignificantDurationChange(previousStatus.duration, evt.duration)) {
1242
- heartbeatStatusMap.set(evt.connectionId, {
1243
- failure: null,
1244
- duration: evt.duration,
1245
- });
1246
- this._logger.debug((0, logger_1.mongoLogId)(1_001_000_022), 'Server heartbeat succeeded', {
1247
- connectionId: evt.connectionId,
1248
- duration: evt.duration,
1249
- });
1250
- }
1251
- });
1252
- client.on('serverHeartbeatFailed', (evt) => {
1253
- const previousStatus = heartbeatStatusMap.get(evt.connectionId);
1254
- if (!previousStatus ||
1255
- !previousStatus.failure ||
1256
- isSignificantDurationChange(previousStatus.duration, evt.duration)) {
1257
- heartbeatStatusMap.set(evt.connectionId, {
1258
- failure: evt.failure.message,
1259
- duration: evt.duration,
1260
- });
1261
- this._logger.warn((0, logger_1.mongoLogId)(1_001_000_023), 'Server heartbeat failed', {
1262
- connectionId: evt.connectionId,
1263
- duration: evt.duration,
1264
- failure: evt.failure.message,
1265
- });
1266
- }
1267
- this._emitter.emit('serverHeartbeatFailed', evt);
1268
- });
1269
- client.on('commandStarted', (evt) => {
1270
- const { address, connectionId, requestId, commandName, databaseName } = evt;
1271
- this._logger.debug((0, logger_1.mongoLogId)(1_001_000_028), 'Driver command started', {
1272
- address,
1273
- databaseName,
1274
- serverConnectionId: connectionId,
1275
- requestId,
1276
- commandName,
1470
+ this._logger.warn((0, logger_1.mongoLogId)(1_001_000_023), 'Server heartbeat failed', {
1471
+ connectionId: evt.connectionId,
1472
+ duration: evt.duration,
1473
+ failure: evt.failure.message,
1277
1474
  });
1475
+ }
1476
+ this._emitter.emit('serverHeartbeatFailed', evt);
1477
+ });
1478
+ client.on('commandStarted', (evt) => {
1479
+ const { address, connectionId, requestId, commandName, databaseName } = evt;
1480
+ this._logger.debug((0, logger_1.mongoLogId)(1_001_000_028), 'Driver command started', {
1481
+ address,
1482
+ databaseName,
1483
+ serverConnectionId: connectionId,
1484
+ requestId,
1485
+ commandName,
1278
1486
  });
1279
- client.on('commandSucceeded', (evt) => {
1280
- const { address, connectionId, duration, requestId, commandName } = evt;
1281
- this._logger.debug((0, logger_1.mongoLogId)(1_001_000_029), 'Driver command succeeded', {
1282
- address,
1283
- requestId,
1284
- serverConnectionId: connectionId,
1285
- duration,
1286
- commandName,
1287
- });
1487
+ });
1488
+ client.on('commandSucceeded', (evt) => {
1489
+ const { address, connectionId, duration, requestId, commandName } = evt;
1490
+ this._logger.debug((0, logger_1.mongoLogId)(1_001_000_029), 'Driver command succeeded', {
1491
+ address,
1492
+ requestId,
1493
+ serverConnectionId: connectionId,
1494
+ duration,
1495
+ commandName,
1288
1496
  });
1289
- client.on('commandFailed', (evt) => {
1290
- const { address, connectionId, duration, requestId, commandName, failure, } = evt;
1291
- this._logger.debug((0, logger_1.mongoLogId)(1_001_000_030), 'Driver command failed', {
1292
- address,
1293
- serverConnectionId: connectionId,
1294
- duration,
1295
- requestId,
1296
- commandName,
1297
- failure: failure.message,
1298
- });
1497
+ });
1498
+ client.on('commandFailed', (evt) => {
1499
+ const { address, connectionId, duration, requestId, commandName, failure, } = evt;
1500
+ this._logger.debug((0, logger_1.mongoLogId)(1_001_000_030), 'Driver command failed', {
1501
+ address,
1502
+ serverConnectionId: connectionId,
1503
+ duration,
1504
+ requestId,
1505
+ commandName,
1506
+ failure: failure.message,
1299
1507
  });
1300
- }
1301
- }
1302
- _initializedClient(type) {
1303
- if (type !== 'CRUD' && type !== 'META') {
1304
- throw new Error(`Invalid client type: ${type}`);
1305
- }
1306
- const client = type === 'CRUD' && this._useCRUDClient
1307
- ? this._crudClient
1308
- : this._metadataClient;
1309
- if (!client) {
1310
- throw new Error(`Client not yet initialized [${type}]`);
1311
- }
1312
- return client;
1313
- }
1314
- _getCSFLECollectionTracker() {
1315
- if (!this._csfleCollectionTracker) {
1316
- throw new Error(`Client not yet initialized [CSFLECollectionTracker]`);
1317
- }
1318
- return this._csfleCollectionTracker;
1508
+ });
1319
1509
  }
1320
- isUpdateAllowed(ns, originalDocument) {
1321
- return this._getCSFLECollectionTracker().isUpdateAllowed(ns, originalDocument);
1510
+ }
1511
+ _initializedClient(type) {
1512
+ if (type !== 'CRUD' && type !== 'META') {
1513
+ throw new Error(`Invalid client type: ${type}`);
1322
1514
  }
1323
- knownSchemaForCollection(ns) {
1324
- return this._getCSFLECollectionTracker().knownSchemaForCollection(ns);
1515
+ const client = type === 'CRUD' && this._useCRUDClient
1516
+ ? this._crudClient
1517
+ : this._metadataClient;
1518
+ if (!client) {
1519
+ throw new Error(`Client not yet initialized [${type}]`);
1325
1520
  }
1326
- async databaseStats(name) {
1327
- const db = this._database(name, 'META');
1328
- const stats = await (0, run_command_1.runCommand)(db, { dbStats: 1 }, {
1329
- enableUtf8Validation: false,
1330
- ...maybeOverrideReadPreference(this.isMongos(), this._crudClient?.readPreference),
1331
- });
1332
- const normalized = (0, instance_detail_helper_2.adaptDatabaseInfo)(stats);
1333
- return { name, ...normalized };
1521
+ return client;
1522
+ }
1523
+ _getCSFLECollectionTracker() {
1524
+ if (!this._csfleCollectionTracker) {
1525
+ throw new Error(`Client not yet initialized [CSFLECollectionTracker]`);
1334
1526
  }
1335
- async previewUpdate(ns, filter, update, executionOptions = {}) {
1336
- const { abortSignal = new AbortController().signal, sample = 10, timeout = 1000, } = executionOptions;
1337
- const startTimeMS = Date.now();
1338
- const remainingTimeoutMS = () => Math.max(1, timeout - (Date.now() - startTimeMS));
1339
- return await this._cancellableOperation(async (session) => {
1340
- if (!session) {
1341
- throw new Error('Could not open session.');
1342
- }
1343
- try {
1344
- return await session.withTransaction(async () => {
1345
- const coll = this._collection(ns, 'CRUD');
1346
- const docsToPreview = await coll
1347
- .find(filter, {
1348
- session,
1349
- maxTimeMS: remainingTimeoutMS(),
1350
- // by using promoteValues: false we can spot BSON type changes
1351
- // when diffing. ie. new Double(1) -> new Int32(1)
1352
- promoteValues: false,
1353
- })
1354
- .sort({ _id: 1 })
1355
- .limit(sample)
1356
- .toArray();
1357
- const idsToPreview = docsToPreview.map((doc) => doc._id);
1358
- await coll.updateMany({ _id: { $in: idsToPreview } }, update, {
1359
- session,
1360
- maxTimeMS: remainingTimeoutMS(),
1361
- });
1362
- const changedDocs = await coll
1363
- .find({ _id: { $in: idsToPreview } }, {
1364
- session,
1365
- maxTimeMS: remainingTimeoutMS(),
1366
- promoteValues: false,
1367
- })
1368
- .sort({ _id: 1 })
1369
- .toArray();
1370
- await session.abortTransaction();
1371
- await session.endSession();
1372
- const changes = docsToPreview.map((before, idx) => ({
1373
- before,
1374
- after: changedDocs[idx],
1375
- }));
1376
- return { changes };
1377
- }, {
1527
+ return this._csfleCollectionTracker;
1528
+ }
1529
+ isUpdateAllowed(ns, originalDocument) {
1530
+ return this._getCSFLECollectionTracker().isUpdateAllowed(ns, originalDocument);
1531
+ }
1532
+ knownSchemaForCollection(ns) {
1533
+ return this._getCSFLECollectionTracker().knownSchemaForCollection(ns);
1534
+ }
1535
+ async databaseStats(name) {
1536
+ const db = this._database(name, 'META');
1537
+ const stats = await (0, run_command_1.runCommand)(db, { dbStats: 1 }, {
1538
+ enableUtf8Validation: false,
1539
+ ...maybeOverrideReadPreference(this.isMongos(), this._crudClient?.readPreference),
1540
+ });
1541
+ const normalized = (0, instance_detail_helper_2.adaptDatabaseInfo)(stats);
1542
+ return { name, ...normalized };
1543
+ }
1544
+ async previewUpdate(ns, filter, update, executionOptions = {}) {
1545
+ const { abortSignal = new AbortController().signal, sample = 10, timeout = 1000, } = executionOptions;
1546
+ const startTimeMS = Date.now();
1547
+ const remainingTimeoutMS = () => Math.max(1, timeout - (Date.now() - startTimeMS));
1548
+ return await this._cancellableOperation(async (session) => {
1549
+ if (!session) {
1550
+ throw new Error('Could not open session.');
1551
+ }
1552
+ try {
1553
+ return await session.withTransaction(async () => {
1554
+ const coll = this._collection(ns, 'CRUD');
1555
+ const docsToPreview = await coll
1556
+ .find(filter, {
1557
+ session,
1558
+ maxTimeMS: remainingTimeoutMS(),
1559
+ // by using promoteValues: false we can spot BSON type changes
1560
+ // when diffing. ie. new Double(1) -> new Int32(1)
1561
+ promoteValues: false,
1562
+ })
1563
+ .sort({ _id: 1 })
1564
+ .limit(sample)
1565
+ .toArray();
1566
+ const idsToPreview = docsToPreview.map((doc) => doc._id);
1567
+ await coll.updateMany({ _id: { $in: idsToPreview } }, update, {
1568
+ session,
1378
1569
  maxTimeMS: remainingTimeoutMS(),
1379
1570
  });
1571
+ const changedDocs = await coll
1572
+ .find({ _id: { $in: idsToPreview } }, {
1573
+ session,
1574
+ maxTimeMS: remainingTimeoutMS(),
1575
+ promoteValues: false,
1576
+ })
1577
+ .sort({ _id: 1 })
1578
+ .toArray();
1579
+ await session.abortTransaction();
1580
+ await session.endSession();
1581
+ const changes = docsToPreview.map((before, idx) => ({
1582
+ before,
1583
+ after: changedDocs[idx],
1584
+ }));
1585
+ return { changes };
1586
+ }, {
1587
+ maxTimeMS: remainingTimeoutMS(),
1588
+ });
1589
+ }
1590
+ catch (err) {
1591
+ if (isTransactionAbortError(err)) {
1592
+ // The transaction was aborted while it was still calculating the
1593
+ // preview. Just return something here rather than erroring. No
1594
+ // reason to abort the transaction or end the session again because
1595
+ // we only got here because that already happened.
1596
+ return { changes: [] };
1380
1597
  }
1381
- catch (err) {
1382
- if (isTransactionAbortError(err)) {
1383
- // The transaction was aborted while it was still calculating the
1384
- // preview. Just return something here rather than erroring. No
1385
- // reason to abort the transaction or end the session again because
1386
- // we only got here because that already happened.
1387
- return { changes: [] };
1388
- }
1389
- // The only way this if statement would be true is if aborting the
1390
- // transaction and ending the session itself failed above. Unlikely.
1391
- if (session.inTransaction()) {
1392
- await session.abortTransaction();
1393
- await session.endSession();
1394
- }
1395
- throw err;
1598
+ // The only way this if statement would be true is if aborting the
1599
+ // transaction and ending the session itself failed above. Unlikely.
1600
+ if (session.inTransaction()) {
1601
+ await session.abortTransaction();
1602
+ await session.endSession();
1396
1603
  }
1397
- }, async () => {
1398
- // Rely on the session being killed when we cancel the operation. It can
1399
- // take a few seconds before the driver reacts, but the Promise.race()
1400
- // against the abort signal should cause the UI to immediately be
1401
- // notified that the operation was cancelled. We don't abort the
1402
- // transaction or end the session as well because the code we run inside
1403
- // session.withTransaction() above would experience race conditions.
1404
- }, abortSignal);
1405
- }
1406
- /**
1407
- * @param databaseName - The name of the database.
1408
- * @param collectionName - The name of the collection.
1409
- * @param data - The result of the collStats command.
1410
- */
1411
- _buildCollectionStats(databaseName, collectionName, data) {
1412
- return {
1413
- ns: databaseName + '.' + collectionName,
1414
- name: collectionName,
1415
- database: databaseName,
1416
- is_capped: data.capped,
1417
- document_count: data.count ?? 0,
1418
- document_size: data.size,
1419
- avg_document_size: data.avgObjSize ?? 0,
1420
- storage_size: data.storageSize ?? 0,
1421
- free_storage_size: data.freeStorageSize ?? 0,
1422
- index_count: data.nindexes ?? 0,
1423
- index_size: data.totalIndexSize ?? 0,
1424
- bucket_count: data.bucket_count,
1425
- avg_bucket_size: data.avg_bucket_size,
1426
- };
1427
- }
1428
- /**
1429
- * Get the collection to operate on.
1430
- *
1431
- * @param ns - The namespace.
1432
- */
1433
- _collection(ns, type) {
1434
- return this._initializedClient(type)
1435
- .db(this._databaseName(ns))
1436
- .collection(this._collectionName(ns));
1437
- }
1438
- /**
1439
- * Get the database to operate on.
1440
- *
1441
- * @param ns - The namespace.
1442
- */
1443
- _database(ns, type) {
1444
- return this._initializedClient(type).db(this._databaseName(ns));
1445
- }
1446
- /**
1447
- * Get the collection name from a namespace.
1448
- *
1449
- * @param ns - The namespace in database.collection format.
1450
- */
1451
- _collectionName(ns) {
1452
- return (0, mongodb_ns_1.default)(ns).collection;
1453
- }
1454
- /**
1455
- * Get the database name from a namespace.
1456
- *
1457
- * @param ns - The namespace in database.collection format.
1458
- */
1459
- _databaseName(ns) {
1460
- return (0, mongodb_ns_1.default)(ns).database;
1461
- }
1462
- /**
1463
- * Determine if the hello response indicates a writable server.
1464
- *
1465
- * @param evt - The topology description changed event.
1466
- *
1467
- * @returns If the server is writable.
1468
- */
1469
- _checkIsWritable(evt) {
1470
- return [...evt.newDescription.servers.values()].some((server) => server.isWritable);
1471
- }
1472
- _cleanup() {
1473
- this._emitter.removeAllListeners();
1474
- this._metadataClient?.removeAllListeners?.();
1475
- this._crudClient?.removeAllListeners?.();
1476
- this._metadataClient = undefined;
1477
- this._crudClient = undefined;
1478
- this._tunnel = undefined;
1479
- this._state = undefined;
1480
- this._mongoClientConnectionOptions = undefined;
1481
- this._isWritable = false;
1482
- this._isConnecting = false;
1483
- }
1484
- async _resetCRUDClient() {
1485
- if (this.getCSFLEMode() === 'unavailable') {
1486
- // No separate client in use, don't do anything
1487
- return;
1488
- }
1489
- const crudClient = this._crudClient;
1490
- if (!crudClient) {
1491
- // In disconnected state, don't do anything
1492
- return;
1493
- }
1494
- const newClient = await crudClient[connect_mongo_client_1.createClonedClient]();
1495
- if (this._crudClient === crudClient) {
1496
- this._crudClient = newClient;
1497
- await crudClient.close();
1498
- }
1499
- else {
1500
- // If _crudClient has changed between start and end of
1501
- // connection establishment, don't do anything, just
1502
- // close and discard the new client.
1503
- await newClient.close();
1604
+ throw err;
1504
1605
  }
1606
+ }, async () => {
1607
+ // Rely on the session being killed when we cancel the operation. It can
1608
+ // take a few seconds before the driver reacts, but the Promise.race()
1609
+ // against the abort signal should cause the UI to immediately be
1610
+ // notified that the operation was cancelled. We don't abort the
1611
+ // transaction or end the session as well because the code we run inside
1612
+ // session.withTransaction() above would experience race conditions.
1613
+ }, abortSignal);
1614
+ }
1615
+ /**
1616
+ * @param databaseName - The name of the database.
1617
+ * @param collectionName - The name of the collection.
1618
+ * @param data - The result of the collStats command.
1619
+ */
1620
+ _buildCollectionStats(databaseName, collectionName, data) {
1621
+ return {
1622
+ ns: databaseName + '.' + collectionName,
1623
+ name: collectionName,
1624
+ database: databaseName,
1625
+ is_capped: data.capped,
1626
+ document_count: data.count ?? 0,
1627
+ document_size: data.size,
1628
+ avg_document_size: data.avgObjSize ?? 0,
1629
+ storage_size: data.storageSize ?? 0,
1630
+ free_storage_size: data.freeStorageSize ?? 0,
1631
+ index_count: data.nindexes ?? 0,
1632
+ index_size: data.totalIndexSize ?? 0,
1633
+ bucket_count: data.bucket_count,
1634
+ avg_bucket_size: data.avg_bucket_size,
1635
+ };
1636
+ }
1637
+ /**
1638
+ * Get the collection to operate on.
1639
+ *
1640
+ * @param ns - The namespace.
1641
+ */
1642
+ _collection(ns, type) {
1643
+ return this._initializedClient(type)
1644
+ .db(this._databaseName(ns))
1645
+ .collection(this._collectionName(ns));
1646
+ }
1647
+ /**
1648
+ * Get the database to operate on.
1649
+ *
1650
+ * @param ns - The namespace.
1651
+ */
1652
+ _database(ns, type) {
1653
+ return this._initializedClient(type).db(this._databaseName(ns));
1654
+ }
1655
+ /**
1656
+ * Get the collection name from a namespace.
1657
+ *
1658
+ * @param ns - The namespace in database.collection format.
1659
+ */
1660
+ _collectionName(ns) {
1661
+ return (0, mongodb_ns_1.default)(ns).collection;
1662
+ }
1663
+ /**
1664
+ * Get the database name from a namespace.
1665
+ *
1666
+ * @param ns - The namespace in database.collection format.
1667
+ */
1668
+ _databaseName(ns) {
1669
+ return (0, mongodb_ns_1.default)(ns).database;
1670
+ }
1671
+ /**
1672
+ * Determine if the hello response indicates a writable server.
1673
+ *
1674
+ * @param evt - The topology description changed event.
1675
+ *
1676
+ * @returns If the server is writable.
1677
+ */
1678
+ _checkIsWritable(evt) {
1679
+ return [...evt.newDescription.servers.values()].some((server) => server.isWritable);
1680
+ }
1681
+ _cleanup() {
1682
+ this._emitter.removeAllListeners();
1683
+ this._metadataClient?.removeAllListeners?.();
1684
+ this._crudClient?.removeAllListeners?.();
1685
+ this._metadataClient = undefined;
1686
+ this._crudClient = undefined;
1687
+ this._tunnel = undefined;
1688
+ this._state = undefined;
1689
+ this._mongoClientConnectionOptions = undefined;
1690
+ this._isWritable = false;
1691
+ this._isConnecting = false;
1692
+ }
1693
+ async _resetCRUDClient() {
1694
+ if (this.getCSFLEMode() === 'unavailable') {
1695
+ // No separate client in use, don't do anything
1696
+ return;
1697
+ }
1698
+ const crudClient = this._crudClient;
1699
+ if (!crudClient) {
1700
+ // In disconnected state, don't do anything
1701
+ return;
1702
+ }
1703
+ const newClient = await crudClient[connect_mongo_client_1.createClonedClient]();
1704
+ if (this._crudClient === crudClient) {
1705
+ this._crudClient = newClient;
1706
+ await crudClient.close();
1707
+ }
1708
+ else {
1709
+ // If _crudClient has changed between start and end of
1710
+ // connection establishment, don't do anything, just
1711
+ // close and discard the new client.
1712
+ await newClient.close();
1505
1713
  }
1506
- configuredKMSProviders() {
1507
- return (0, instance_detail_helper_2.configuredKMSProviders)(this._connectionOptions.fleOptions?.autoEncryption);
1508
- }
1509
- _csfleLogInformation(fleOptions) {
1510
- const kmsProviders = (0, instance_detail_helper_2.configuredKMSProviders)(fleOptions?.autoEncryption);
1511
- if (kmsProviders.length === 0)
1512
- return null;
1513
- return {
1514
- storeCredentials: fleOptions?.storeCredentials,
1515
- encryptedFieldsMapNamespaces: Object.keys({
1516
- ...fleOptions?.autoEncryption?.encryptedFieldsMap,
1517
- ...fleOptions?.autoEncryption?.schemaMap,
1518
- }),
1519
- keyVaultNamespace: fleOptions?.autoEncryption?.keyVaultNamespace,
1520
- kmsProviders,
1521
- };
1522
- }
1523
- async createDataKey(provider, options) {
1524
- const clientEncryption = this._getClientEncryption();
1525
- return await clientEncryption.createDataKey(provider, options ?? {});
1526
- }
1527
- _getClientEncryption() {
1528
- const crudClient = this._initializedClient('CRUD');
1529
- const autoEncryptionOptions = crudClient.options.autoEncryption;
1530
- const { proxyHost, proxyPort, proxyUsername, proxyPassword } = crudClient.options;
1531
- return new mongodb_1.ClientEncryption(crudClient, {
1532
- keyVaultNamespace: autoEncryptionOptions.keyVaultNamespace,
1533
- kmsProviders: autoEncryptionOptions.kmsProviders,
1534
- tlsOptions: autoEncryptionOptions.tlsOptions,
1535
- proxyOptions: proxyHost
1536
- ? {
1537
- proxyHost,
1538
- proxyPort,
1539
- proxyUsername,
1540
- proxyPassword,
1541
- }
1542
- : undefined,
1543
- });
1544
- }
1545
- async getUpdatedSecrets() {
1546
- if (!this._state)
1547
- return {};
1548
- return {
1549
- oidc: {
1550
- serializedState: await this._state.oidcPlugin.serialize(),
1551
- },
1552
- };
1553
- }
1554
- async listStreamProcessors(filter) {
1555
- const adminDb = this._database('admin', 'CRUD');
1556
- const { streamProcessors } = await (0, run_command_1.runCommand)(adminDb, {
1557
- listStreamProcessors: 1,
1558
- filter,
1559
- });
1560
- return streamProcessors;
1561
- }
1562
- async startStreamProcessor(name) {
1563
- const adminDb = this._database('admin', 'CRUD');
1564
- await (0, run_command_1.runCommand)(adminDb, { startStreamProcessor: name });
1565
- }
1566
- async stopStreamProcessor(name) {
1567
- const adminDb = this._database('admin', 'CRUD');
1568
- await (0, run_command_1.runCommand)(adminDb, { stopStreamProcessor: name });
1569
- }
1570
- async dropStreamProcessor(name) {
1571
- const adminDb = this._database('admin', 'CRUD');
1572
- await (0, run_command_1.runCommand)(adminDb, { dropStreamProcessor: name });
1573
- }
1574
- },
1575
- (() => {
1576
- const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
1577
- _collectionStats_decorators = [op((0, logger_1.mongoLogId)(1_001_000_178), ([dbName, collName], result) => {
1578
- return { ns: `${dbName}.${collName}`, ...(result && { result }) };
1579
- })];
1580
- _collectionInfo_decorators = [op((0, logger_1.mongoLogId)(1_001_000_179))];
1581
- _killOp_decorators = [op((0, logger_1.mongoLogId)(1_001_000_031))];
1582
- __connectionStatus_decorators = [op((0, logger_1.mongoLogId)(1_001_000_100))];
1583
- _listCollections_decorators = [op((0, logger_1.mongoLogId)(1_001_000_032), ([databaseName, , options], colls) => {
1584
- return {
1585
- db: databaseName,
1586
- nameOnly: options?.nameOnly ?? false,
1587
- ...(colls && { collectionsCount: colls.length }),
1588
- };
1589
- })];
1590
- _listDatabases_decorators = [op((0, logger_1.mongoLogId)(1_001_000_033), ([options], dbs) => {
1591
- return {
1592
- nameOnly: options?.nameOnly ?? false,
1593
- ...(dbs && { databasesCount: dbs.length }),
1594
- };
1595
- })];
1596
- _estimatedCount_decorators = [op((0, logger_1.mongoLogId)(1_001_000_034), ([ns, options]) => {
1597
- return { ns, maxTimeMS: options?.maxTimeMS };
1598
- })];
1599
- _count_decorators = [op((0, logger_1.mongoLogId)(1_001_000_035))];
1600
- _createCollection_decorators = [op((0, logger_1.mongoLogId)(1_001_000_036), ([ns, options], result) => {
1601
- return { ns, options, ...(result && { result }) };
1602
- })];
1603
- _createIndex_decorators = [op((0, logger_1.mongoLogId)(1_001_000_037), ([ns, spec, options], result) => {
1604
- return { ns, spec, options, ...(result && { result }) };
1605
- })];
1606
- _deleteOne_decorators = [op((0, logger_1.mongoLogId)(1_001_000_038), ([ns], result) => {
1607
- return { ns, ...(result && { result }) };
1608
- })];
1609
- _deleteMany_decorators = [op((0, logger_1.mongoLogId)(1_001_000_039), ([ns], result) => {
1610
- return { ns, ...(result && { result }) };
1611
- })];
1612
- _dropCollection_decorators = [op((0, logger_1.mongoLogId)(1_001_000_059), ([ns], result) => {
1613
- return { ns, ...(result && { result }) };
1614
- })];
1615
- _renameCollection_decorators = [op((0, logger_1.mongoLogId)(1_001_000_276))];
1616
- _dropDatabase_decorators = [op((0, logger_1.mongoLogId)(1_001_000_040), ([db], result) => {
1617
- return { db, ...(result && { result }) };
1618
- })];
1619
- _dropIndex_decorators = [op((0, logger_1.mongoLogId)(1_001_000_182), ([ns, name], result) => {
1620
- return { ns, name, ...(result && { result }) };
1621
- })];
1622
- _isListSearchIndexesSupported_decorators = [op((0, logger_1.mongoLogId)(1_001_000_237))];
1623
- _getSearchIndexes_decorators = [op((0, logger_1.mongoLogId)(1_001_000_238))];
1624
- _createSearchIndex_decorators = [op((0, logger_1.mongoLogId)(1_001_000_239))];
1625
- _updateSearchIndex_decorators = [op((0, logger_1.mongoLogId)(1_001_000_240))];
1626
- _dropSearchIndex_decorators = [op((0, logger_1.mongoLogId)(1_001_000_241))];
1627
- _aggregateCursor_decorators = [op((0, logger_1.mongoLogId)(1_001_000_041), ([ns, pipeline, options]) => {
1628
- return {
1629
- ns,
1630
- stages: pipeline.map((stage) => Object.keys(stage)[0]),
1631
- maxTimeMS: options?.maxTimeMS,
1632
- };
1633
- })];
1634
- _aggregate_decorators = [op((0, logger_1.mongoLogId)(1_001_000_181), ([ns, pipeline, options]) => {
1635
- return {
1636
- ns,
1637
- stages: pipeline.map((stage) => Object.keys(stage)[0]),
1638
- maxTimeMS: options?.maxTimeMS,
1639
- };
1640
- })];
1641
- _find_decorators = [op((0, logger_1.mongoLogId)(1_001_000_060), ([ns, , options]) => {
1642
- return { ns, maxTimeMS: options?.maxTimeMS };
1643
- })];
1644
- _findCursor_decorators = [op((0, logger_1.mongoLogId)(1_001_000_043))];
1645
- _findOneAndReplace_decorators = [op((0, logger_1.mongoLogId)(1_001_000_044))];
1646
- _findOneAndUpdate_decorators = [op((0, logger_1.mongoLogId)(1_001_000_045))];
1647
- _updateOne_decorators = [op((0, logger_1.mongoLogId)(1_001_000_183))];
1648
- _replaceOne_decorators = [op((0, logger_1.mongoLogId)(1_001_000_191))];
1649
- _explainFind_decorators = [op((0, logger_1.mongoLogId)(1_001_000_046), ([ns, , , executionOptions]) => {
1650
- return {
1651
- ns,
1652
- verbosity: executionOptions?.explainVerbosity || mongodb_1.ExplainVerbosity.executionStats,
1653
- };
1654
- })];
1655
- _explainAggregate_decorators = [op((0, logger_1.mongoLogId)(1_001_000_177), ([ns, , , executionOptions]) => {
1656
- return {
1657
- ns,
1658
- verbosity: executionOptions?.explainVerbosity || mongodb_1.ExplainVerbosity.executionStats,
1659
- };
1660
- })];
1661
- _fetchShardKey_decorators = [op((0, logger_1.mongoLogId)(1_001_000_381))];
1662
- _indexes_decorators = [op((0, logger_1.mongoLogId)(1_001_000_047))];
1663
- _instance_decorators = [op((0, logger_1.mongoLogId)(1_001_000_024), (_, instanceData) => {
1664
- if (instanceData) {
1665
- return {
1666
- serverVersion: instanceData.build.version,
1667
- genuineMongoDB: instanceData.genuineMongoDB,
1668
- dataLake: instanceData.dataLake,
1669
- featureCompatibilityVersion: instanceData.featureCompatibilityVersion,
1670
- };
1714
+ }
1715
+ configuredKMSProviders() {
1716
+ return (0, instance_detail_helper_2.configuredKMSProviders)(this._connectionOptions.fleOptions?.autoEncryption);
1717
+ }
1718
+ _csfleLogInformation(fleOptions) {
1719
+ const kmsProviders = (0, instance_detail_helper_2.configuredKMSProviders)(fleOptions?.autoEncryption);
1720
+ if (kmsProviders.length === 0)
1721
+ return null;
1722
+ return {
1723
+ storeCredentials: fleOptions?.storeCredentials,
1724
+ encryptedFieldsMapNamespaces: Object.keys({
1725
+ ...fleOptions?.autoEncryption?.encryptedFieldsMap,
1726
+ ...fleOptions?.autoEncryption?.schemaMap,
1727
+ }),
1728
+ keyVaultNamespace: fleOptions?.autoEncryption?.keyVaultNamespace,
1729
+ kmsProviders,
1730
+ };
1731
+ }
1732
+ async createDataKey(provider, options) {
1733
+ const clientEncryption = this._getClientEncryption();
1734
+ return await clientEncryption.createDataKey(provider, options ?? {});
1735
+ }
1736
+ _getClientEncryption() {
1737
+ const crudClient = this._initializedClient('CRUD');
1738
+ const autoEncryptionOptions = crudClient.options.autoEncryption;
1739
+ const { proxyHost, proxyPort, proxyUsername, proxyPassword } = crudClient.options;
1740
+ return new mongodb_1.ClientEncryption(crudClient, {
1741
+ keyVaultNamespace: autoEncryptionOptions.keyVaultNamespace,
1742
+ kmsProviders: autoEncryptionOptions.kmsProviders,
1743
+ tlsOptions: autoEncryptionOptions.tlsOptions,
1744
+ proxyOptions: proxyHost
1745
+ ? {
1746
+ proxyHost,
1747
+ proxyPort,
1748
+ proxyUsername,
1749
+ proxyPassword,
1671
1750
  }
1672
- })];
1673
- _insertOne_decorators = [op((0, logger_1.mongoLogId)(1_001_000_048), ([ns], result) => {
1674
- return { ns, ...(result && { acknowledged: result.acknowledged }) };
1675
- })];
1676
- _insertMany_decorators = [op((0, logger_1.mongoLogId)(1_001_000_049), ([ns], result) => {
1677
- return {
1678
- ns,
1679
- ...(result && {
1680
- acknowledged: result.acknowledged,
1681
- insertedCount: result.insertedCount,
1682
- }),
1683
- };
1684
- })];
1685
- _updateCollection_decorators = [op((0, logger_1.mongoLogId)(1_001_000_050), ([ns], result) => {
1686
- return { ns, ...(result && { result }) };
1687
- })];
1688
- _currentOp_decorators = [op((0, logger_1.mongoLogId)(1_001_000_053))];
1689
- _serverStatus_decorators = [op((0, logger_1.mongoLogId)(1_001_000_061), (_, result) => {
1690
- return result ? { result } : undefined;
1691
- })];
1692
- _top_decorators = [op((0, logger_1.mongoLogId)(1_001_000_062), (_, result) => {
1693
- return result ? { result } : undefined;
1694
- })];
1695
- _createView_decorators = [op((0, logger_1.mongoLogId)(1_001_000_055), ([name, sourceNs, pipeline, options], result) => {
1696
- return {
1697
- name,
1698
- sourceNs,
1699
- stages: pipeline.map((stage) => Object.keys(stage)[0]),
1700
- options,
1701
- ...(result && { result }),
1702
- };
1703
- })];
1704
- _databaseStats_decorators = [op((0, logger_1.mongoLogId)(1_001_000_057))];
1705
- _previewUpdate_decorators = [op((0, logger_1.mongoLogId)(1_001_000_266))];
1706
- _createDataKey_decorators = [op((0, logger_1.mongoLogId)(1_001_000_123), ([provider]) => {
1707
- return { provider };
1708
- })];
1709
- _listStreamProcessors_decorators = [op((0, logger_1.mongoLogId)(1_001_000_284))];
1710
- _startStreamProcessor_decorators = [op((0, logger_1.mongoLogId)(1_001_000_285))];
1711
- _stopStreamProcessor_decorators = [op((0, logger_1.mongoLogId)(1_001_000_286))];
1712
- _dropStreamProcessor_decorators = [op((0, logger_1.mongoLogId)(1_001_000_287))];
1713
- __esDecorate(_a, null, _collectionStats_decorators, { kind: "method", name: "collectionStats", static: false, private: false, access: { has: obj => "collectionStats" in obj, get: obj => obj.collectionStats }, metadata: _metadata }, null, _instanceExtraInitializers);
1714
- __esDecorate(_a, null, _collectionInfo_decorators, { kind: "method", name: "collectionInfo", static: false, private: false, access: { has: obj => "collectionInfo" in obj, get: obj => obj.collectionInfo }, metadata: _metadata }, null, _instanceExtraInitializers);
1715
- __esDecorate(_a, null, _killOp_decorators, { kind: "method", name: "killOp", static: false, private: false, access: { has: obj => "killOp" in obj, get: obj => obj.killOp }, metadata: _metadata }, null, _instanceExtraInitializers);
1716
- __esDecorate(_a, null, __connectionStatus_decorators, { kind: "method", name: "_connectionStatus", static: false, private: false, access: { has: obj => "_connectionStatus" in obj, get: obj => obj._connectionStatus }, metadata: _metadata }, null, _instanceExtraInitializers);
1717
- __esDecorate(_a, null, _listCollections_decorators, { kind: "method", name: "listCollections", static: false, private: false, access: { has: obj => "listCollections" in obj, get: obj => obj.listCollections }, metadata: _metadata }, null, _instanceExtraInitializers);
1718
- __esDecorate(_a, null, _listDatabases_decorators, { kind: "method", name: "listDatabases", static: false, private: false, access: { has: obj => "listDatabases" in obj, get: obj => obj.listDatabases }, metadata: _metadata }, null, _instanceExtraInitializers);
1719
- __esDecorate(_a, null, _estimatedCount_decorators, { kind: "method", name: "estimatedCount", static: false, private: false, access: { has: obj => "estimatedCount" in obj, get: obj => obj.estimatedCount }, metadata: _metadata }, null, _instanceExtraInitializers);
1720
- __esDecorate(_a, null, _count_decorators, { kind: "method", name: "count", static: false, private: false, access: { has: obj => "count" in obj, get: obj => obj.count }, metadata: _metadata }, null, _instanceExtraInitializers);
1721
- __esDecorate(_a, null, _createCollection_decorators, { kind: "method", name: "createCollection", static: false, private: false, access: { has: obj => "createCollection" in obj, get: obj => obj.createCollection }, metadata: _metadata }, null, _instanceExtraInitializers);
1722
- __esDecorate(_a, null, _createIndex_decorators, { kind: "method", name: "createIndex", static: false, private: false, access: { has: obj => "createIndex" in obj, get: obj => obj.createIndex }, metadata: _metadata }, null, _instanceExtraInitializers);
1723
- __esDecorate(_a, null, _deleteOne_decorators, { kind: "method", name: "deleteOne", static: false, private: false, access: { has: obj => "deleteOne" in obj, get: obj => obj.deleteOne }, metadata: _metadata }, null, _instanceExtraInitializers);
1724
- __esDecorate(_a, null, _deleteMany_decorators, { kind: "method", name: "deleteMany", static: false, private: false, access: { has: obj => "deleteMany" in obj, get: obj => obj.deleteMany }, metadata: _metadata }, null, _instanceExtraInitializers);
1725
- __esDecorate(_a, null, _dropCollection_decorators, { kind: "method", name: "dropCollection", static: false, private: false, access: { has: obj => "dropCollection" in obj, get: obj => obj.dropCollection }, metadata: _metadata }, null, _instanceExtraInitializers);
1726
- __esDecorate(_a, null, _renameCollection_decorators, { kind: "method", name: "renameCollection", static: false, private: false, access: { has: obj => "renameCollection" in obj, get: obj => obj.renameCollection }, metadata: _metadata }, null, _instanceExtraInitializers);
1727
- __esDecorate(_a, null, _dropDatabase_decorators, { kind: "method", name: "dropDatabase", static: false, private: false, access: { has: obj => "dropDatabase" in obj, get: obj => obj.dropDatabase }, metadata: _metadata }, null, _instanceExtraInitializers);
1728
- __esDecorate(_a, null, _dropIndex_decorators, { kind: "method", name: "dropIndex", static: false, private: false, access: { has: obj => "dropIndex" in obj, get: obj => obj.dropIndex }, metadata: _metadata }, null, _instanceExtraInitializers);
1729
- __esDecorate(_a, null, _isListSearchIndexesSupported_decorators, { kind: "method", name: "isListSearchIndexesSupported", static: false, private: false, access: { has: obj => "isListSearchIndexesSupported" in obj, get: obj => obj.isListSearchIndexesSupported }, metadata: _metadata }, null, _instanceExtraInitializers);
1730
- __esDecorate(_a, null, _getSearchIndexes_decorators, { kind: "method", name: "getSearchIndexes", static: false, private: false, access: { has: obj => "getSearchIndexes" in obj, get: obj => obj.getSearchIndexes }, metadata: _metadata }, null, _instanceExtraInitializers);
1731
- __esDecorate(_a, null, _createSearchIndex_decorators, { kind: "method", name: "createSearchIndex", static: false, private: false, access: { has: obj => "createSearchIndex" in obj, get: obj => obj.createSearchIndex }, metadata: _metadata }, null, _instanceExtraInitializers);
1732
- __esDecorate(_a, null, _updateSearchIndex_decorators, { kind: "method", name: "updateSearchIndex", static: false, private: false, access: { has: obj => "updateSearchIndex" in obj, get: obj => obj.updateSearchIndex }, metadata: _metadata }, null, _instanceExtraInitializers);
1733
- __esDecorate(_a, null, _dropSearchIndex_decorators, { kind: "method", name: "dropSearchIndex", static: false, private: false, access: { has: obj => "dropSearchIndex" in obj, get: obj => obj.dropSearchIndex }, metadata: _metadata }, null, _instanceExtraInitializers);
1734
- __esDecorate(_a, null, _aggregateCursor_decorators, { kind: "method", name: "aggregateCursor", static: false, private: false, access: { has: obj => "aggregateCursor" in obj, get: obj => obj.aggregateCursor }, metadata: _metadata }, null, _instanceExtraInitializers);
1735
- __esDecorate(_a, null, _aggregate_decorators, { kind: "method", name: "aggregate", static: false, private: false, access: { has: obj => "aggregate" in obj, get: obj => obj.aggregate }, metadata: _metadata }, null, _instanceExtraInitializers);
1736
- __esDecorate(_a, null, _find_decorators, { kind: "method", name: "find", static: false, private: false, access: { has: obj => "find" in obj, get: obj => obj.find }, metadata: _metadata }, null, _instanceExtraInitializers);
1737
- __esDecorate(_a, null, _findCursor_decorators, { kind: "method", name: "findCursor", static: false, private: false, access: { has: obj => "findCursor" in obj, get: obj => obj.findCursor }, metadata: _metadata }, null, _instanceExtraInitializers);
1738
- __esDecorate(_a, null, _findOneAndReplace_decorators, { kind: "method", name: "findOneAndReplace", static: false, private: false, access: { has: obj => "findOneAndReplace" in obj, get: obj => obj.findOneAndReplace }, metadata: _metadata }, null, _instanceExtraInitializers);
1739
- __esDecorate(_a, null, _findOneAndUpdate_decorators, { kind: "method", name: "findOneAndUpdate", static: false, private: false, access: { has: obj => "findOneAndUpdate" in obj, get: obj => obj.findOneAndUpdate }, metadata: _metadata }, null, _instanceExtraInitializers);
1740
- __esDecorate(_a, null, _updateOne_decorators, { kind: "method", name: "updateOne", static: false, private: false, access: { has: obj => "updateOne" in obj, get: obj => obj.updateOne }, metadata: _metadata }, null, _instanceExtraInitializers);
1741
- __esDecorate(_a, null, _replaceOne_decorators, { kind: "method", name: "replaceOne", static: false, private: false, access: { has: obj => "replaceOne" in obj, get: obj => obj.replaceOne }, metadata: _metadata }, null, _instanceExtraInitializers);
1742
- __esDecorate(_a, null, _explainFind_decorators, { kind: "method", name: "explainFind", static: false, private: false, access: { has: obj => "explainFind" in obj, get: obj => obj.explainFind }, metadata: _metadata }, null, _instanceExtraInitializers);
1743
- __esDecorate(_a, null, _explainAggregate_decorators, { kind: "method", name: "explainAggregate", static: false, private: false, access: { has: obj => "explainAggregate" in obj, get: obj => obj.explainAggregate }, metadata: _metadata }, null, _instanceExtraInitializers);
1744
- __esDecorate(_a, null, _fetchShardKey_decorators, { kind: "method", name: "fetchShardKey", static: false, private: false, access: { has: obj => "fetchShardKey" in obj, get: obj => obj.fetchShardKey }, metadata: _metadata }, null, _instanceExtraInitializers);
1745
- __esDecorate(_a, null, _indexes_decorators, { kind: "method", name: "indexes", static: false, private: false, access: { has: obj => "indexes" in obj, get: obj => obj.indexes }, metadata: _metadata }, null, _instanceExtraInitializers);
1746
- __esDecorate(_a, null, _instance_decorators, { kind: "method", name: "instance", static: false, private: false, access: { has: obj => "instance" in obj, get: obj => obj.instance }, metadata: _metadata }, null, _instanceExtraInitializers);
1747
- __esDecorate(_a, null, _insertOne_decorators, { kind: "method", name: "insertOne", static: false, private: false, access: { has: obj => "insertOne" in obj, get: obj => obj.insertOne }, metadata: _metadata }, null, _instanceExtraInitializers);
1748
- __esDecorate(_a, null, _insertMany_decorators, { kind: "method", name: "insertMany", static: false, private: false, access: { has: obj => "insertMany" in obj, get: obj => obj.insertMany }, metadata: _metadata }, null, _instanceExtraInitializers);
1749
- __esDecorate(_a, null, _updateCollection_decorators, { kind: "method", name: "updateCollection", static: false, private: false, access: { has: obj => "updateCollection" in obj, get: obj => obj.updateCollection }, metadata: _metadata }, null, _instanceExtraInitializers);
1750
- __esDecorate(_a, null, _currentOp_decorators, { kind: "method", name: "currentOp", static: false, private: false, access: { has: obj => "currentOp" in obj, get: obj => obj.currentOp }, metadata: _metadata }, null, _instanceExtraInitializers);
1751
- __esDecorate(_a, null, _serverStatus_decorators, { kind: "method", name: "serverStatus", static: false, private: false, access: { has: obj => "serverStatus" in obj, get: obj => obj.serverStatus }, metadata: _metadata }, null, _instanceExtraInitializers);
1752
- __esDecorate(_a, null, _top_decorators, { kind: "method", name: "top", static: false, private: false, access: { has: obj => "top" in obj, get: obj => obj.top }, metadata: _metadata }, null, _instanceExtraInitializers);
1753
- __esDecorate(_a, null, _createView_decorators, { kind: "method", name: "createView", static: false, private: false, access: { has: obj => "createView" in obj, get: obj => obj.createView }, metadata: _metadata }, null, _instanceExtraInitializers);
1754
- __esDecorate(_a, null, _databaseStats_decorators, { kind: "method", name: "databaseStats", static: false, private: false, access: { has: obj => "databaseStats" in obj, get: obj => obj.databaseStats }, metadata: _metadata }, null, _instanceExtraInitializers);
1755
- __esDecorate(_a, null, _previewUpdate_decorators, { kind: "method", name: "previewUpdate", static: false, private: false, access: { has: obj => "previewUpdate" in obj, get: obj => obj.previewUpdate }, metadata: _metadata }, null, _instanceExtraInitializers);
1756
- __esDecorate(_a, null, _createDataKey_decorators, { kind: "method", name: "createDataKey", static: false, private: false, access: { has: obj => "createDataKey" in obj, get: obj => obj.createDataKey }, metadata: _metadata }, null, _instanceExtraInitializers);
1757
- __esDecorate(_a, null, _listStreamProcessors_decorators, { kind: "method", name: "listStreamProcessors", static: false, private: false, access: { has: obj => "listStreamProcessors" in obj, get: obj => obj.listStreamProcessors }, metadata: _metadata }, null, _instanceExtraInitializers);
1758
- __esDecorate(_a, null, _startStreamProcessor_decorators, { kind: "method", name: "startStreamProcessor", static: false, private: false, access: { has: obj => "startStreamProcessor" in obj, get: obj => obj.startStreamProcessor }, metadata: _metadata }, null, _instanceExtraInitializers);
1759
- __esDecorate(_a, null, _stopStreamProcessor_decorators, { kind: "method", name: "stopStreamProcessor", static: false, private: false, access: { has: obj => "stopStreamProcessor" in obj, get: obj => obj.stopStreamProcessor }, metadata: _metadata }, null, _instanceExtraInitializers);
1760
- __esDecorate(_a, null, _dropStreamProcessor_decorators, { kind: "method", name: "dropStreamProcessor", static: false, private: false, access: { has: obj => "dropStreamProcessor" in obj, get: obj => obj.dropStreamProcessor }, metadata: _metadata }, null, _instanceExtraInitializers);
1761
- if (_metadata) Object.defineProperty(_a, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
1762
- })(),
1763
- (() => {
1764
- const assertNoExtraProps = (
1765
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1766
- _cls) => {
1751
+ : undefined,
1752
+ });
1753
+ }
1754
+ async getUpdatedSecrets() {
1755
+ if (!this._state)
1756
+ return {};
1757
+ return {
1758
+ oidc: {
1759
+ serializedState: await this._state.oidcPlugin.serialize(),
1760
+ },
1761
+ };
1762
+ }
1763
+ async listStreamProcessors(filter) {
1764
+ const adminDb = this._database('admin', 'CRUD');
1765
+ const { streamProcessors } = await (0, run_command_1.runCommand)(adminDb, {
1766
+ listStreamProcessors: 1,
1767
+ filter,
1768
+ });
1769
+ return streamProcessors;
1770
+ }
1771
+ async startStreamProcessor(name) {
1772
+ const adminDb = this._database('admin', 'CRUD');
1773
+ await (0, run_command_1.runCommand)(adminDb, { startStreamProcessor: name });
1774
+ }
1775
+ async stopStreamProcessor(name) {
1776
+ const adminDb = this._database('admin', 'CRUD');
1777
+ await (0, run_command_1.runCommand)(adminDb, { stopStreamProcessor: name });
1778
+ }
1779
+ async dropStreamProcessor(name) {
1780
+ const adminDb = this._database('admin', 'CRUD');
1781
+ await (0, run_command_1.runCommand)(adminDb, { dropStreamProcessor: name });
1782
+ }
1783
+ static {
1784
+ const assertNoExtraProps = (_cls) => {
1767
1785
  // Checking that we are not exposing anything unexpected on our data service
1768
1786
  // implementation. This file will not compile if there are more public methods
1769
1787
  // on the DataServiceImpl than DataService interface allows
1770
1788
  };
1771
- assertNoExtraProps(_a);
1772
- })(),
1773
- _a;
1789
+ assertNoExtraProps(this);
1790
+ }
1791
+ };
1774
1792
  })();
1775
1793
  exports.DataServiceImpl = DataServiceImpl;
1776
1794
  function isTransactionAbortError(err) {