Skip to content

Commit f420e36

Browse files
committed
refactor: Add validation for serverApi version and tests
1 parent 393ba90 commit f420e36

File tree

3 files changed

+89
-6
lines changed

3 files changed

+89
-6
lines changed

src/connection_string.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ import {
2323
MongoClientOptions,
2424
MongoOptions,
2525
PkFactory,
26-
ServerApi
26+
ServerApi,
27+
ServerApiVersion
2728
} from './mongo_client';
2829
import { MongoCredentials } from './cmap/auth/mongo_credentials';
2930
import type { TagSet } from './sdam/server_description';
@@ -590,10 +591,24 @@ export const OPTIONS = {
590591
serverApi: {
591592
target: 'serverApi',
592593
transform({ values: [version] }): ServerApi {
593-
if (typeof version === 'string') {
594-
return { version };
594+
const serverApiToValidate =
595+
typeof version === 'string' ? ({ version } as ServerApi) : (version as ServerApi);
596+
const versionToValidate = serverApiToValidate && serverApiToValidate.version;
597+
if (!versionToValidate) {
598+
throw new MongoParseError(
599+
`Invalid \`serverApi\` property; must specify a version as one of the following strings: "${Object.values(
600+
ServerApiVersion
601+
).join('", "')}"`
602+
);
603+
}
604+
if (!Object.values(ServerApiVersion).some(v => v === versionToValidate)) {
605+
throw new MongoParseError(
606+
`Invalid server API version=${versionToValidate}; must be one of the following strings: "${Object.values(
607+
ServerApiVersion
608+
).join('", "')}"`
609+
);
595610
}
596-
return version as ServerApi;
611+
return serverApiToValidate;
597612
}
598613
},
599614
checkKeys: {

src/mongo_client.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export type ServerApiVersion = typeof ServerApiVersion[keyof typeof ServerApiVer
4343

4444
/** @public */
4545
export interface ServerApi {
46-
version: string | ServerApiVersion;
46+
version: ServerApiVersion;
4747
strict?: boolean;
4848
deprecationErrors?: boolean;
4949
}

test/unit/mongo_client_options.test.js

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const { WriteConcern } = require('../../src/write_concern');
88
const { ReadPreference } = require('../../src/read_preference');
99
const { Logger } = require('../../src/logger');
1010
const { MongoCredentials } = require('../../src/cmap/auth/mongo_credentials');
11-
const { MongoClient, MongoParseError } = require('../../src');
11+
const { MongoClient, MongoParseError, ServerApiVersion } = require('../../src');
1212

1313
describe('MongoOptions', function () {
1414
it('MongoClient should always freeze public options', function () {
@@ -122,6 +122,7 @@ describe('MongoOptions', function () {
122122
serializeFunctions: true,
123123
serverSelectionTimeoutMS: 3,
124124
servername: 'some tls option',
125+
serverApi: { version: '1' },
125126
socketTimeoutMS: 3,
126127
ssl: true,
127128
sslPass: 'pass',
@@ -369,4 +370,71 @@ describe('MongoOptions', function () {
369370
expect(optionsUndefined.rejectUnauthorized).to.equal(undefined);
370371
expect(optionsUndefined.checkServerIdentity).to.equal(undefined);
371372
});
373+
374+
describe('serverApi', function () {
375+
it('is supported as a client option when it is a valid ServerApiVersion string', function () {
376+
const validVersions = Object.values(ServerApiVersion);
377+
expect(validVersions.length).to.be.at.least(1);
378+
for (const version of validVersions) {
379+
const result = parseOptions('mongodb://localhost/', {
380+
serverApi: version
381+
});
382+
expect(result).to.have.property('serverApi').deep.equal({ version });
383+
}
384+
});
385+
386+
it('is supported as a client option when it is an object with a valid version property', function () {
387+
const validVersions = Object.values(ServerApiVersion);
388+
expect(validVersions.length).to.be.at.least(1);
389+
for (const version of validVersions) {
390+
const result = parseOptions('mongodb://localhost/', {
391+
serverApi: { version }
392+
});
393+
expect(result).to.have.property('serverApi').deep.equal({ version });
394+
}
395+
});
396+
397+
it('is not supported as a client option when it is an invalid string', function () {
398+
expect(() =>
399+
parseOptions('mongodb://localhost/', {
400+
serverApi: 'bad'
401+
})
402+
).to.throw(/^Invalid server API version=bad;/);
403+
});
404+
405+
it('is not supported as a client option when it is a number', function () {
406+
expect(() =>
407+
parseOptions('mongodb://localhost/', {
408+
serverApi: 1
409+
})
410+
).to.throw(/^Invalid `serverApi` property;/);
411+
});
412+
413+
it('is not supported as a client option when it is an object without a specified version', function () {
414+
expect(() =>
415+
parseOptions('mongodb://localhost/', {
416+
serverApi: {}
417+
})
418+
).to.throw(/^Invalid `serverApi` property;/);
419+
});
420+
421+
it('is not supported as a client option when it is an object with an invalid specified version', function () {
422+
expect(() =>
423+
parseOptions('mongodb://localhost/', {
424+
serverApi: { version: 1 }
425+
})
426+
).to.throw(/^Invalid server API version=1;/);
427+
expect(() =>
428+
parseOptions('mongodb://localhost/', {
429+
serverApi: { version: 'bad' }
430+
})
431+
).to.throw(/^Invalid server API version=bad;/);
432+
});
433+
434+
it('is not supported as a URI option even when it is a valid ServerApiVersion string', function () {
435+
expect(() => parseOptions('mongodb://localhost/?serverApi=1')).to.throw(
436+
'URI cannot contain `serverApi`, it can only be passed to the client'
437+
);
438+
});
439+
});
372440
});

0 commit comments

Comments
 (0)