From a2292d002bcd55294f46372e68f6b3aef388cbb0 Mon Sep 17 00:00:00 2001 From: Raschid Jimenez Date: Mon, 29 Dec 2025 18:02:46 -0500 Subject: [PATCH 1/3] feat: append metadata to MongoClient --- spec/GridFSBucketStorageAdapter.spec.js | 13 +++++++++++++ spec/MongoStorageAdapter.spec.js | 12 ++++++++++++ src/Adapters/Files/GridFSBucketAdapter.js | 5 +++++ src/Adapters/Storage/Mongo/MongoStorageAdapter.js | 5 +++++ 4 files changed, 35 insertions(+) diff --git a/spec/GridFSBucketStorageAdapter.spec.js b/spec/GridFSBucketStorageAdapter.spec.js index 8e1e4f2900..93820f0067 100644 --- a/spec/GridFSBucketStorageAdapter.spec.js +++ b/spec/GridFSBucketStorageAdapter.spec.js @@ -1,6 +1,7 @@ const GridFSBucketAdapter = require('../lib/Adapters/Files/GridFSBucketAdapter') .GridFSBucketAdapter; const { randomString } = require('../lib/cryptoUtils'); +const { MongoClient } = require('mongodb'); const databaseURI = 'mongodb://localhost:27017/parse'; const request = require('../lib/request'); @@ -475,4 +476,16 @@ describe_only_db('mongo')('GridFSBucket', () => { expect(e.message).toEqual('Client must be connected before running operations'); } }); + + it('pass metadata to MongoClient', async () => { + const pkg = require('../package.json'); + spyOn(MongoClient.prototype, 'appendMetadata').and.callThrough(); + + const gfsAdapter = new GridFSBucketAdapter(databaseURI); + await gfsAdapter._connect(); + expect(MongoClient.prototype.appendMetadata).toHaveBeenCalledWith({ + name: 'Parse Server', + version: pkg.version, + }); + }); }); diff --git a/spec/MongoStorageAdapter.spec.js b/spec/MongoStorageAdapter.spec.js index 8b14973243..361958592f 100644 --- a/spec/MongoStorageAdapter.spec.js +++ b/spec/MongoStorageAdapter.spec.js @@ -449,6 +449,18 @@ describe_only_db('mongo')('MongoStorageAdapter', () => { expect(schemaAfterDeletion.fields.test).toBeUndefined(); }); + it('pass metadata to MongoClient', async () => { + const pkg = require('../package.json'); + spyOn(MongoClient.prototype, 'appendMetadata').and.callThrough(); + + const adapter = new MongoStorageAdapter({ uri: databaseURI }); + await adapter.connect(); + expect(adapter.client.appendMetadata).toHaveBeenCalledWith({ + name: 'Parse Server', + version: pkg.version, + }); + }); + if (process.env.MONGODB_TOPOLOGY === 'replicaset') { describe('transactions', () => { const headers = { diff --git a/src/Adapters/Files/GridFSBucketAdapter.js b/src/Adapters/Files/GridFSBucketAdapter.js index 6820fc887f..2e505487e6 100644 --- a/src/Adapters/Files/GridFSBucketAdapter.js +++ b/src/Adapters/Files/GridFSBucketAdapter.js @@ -10,6 +10,7 @@ import { MongoClient, GridFSBucket, Db } from 'mongodb'; import { FilesAdapter, validateFilename } from './FilesAdapter'; import defaults, { ParseServerDatabaseOptions } from '../../defaults'; +import pkg from '../../../package.json'; const crypto = require('crypto'); export class GridFSBucketAdapter extends FilesAdapter { @@ -47,6 +48,10 @@ export class GridFSBucketAdapter extends FilesAdapter { if (!this._connectionPromise) { this._connectionPromise = MongoClient.connect(this._databaseURI, this._mongoOptions).then( client => { + client.appendMetadata?.({ + name: 'Parse Server', + version: pkg.version, + }); this._client = client; return client.db(client.s.options.dbName); } diff --git a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js index 24b206aec9..03a00b7926 100644 --- a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js +++ b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -19,6 +19,7 @@ import _ from 'lodash'; import defaults, { ParseServerDatabaseOptions } from '../../../defaults'; import logger from '../../../logger'; import Utils from '../../../Utils'; +import pkg from '../../../../package.json'; // @flow-disable-next const mongodb = require('mongodb'); @@ -184,6 +185,10 @@ export class MongoStorageAdapter implements StorageAdapter { // Starting mongoDB 3.0, the MongoClient.connect don't return a DB anymore but a client // Fortunately, we can get back the options and use them to select the proper DB. // https://github.com/mongodb/node-mongodb-native/blob/2c35d76f08574225b8db02d7bef687123e6bb018/lib/mongo_client.js#L885 + client.appendMetadata?.({ + name: 'Parse Server', + version: pkg.version, + }); const options = client.s.options; const database = client.db(options.dbName); if (!database) { From faf0116453d658ff4e7d8d65e6669de27398af16 Mon Sep 17 00:00:00 2001 From: Raschid JF Rafaelly Date: Mon, 29 Dec 2025 22:10:00 -0500 Subject: [PATCH 2/3] fix(Adapters): ensure mongodb metadata is passed from the first handshake --- spec/GridFSBucketStorageAdapter.spec.js | 5 +---- spec/MongoStorageAdapter.spec.js | 4 +--- src/Adapters/Files/GridFSBucketAdapter.js | 13 ++++++++----- src/Adapters/Storage/Mongo/MongoStorageAdapter.js | 13 ++++++++----- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/spec/GridFSBucketStorageAdapter.spec.js b/spec/GridFSBucketStorageAdapter.spec.js index 93820f0067..3ef62afd87 100644 --- a/spec/GridFSBucketStorageAdapter.spec.js +++ b/spec/GridFSBucketStorageAdapter.spec.js @@ -1,7 +1,6 @@ const GridFSBucketAdapter = require('../lib/Adapters/Files/GridFSBucketAdapter') .GridFSBucketAdapter; const { randomString } = require('../lib/cryptoUtils'); -const { MongoClient } = require('mongodb'); const databaseURI = 'mongodb://localhost:27017/parse'; const request = require('../lib/request'); @@ -479,11 +478,9 @@ describe_only_db('mongo')('GridFSBucket', () => { it('pass metadata to MongoClient', async () => { const pkg = require('../package.json'); - spyOn(MongoClient.prototype, 'appendMetadata').and.callThrough(); - const gfsAdapter = new GridFSBucketAdapter(databaseURI); await gfsAdapter._connect(); - expect(MongoClient.prototype.appendMetadata).toHaveBeenCalledWith({ + expect(gfsAdapter._client.s.options.driverInfo).toEqual({ name: 'Parse Server', version: pkg.version, }); diff --git a/spec/MongoStorageAdapter.spec.js b/spec/MongoStorageAdapter.spec.js index 361958592f..b8d71bc149 100644 --- a/spec/MongoStorageAdapter.spec.js +++ b/spec/MongoStorageAdapter.spec.js @@ -451,11 +451,9 @@ describe_only_db('mongo')('MongoStorageAdapter', () => { it('pass metadata to MongoClient', async () => { const pkg = require('../package.json'); - spyOn(MongoClient.prototype, 'appendMetadata').and.callThrough(); - const adapter = new MongoStorageAdapter({ uri: databaseURI }); await adapter.connect(); - expect(adapter.client.appendMetadata).toHaveBeenCalledWith({ + expect(adapter.client.s.options.driverInfo).toEqual({ name: 'Parse Server', version: pkg.version, }); diff --git a/src/Adapters/Files/GridFSBucketAdapter.js b/src/Adapters/Files/GridFSBucketAdapter.js index 2e505487e6..ded93681cb 100644 --- a/src/Adapters/Files/GridFSBucketAdapter.js +++ b/src/Adapters/Files/GridFSBucketAdapter.js @@ -46,12 +46,15 @@ export class GridFSBucketAdapter extends FilesAdapter { _connect() { if (!this._connectionPromise) { - this._connectionPromise = MongoClient.connect(this._databaseURI, this._mongoOptions).then( + // Add wrapping library metadata. + const driverInfo = { + name: 'Parse Server', + version: pkg.version, + }; + const mongoclient = new MongoClient(this._databaseURI, this._mongoOptions); + mongoclient.appendMetadata(driverInfo); + this._connectionPromise = mongoclient.connect().then( client => { - client.appendMetadata?.({ - name: 'Parse Server', - version: pkg.version, - }); this._client = client; return client.db(client.s.options.dbName); } diff --git a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js index 03a00b7926..a164f52d91 100644 --- a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js +++ b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -180,15 +180,18 @@ export class MongoStorageAdapter implements StorageAdapter { // parsing and re-formatting causes the auth value (if there) to get URI // encoded const encodedUri = formatUrl(parseUrl(this._uri)); - this.connectionPromise = MongoClient.connect(encodedUri, this._mongoOptions) + // Add wrapping library metadata. + const driverInfo = { + name: 'Parse Server', + version: pkg.version, + } + const mongoclient = new MongoClient(encodedUri, this._mongoOptions) + mongoclient.appendMetadata(driverInfo); + this.connectionPromise = mongoclient.connect() .then(client => { // Starting mongoDB 3.0, the MongoClient.connect don't return a DB anymore but a client // Fortunately, we can get back the options and use them to select the proper DB. // https://github.com/mongodb/node-mongodb-native/blob/2c35d76f08574225b8db02d7bef687123e6bb018/lib/mongo_client.js#L885 - client.appendMetadata?.({ - name: 'Parse Server', - version: pkg.version, - }); const options = client.s.options; const database = client.db(options.dbName); if (!database) { From f4a93ae1d3f35c7c4867e89006b86d43651ebfa8 Mon Sep 17 00:00:00 2001 From: Raschid JF Rafaelly Date: Tue, 30 Dec 2025 01:54:46 -0500 Subject: [PATCH 3/3] test: fix failing tests --- src/Adapters/Files/GridFSBucketAdapter.js | 4 +--- src/Adapters/Storage/Mongo/MongoStorageAdapter.js | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Adapters/Files/GridFSBucketAdapter.js b/src/Adapters/Files/GridFSBucketAdapter.js index ded93681cb..7069e2968d 100644 --- a/src/Adapters/Files/GridFSBucketAdapter.js +++ b/src/Adapters/Files/GridFSBucketAdapter.js @@ -51,9 +51,7 @@ export class GridFSBucketAdapter extends FilesAdapter { name: 'Parse Server', version: pkg.version, }; - const mongoclient = new MongoClient(this._databaseURI, this._mongoOptions); - mongoclient.appendMetadata(driverInfo); - this._connectionPromise = mongoclient.connect().then( + this._connectionPromise = MongoClient.connect(this._databaseURI, { ...this._mongoOptions, driverInfo }).then( client => { this._client = client; return client.db(client.s.options.dbName); diff --git a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js index a164f52d91..096d3835db 100644 --- a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js +++ b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -185,9 +185,7 @@ export class MongoStorageAdapter implements StorageAdapter { name: 'Parse Server', version: pkg.version, } - const mongoclient = new MongoClient(encodedUri, this._mongoOptions) - mongoclient.appendMetadata(driverInfo); - this.connectionPromise = mongoclient.connect() + this.connectionPromise = MongoClient.connect(encodedUri, { ...this._mongoOptions, driverInfo }) .then(client => { // Starting mongoDB 3.0, the MongoClient.connect don't return a DB anymore but a client // Fortunately, we can get back the options and use them to select the proper DB.