diff --git a/src/sdam/topology.ts b/src/sdam/topology.ts index 9f91d60f658..c4d81bd3ba8 100644 --- a/src/sdam/topology.ts +++ b/src/sdam/topology.ts @@ -52,6 +52,7 @@ import type { CloseOptions } from '../cmap/connection_pool'; import { DestroyOptions, Connection } from '../cmap/connection'; import type { MongoClientOptions } from '../mongo_client'; import { DEFAULT_OPTIONS } from '../connection_string'; +import { serialize, deserialize } from '../bson'; // Global state let globalTopologyCounter = 0; @@ -188,6 +189,15 @@ export class Topology extends EventEmitter { static readonly OPEN = 'open' as const; /** @event */ static readonly CONNECT = 'connect' as const; + /** + * @internal + * + * @privateRemarks + * mongodb-client-encryption's class ClientEncryption falls back to finding the bson lib + * defined on client.topology.bson, in order to maintain compatibility with any version + * of mongodb-client-encryption we keep a reference to serialize and deserialize here. + */ + bson: { serialize: typeof serialize; deserialize: typeof deserialize }; /** * @param seedlist - a list of HostAddress instances to connect to @@ -195,6 +205,11 @@ export class Topology extends EventEmitter { constructor(seeds: string | string[] | HostAddress | HostAddress[], options: TopologyOptions) { super(); + // Legacy CSFLE support + this.bson = Object.create(null); + this.bson.serialize = serialize; + this.bson.deserialize = deserialize; + // Options should only be undefined in tests, MongoClient will always have defined options options = options ?? { hosts: [HostAddress.fromString('localhost:27017')], diff --git a/test/unit/legacy_compat.test.js b/test/unit/legacy_compat.test.js new file mode 100644 index 00000000000..8d7a4e0f8d9 --- /dev/null +++ b/test/unit/legacy_compat.test.js @@ -0,0 +1,30 @@ +'use strict'; + +const { expect } = require('chai'); +const { MongoClient } = require('../../src'); + +describe('Legacy 3.x features', function () { + it('Should have bson defined on topology', function () { + const client = new MongoClient(this.configuration.url()); + return client + .connect() + .then(client => { + expect(client.topology).to.have.property('bson'); + expect(client.topology.bson).to.have.property('serialize'); + expect(client.topology.bson).to.have.property('deserialize'); + }) + .finally(() => client.close()); + }); + + it('Should allow legacy option useUnifiedTopology', function () { + const url = this.configuration.url(); + expect(() => new MongoClient(url, { useUnifiedTopology: true })).to.not.throw; + expect(() => new MongoClient(url, { useUnifiedTopology: false })).to.not.throw; + }); + + it('Should allow legacy option useNewUrlParser', function () { + const url = this.configuration.url(); + expect(() => new MongoClient(url, { useNewUrlParser: true })).to.not.throw; + expect(() => new MongoClient(url, { useNewUrlParser: false })).to.not.throw; + }); +});