Skip to content

Commit f1b896d

Browse files
authored
fix(NODE-3585): MongoClientOptions#compressors has incorrect type (#2976)
1 parent cfdd799 commit f1b896d

File tree

4 files changed

+66
-8
lines changed

4 files changed

+66
-8
lines changed

src/connection_string.ts

+9-3
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import type { TagSet } from './sdam/server_description';
3232
import { Logger, LoggerLevel } from './logger';
3333
import { PromiseProvider } from './promise_provider';
3434
import { Encrypter } from './encrypter';
35-
import { Compressor } from './cmap/wire_protocol/compression';
35+
import { Compressor, CompressorName } from './cmap/wire_protocol/compression';
3636

3737
const VALID_TXT_RECORDS = ['authSource', 'replicaSet', 'loadBalanced'];
3838

@@ -612,8 +612,14 @@ export const OPTIONS = {
612612
target: 'compressors',
613613
transform({ values }) {
614614
const compressionList = new Set();
615-
for (const compVal of values as string[]) {
616-
for (const c of compVal.split(',')) {
615+
for (const compVal of values as (CompressorName[] | string)[]) {
616+
const compValArray = typeof compVal === 'string' ? compVal.split(',') : compVal;
617+
if (!Array.isArray(compValArray)) {
618+
throw new MongoInvalidArgumentError(
619+
'compressors must be an array or a comma-delimited list of strings'
620+
);
621+
}
622+
for (const c of compValArray) {
617623
if (Object.keys(Compressor).includes(String(c))) {
618624
compressionList.add(String(c));
619625
} else {

src/mongo_client.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,8 @@ export interface MongoClientOptions extends BSONSerializeOptions, SupportedNodeC
128128
connectTimeoutMS?: number;
129129
/** The time in milliseconds to attempt a send or receive on a socket before the attempt times out. */
130130
socketTimeoutMS?: number;
131-
/** Comma-delimited string of compressors to enable network compression for communication between this client and a mongod/mongos instance. */
132-
compressors?: CompressorName[];
131+
/** An array or comma-delimited string of compressors to enable network compression for communication between this client and a mongod/mongos instance. */
132+
compressors?: CompressorName[] | string;
133133
/** An integer that specifies the compression level if using zlib for network compression. */
134134
zlibCompressionLevel?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | undefined;
135135
/** The maximum number of connections in the connection pool. */
@@ -620,7 +620,6 @@ export interface MongoOptions
620620
Pick<
621621
MongoClientOptions,
622622
| 'autoEncryption'
623-
| 'compressors'
624623
| 'connectTimeoutMS'
625624
| 'directConnection'
626625
| 'driverInfo'
@@ -659,6 +658,7 @@ export interface MongoOptions
659658
readConcern: ReadConcern;
660659
loadBalanced: boolean;
661660
serverApi: ServerApi;
661+
compressors: CompressorName[];
662662
writeConcern: WriteConcern;
663663
dbName: string;
664664
metadata: ClientMetadata;

test/types/community/changes_from_36.test-d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ expectAssignable<((host: string, cert: PeerCertificate) => Error | undefined) |
6969
// compression options have simpler specification:
7070
// old way: {compression: { compressors: ['zlib', 'snappy'] }}
7171
expectType<PropExists<MongoClientOptions, 'compression'>>(false);
72-
expectType<('none' | 'snappy' | 'zlib')[] | undefined>(options.compressors);
72+
expectType<('none' | 'snappy' | 'zlib')[] | string | undefined>(options.compressors);
7373

7474
// Removed cursor API
7575
const cursor = new MongoClient('').db().aggregate();

test/unit/mongo_client_options.test.js

+53-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ describe('MongoOptions', function () {
7878
autoEncryption: { bypassAutoEncryption: true },
7979
checkKeys: true,
8080
checkServerIdentity: false,
81-
compressors: 'snappy', // TODO
81+
compressors: 'snappy,zlib',
8282
connectTimeoutMS: 123,
8383
directConnection: true,
8484
dbName: 'test',
@@ -385,6 +385,58 @@ describe('MongoOptions', function () {
385385
expect(optionsUndefined.checkServerIdentity).to.equal(undefined);
386386
});
387387

388+
describe('compressors', function () {
389+
it('can be set when passed in as an array in the options object', function () {
390+
const clientViaOpt = new MongoClient('mongodb://localhost', {
391+
compressors: ['zlib', 'snappy']
392+
});
393+
expect(clientViaOpt.options)
394+
.to.have.property('compressors')
395+
.deep.equal(['zlib', 'snappy', 'none']);
396+
});
397+
398+
it('can be set when passed in as a comma-delimited string in the options object or URI', function () {
399+
const clientViaOpt = new MongoClient('mongodb://localhost', {
400+
compressors: 'zlib,snappy'
401+
});
402+
const clientViaUri = new MongoClient('mongodb://localhost?compressors=zlib,snappy');
403+
expect(clientViaOpt.options)
404+
.to.have.property('compressors')
405+
.deep.equal(['zlib', 'snappy', 'none']);
406+
expect(clientViaUri.options)
407+
.to.have.property('compressors')
408+
.deep.equal(['zlib', 'snappy', 'none']);
409+
});
410+
411+
it('should validate that a string or an array of strings is provided as input', function () {
412+
expect(
413+
() =>
414+
new MongoClient('mongodb://localhost', {
415+
compressors: { zlib: true }
416+
})
417+
).to.throw(/^compressors must be an array or a comma-delimited list of strings/);
418+
});
419+
420+
it('should throw an error if an unrecognized compressor is specified', function () {
421+
const expectedErrRegex = /not a valid compression mechanism/;
422+
expect(
423+
() =>
424+
new MongoClient('mongodb://localhost', {
425+
compressors: ['invalid']
426+
})
427+
).to.throw(expectedErrRegex);
428+
expect(
429+
() =>
430+
new MongoClient('mongodb://localhost', {
431+
compressors: 'invalid'
432+
})
433+
).to.throw(expectedErrRegex);
434+
expect(() => new MongoClient('mongodb://localhost?compressors=invalid')).to.throw(
435+
expectedErrRegex
436+
);
437+
});
438+
});
439+
388440
describe('serverApi', function () {
389441
it('is supported as a client option when it is a valid ServerApiVersion string', function () {
390442
const validVersions = Object.values(ServerApiVersion);

0 commit comments

Comments
 (0)