Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(NODE-4425): webpack optional import of FLE issue #3324

Merged
merged 4 commits into from
Jul 19, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions src/encrypter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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>): AutoEncrypter };

/** @internal */
const kInternalClient = Symbol('internalClient');
Expand Down Expand Up @@ -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;
}
}
35 changes: 25 additions & 10 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { LEGACY_HELLO_COMMAND } from './constants';
import type { AbstractCursor } from './cursor/abstract_cursor';
import type { FindCursor } from './cursor/find_cursor';
import type { Db } from './db';
import type { AutoEncrypter } from './deps';
import {
AnyError,
MongoCompatibilityError,
Expand Down Expand Up @@ -1409,24 +1410,38 @@ 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: typeof import('../src/index')) => {
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.
if (
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;
Expand Down
5 changes: 5 additions & 0 deletions test/tools/unified-spec-runner/unified-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'));
Expand Down