All files / src/operations drop.ts

97.29% Statements 36/37
94.11% Branches 16/17
100% Functions 7/7
97.29% Lines 36/37

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117    396x       396x 396x                 396x           564805x 564805x 564805x 564805x       540164x               539706x 539706x 539706x   539706x   539706x   539706x         128x     128x     539706x 11748x 11748x   11748x   23496x 23496x 23496x   12x                   539706x               563202x 553349x               396x       121375x 121375x     121087x               120629x 120171x       396x 396x  
import type { Document } from '../bson';
import type { Db } from '../db';
import { MONGODB_ERROR_CODES, MongoServerError } from '../error';
import type { Server } from '../sdam/server';
import type { ClientSession } from '../sessions';
import { type TimeoutContext } from '../timeout';
import { CommandOperation, type CommandOperationOptions } from './command';
import { Aspect, defineAspects } from './operation';
 
/** @public */
export interface DropCollectionOptions extends CommandOperationOptions {
  /** @experimental */
  encryptedFields?: Document;
}
 
/** @internal */
export class DropCollectionOperation extends CommandOperation<boolean> {
  override options: DropCollectionOptions;
  db: Db;
  name: string;
 
  constructor(db: Db, name: string, options: DropCollectionOptions = {}) {
    super(db, options);
    this.db = db;
    this.options = options;
    this.name = name;
  }
 
  override get commandName() {
    return 'drop' as const;
  }
 
  override async execute(
    server: Server,
    session: ClientSession | undefined,
    timeoutContext: TimeoutContext
  ): Promise<boolean> {
    const db = this.db;
    const options = this.options;
    const name = this.name;
 
    const encryptedFieldsMap = db.client.s.options.autoEncryption?.encryptedFieldsMap;
    let encryptedFields: Document | undefined =
      options.encryptedFields ?? encryptedFieldsMap?.[`${db.databaseName}.${name}`];
 
    if (!encryptedFields && encryptedFieldsMap) {
      // If the MongoClient was configured with an encryptedFieldsMap,
      // and no encryptedFields config was available in it or explicitly
      // passed as an argument, the spec tells us to look one up using
      // listCollections().
      const listCollectionsResult = await db
        .listCollections({ name }, { nameOnly: false })
        .toArray();
      encryptedFields = listCollectionsResult?.[0]?.options?.encryptedFields;
    }
 
    if (encryptedFields) {
      const escCollection = encryptedFields.escCollection || `enxcol_.${name}.esc`;
      const ecocCollection = encryptedFields.ecocCollection || `enxcol_.${name}.ecoc`;
 
      for (const collectionName of [escCollection, ecocCollection]) {
        // Drop auxilliary collections, ignoring potential NamespaceNotFound errors.
        const dropOp = new DropCollectionOperation(db, collectionName);
        try {
          await dropOp.executeWithoutEncryptedFieldsCheck(server, session, timeoutContext);
        } catch (err) {
          Iif (
            !(err instanceof MongoServerError) ||
            err.code !== MONGODB_ERROR_CODES.NamespaceNotFound
          ) {
            throw err;
          }
        }
      }
    }
 
    return await this.executeWithoutEncryptedFieldsCheck(server, session, timeoutContext);
  }
 
  private async executeWithoutEncryptedFieldsCheck(
    server: Server,
    session: ClientSession | undefined,
    timeoutContext: TimeoutContext
  ): Promise<boolean> {
    await super.executeCommand(server, session, { drop: this.name }, timeoutContext);
    return true;
  }
}
 
/** @public */
export type DropDatabaseOptions = CommandOperationOptions;
 
/** @internal */
export class DropDatabaseOperation extends CommandOperation<boolean> {
  override options: DropDatabaseOptions;
 
  constructor(db: Db, options: DropDatabaseOptions) {
    super(db, options);
    this.options = options;
  }
  override get commandName() {
    return 'dropDatabase' as const;
  }
 
  override async execute(
    server: Server,
    session: ClientSession | undefined,
    timeoutContext: TimeoutContext
  ): Promise<boolean> {
    await super.executeCommand(server, session, { dropDatabase: 1 }, timeoutContext);
    return true;
  }
}
 
defineAspects(DropCollectionOperation, [Aspect.WRITE_OPERATION]);
defineAspects(DropDatabaseOperation, [Aspect.WRITE_OPERATION]);