From 5ab2b0517216b6675bed38824448fd9d598fd096 Mon Sep 17 00:00:00 2001 From: Neal Beeken Date: Tue, 19 Jul 2022 17:22:05 -0400 Subject: [PATCH] fix(NODE-4425): webpack optional import of FLE issue (#3324) --- src/encrypter.ts | 10 +++--- src/utils.ts | 34 +++++++++++++------ .../unified-spec-runner/unified-utils.ts | 5 +++ 3 files changed, 33 insertions(+), 16 deletions(-) diff --git a/src/encrypter.ts b/src/encrypter.ts index 316c44f9e3..c67643c043 100644 --- a/src/encrypter.ts +++ b/src/encrypter.ts @@ -6,7 +6,7 @@ import { MongoInvalidArgumentError, MongoMissingDependencyError } from './error' import { MongoClient, MongoClientOptions } from './mongo_client'; import { Callback, getMongoDBClientEncryption } from './utils'; -let AutoEncrypterClass: AutoEncrypter; +let AutoEncrypterClass: { new (...args: ConstructorParameters): AutoEncrypter }; /** @internal */ const kInternalClient = Symbol('internalClient'); @@ -123,15 +123,13 @@ export class Encrypter { } static checkForMongoCrypt(): void { - try { - // NOTE(NODE-3199): Ensure you always wrap an optional require in the try block - const mongodbClientEncryption = getMongoDBClientEncryption(); - AutoEncrypterClass = mongodbClientEncryption.extension(require('../lib/index')).AutoEncrypter; - } catch { + const mongodbClientEncryption = getMongoDBClientEncryption(); + if (mongodbClientEncryption == null) { throw new MongoMissingDependencyError( 'Auto-encryption requested, but the module is not installed. ' + 'Please add `mongodb-client-encryption` as a dependency of your project' ); } + AutoEncrypterClass = mongodbClientEncryption.extension(require('../lib/index')).AutoEncrypter; } } diff --git a/src/utils.ts b/src/utils.ts index f7f0ebd545..abbdf02d1d 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1409,14 +1409,14 @@ export function commandSupportsReadConcern(command: Document, options?: Document return false; } -/** - * A utility function to get the instance of mongodb-client-encryption, if it exists. - * - * @throws MongoMissingDependencyError if mongodb-client-encryption isn't installed. - * @returns - */ -export function getMongoDBClientEncryption() { - let mongodbClientEncryption; +/** A utility function to get the instance of mongodb-client-encryption, if it exists. */ +export function getMongoDBClientEncryption(): { + extension: (mdb: unknown) => { + AutoEncrypter: any; + ClientEncryption: any; + }; +} | null { + let mongodbClientEncryption = null; // NOTE(NODE-4254): This is to get around the circular dependency between // mongodb-client-encryption and the driver in the test scenarios. @@ -1424,9 +1424,23 @@ export function getMongoDBClientEncryption() { typeof process.env.MONGODB_CLIENT_ENCRYPTION_OVERRIDE === 'string' && process.env.MONGODB_CLIENT_ENCRYPTION_OVERRIDE.length > 0 ) { - mongodbClientEncryption = require(process.env.MONGODB_CLIENT_ENCRYPTION_OVERRIDE); + try { + // NOTE(NODE-3199): Ensure you always wrap an optional require literally in the try block + // Cannot be moved to helper utility function, bundlers search and replace the actual require call + // in a way that makes this line throw at bundle time, not runtime, catching here will make bundling succeed + mongodbClientEncryption = require(process.env.MONGODB_CLIENT_ENCRYPTION_OVERRIDE); + } catch { + // ignore + } } else { - mongodbClientEncryption = require('mongodb-client-encryption'); + try { + // NOTE(NODE-3199): Ensure you always wrap an optional require literally in the try block + // Cannot be moved to helper utility function, bundlers search and replace the actual require call + // in a way that makes this line throw at bundle time, not runtime, catching here will make bundling succeed + mongodbClientEncryption = require('mongodb-client-encryption'); + } catch { + // ignore + } } return mongodbClientEncryption; diff --git a/test/tools/unified-spec-runner/unified-utils.ts b/test/tools/unified-spec-runner/unified-utils.ts index 1e03f2d907..1ab8ae1e27 100644 --- a/test/tools/unified-spec-runner/unified-utils.ts +++ b/test/tools/unified-spec-runner/unified-utils.ts @@ -206,6 +206,11 @@ export function makeConnectionString( export function getClientEncryptionClass(): ClientEncryption { try { const mongodbClientEncryption = getMongoDBClientEncryption(); + if (mongodbClientEncryption == null) { + throw new MongoMissingDependencyError( + 'Attempting to import mongodb-client-encryption but it is not installed.' + ); + } // eslint-disable-next-line @typescript-eslint/no-var-requires const { ClientEncryption } = mongodbClientEncryption.extension(require('../../../src/index'));