diff --git a/lib/core/topologies/shared.js b/lib/core/topologies/shared.js index 0f62b5beb9..ab01b02105 100644 --- a/lib/core/topologies/shared.js +++ b/lib/core/topologies/shared.js @@ -56,6 +56,21 @@ function createClientInfo(options) { clientInfo.application = { name: appname }; } + // support optionally provided wrapping driver info + if (options.driverInfo) { + if (options.driverInfo.name) { + clientInfo.driver.name = `${clientInfo.driver.name}|${options.driverInfo.name}`; + } + + if (options.driverInfo.version) { + clientInfo.driver.version = `${clientInfo.driver.version}|${options.driverInfo.version}`; + } + + if (options.driverInfo.platform) { + clientInfo.platform = `${clientInfo.platform}|${options.driverInfo.platform}`; + } + } + return clientInfo; } diff --git a/lib/mongo_client.js b/lib/mongo_client.js index 703eda64a0..4e0250aa75 100644 --- a/lib/mongo_client.js +++ b/lib/mongo_client.js @@ -77,6 +77,15 @@ const CloseOperation = require('./operations/close'); * @property {string[]} [extraOptions.mongocryptdSpawnArgs] Command line arguments to use when auto-spawning a mongocryptd */ +/** + * Configuration options for drivers wrapping the node driver. + * + * @typedef {Object} DriverInfoOptions + * @property {string} [name] The name of the driver + * @property {string} [version] The version of the driver + * @property {string} [platform] Optional platform information + */ + /** * Creates a new MongoClient instance * @class @@ -143,6 +152,7 @@ const CloseOperation = require('./operations/close'); * @param {boolean} [options.useNewUrlParser=true] Determines whether or not to use the new url parser. Enables the new, spec-compliant, url parser shipped in the core driver. This url parser fixes a number of problems with the original parser, and aims to outright replace that parser in the near future. Defaults to true, and must be explicitly set to false to use the legacy url parser. * @param {boolean} [options.useUnifiedTopology] Enables the new unified topology layer * @param {AutoEncryptionOptions} [options.autoEncryption] Optionally enable client side auto encryption + * @param {DriverInfoOptions} [options.driverInfo] Allows a wrapping driver to amend the client metadata generated by the driver to include information about the wrapping driver * @param {MongoClient~connectCallback} [callback] The command result callback * @return {MongoClient} a MongoClient instance */ diff --git a/lib/operations/connect.js b/lib/operations/connect.js index e8f251875d..56695bc316 100644 --- a/lib/operations/connect.js +++ b/lib/operations/connect.js @@ -137,7 +137,8 @@ const validOptionNames = [ 'useUnifiedTopology', 'serverSelectionTimeoutMS', 'useRecoveryToken', - 'autoEncryption' + 'autoEncryption', + 'driverInfo' ]; const ignoreOptionNames = ['native_parser']; diff --git a/test/unit/client_tests.js b/test/unit/client_tests.js new file mode 100644 index 0000000000..672fe193c8 --- /dev/null +++ b/test/unit/client_tests.js @@ -0,0 +1,50 @@ +'use strict'; + +const expect = require('chai').expect; +const mock = require('mongodb-mock-server'); + +describe('Client (unit)', function() { + let server; + + afterEach(() => mock.cleanup()); + beforeEach(() => { + return mock.createServer().then(_server => (server = _server)); + }); + + it('should let wrapping libraries amend the client metadata', function() { + let handshake; + server.setMessageHandler(request => { + const doc = request.document; + if (doc.ismaster) { + handshake = doc; + request.reply(Object.assign({}, mock.DEFAULT_ISMASTER)); + } else if (doc.endSessions) { + request.reply({ ok: 1 }); + } + }); + + const client = this.configuration.newClient(`mongodb://${server.uri()}/`, { + useUnifiedTopology: true, + driverInfo: { + name: 'mongoose', + version: '5.7.10', + platform: 'llama edition' + } + }); + + return client.connect().then(() => { + this.defer(() => client.close()); + + expect(handshake) + .nested.property('client.driver') + .to.deep.equal({ + name: 'nodejs|mongoose', + version: '3.3.4|5.7.10' + }); + + expect(handshake) + .nested.property('client.platform') + .to.match(/llama edition/); + }); + }); +});