You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							1086 lines
						
					
					
						
							41 KiB
						
					
					
				
			
		
		
	
	
							1086 lines
						
					
					
						
							41 KiB
						
					
					
				| "use strict";
 | |
| Object.defineProperty(exports, "__esModule", { value: true });
 | |
| exports.FEATURE_FLAGS = exports.DEFAULT_OPTIONS = exports.OPTIONS = exports.parseOptions = exports.resolveSRVRecord = void 0;
 | |
| const dns = require("dns");
 | |
| const fs = require("fs");
 | |
| const mongodb_connection_string_url_1 = require("mongodb-connection-string-url");
 | |
| const url_1 = require("url");
 | |
| const mongo_credentials_1 = require("./cmap/auth/mongo_credentials");
 | |
| const providers_1 = require("./cmap/auth/providers");
 | |
| const compression_1 = require("./cmap/wire_protocol/compression");
 | |
| const encrypter_1 = require("./encrypter");
 | |
| const error_1 = require("./error");
 | |
| const mongo_client_1 = require("./mongo_client");
 | |
| const mongo_logger_1 = require("./mongo_logger");
 | |
| const read_concern_1 = require("./read_concern");
 | |
| const read_preference_1 = require("./read_preference");
 | |
| const utils_1 = require("./utils");
 | |
| const write_concern_1 = require("./write_concern");
 | |
| const VALID_TXT_RECORDS = ['authSource', 'replicaSet', 'loadBalanced'];
 | |
| const LB_SINGLE_HOST_ERROR = 'loadBalanced option only supported with a single host in the URI';
 | |
| const LB_REPLICA_SET_ERROR = 'loadBalanced option not supported with a replicaSet option';
 | |
| const LB_DIRECT_CONNECTION_ERROR = 'loadBalanced option not supported when directConnection is provided';
 | |
| /**
 | |
|  * Determines whether a provided address matches the provided parent domain in order
 | |
|  * to avoid certain attack vectors.
 | |
|  *
 | |
|  * @param srvAddress - The address to check against a domain
 | |
|  * @param parentDomain - The domain to check the provided address against
 | |
|  * @returns Whether the provided address matches the parent domain
 | |
|  */
 | |
| function matchesParentDomain(srvAddress, parentDomain) {
 | |
|     const regex = /^.*?\./;
 | |
|     const srv = `.${srvAddress.replace(regex, '')}`;
 | |
|     const parent = `.${parentDomain.replace(regex, '')}`;
 | |
|     return srv.endsWith(parent);
 | |
| }
 | |
| /**
 | |
|  * Lookup a `mongodb+srv` connection string, combine the parts and reparse it as a normal
 | |
|  * connection string.
 | |
|  *
 | |
|  * @param uri - The connection string to parse
 | |
|  * @param options - Optional user provided connection string options
 | |
|  */
 | |
| async function resolveSRVRecord(options) {
 | |
|     if (typeof options.srvHost !== 'string') {
 | |
|         throw new error_1.MongoAPIError('Option "srvHost" must not be empty');
 | |
|     }
 | |
|     if (options.srvHost.split('.').length < 3) {
 | |
|         // TODO(NODE-3484): Replace with MongoConnectionStringError
 | |
|         throw new error_1.MongoAPIError('URI must include hostname, domain name, and tld');
 | |
|     }
 | |
|     // Resolve the SRV record and use the result as the list of hosts to connect to.
 | |
|     const lookupAddress = options.srvHost;
 | |
|     const addresses = await dns.promises.resolveSrv(`_${options.srvServiceName}._tcp.${lookupAddress}`);
 | |
|     if (addresses.length === 0) {
 | |
|         throw new error_1.MongoAPIError('No addresses found at host');
 | |
|     }
 | |
|     for (const { name } of addresses) {
 | |
|         if (!matchesParentDomain(name, lookupAddress)) {
 | |
|             throw new error_1.MongoAPIError('Server record does not share hostname with parent URI');
 | |
|         }
 | |
|     }
 | |
|     const hostAddresses = addresses.map(r => utils_1.HostAddress.fromString(`${r.name}:${r.port ?? 27017}`));
 | |
|     validateLoadBalancedOptions(hostAddresses, options, true);
 | |
|     // Resolve TXT record and add options from there if they exist.
 | |
|     let record;
 | |
|     try {
 | |
|         record = await dns.promises.resolveTxt(lookupAddress);
 | |
|     }
 | |
|     catch (error) {
 | |
|         if (error.code !== 'ENODATA' && error.code !== 'ENOTFOUND') {
 | |
|             throw error;
 | |
|         }
 | |
|         return hostAddresses;
 | |
|     }
 | |
|     if (record.length > 1) {
 | |
|         throw new error_1.MongoParseError('Multiple text records not allowed');
 | |
|     }
 | |
|     const txtRecordOptions = new url_1.URLSearchParams(record[0].join(''));
 | |
|     const txtRecordOptionKeys = [...txtRecordOptions.keys()];
 | |
|     if (txtRecordOptionKeys.some(key => !VALID_TXT_RECORDS.includes(key))) {
 | |
|         throw new error_1.MongoParseError(`Text record may only set any of: ${VALID_TXT_RECORDS.join(', ')}`);
 | |
|     }
 | |
|     if (VALID_TXT_RECORDS.some(option => txtRecordOptions.get(option) === '')) {
 | |
|         throw new error_1.MongoParseError('Cannot have empty URI params in DNS TXT Record');
 | |
|     }
 | |
|     const source = txtRecordOptions.get('authSource') ?? undefined;
 | |
|     const replicaSet = txtRecordOptions.get('replicaSet') ?? undefined;
 | |
|     const loadBalanced = txtRecordOptions.get('loadBalanced') ?? undefined;
 | |
|     if (!options.userSpecifiedAuthSource &&
 | |
|         source &&
 | |
|         options.credentials &&
 | |
|         !providers_1.AUTH_MECHS_AUTH_SRC_EXTERNAL.has(options.credentials.mechanism)) {
 | |
|         options.credentials = mongo_credentials_1.MongoCredentials.merge(options.credentials, { source });
 | |
|     }
 | |
|     if (!options.userSpecifiedReplicaSet && replicaSet) {
 | |
|         options.replicaSet = replicaSet;
 | |
|     }
 | |
|     if (loadBalanced === 'true') {
 | |
|         options.loadBalanced = true;
 | |
|     }
 | |
|     if (options.replicaSet && options.srvMaxHosts > 0) {
 | |
|         throw new error_1.MongoParseError('Cannot combine replicaSet option with srvMaxHosts');
 | |
|     }
 | |
|     validateLoadBalancedOptions(hostAddresses, options, true);
 | |
|     return hostAddresses;
 | |
| }
 | |
| exports.resolveSRVRecord = resolveSRVRecord;
 | |
| /**
 | |
|  * Checks if TLS options are valid
 | |
|  *
 | |
|  * @param allOptions - All options provided by user or included in default options map
 | |
|  * @throws MongoAPIError if TLS options are invalid
 | |
|  */
 | |
| function checkTLSOptions(allOptions) {
 | |
|     if (!allOptions)
 | |
|         return;
 | |
|     const check = (a, b) => {
 | |
|         if (allOptions.has(a) && allOptions.has(b)) {
 | |
|             throw new error_1.MongoAPIError(`The '${a}' option cannot be used with the '${b}' option`);
 | |
|         }
 | |
|     };
 | |
|     check('tlsInsecure', 'tlsAllowInvalidCertificates');
 | |
|     check('tlsInsecure', 'tlsAllowInvalidHostnames');
 | |
|     check('tlsInsecure', 'tlsDisableCertificateRevocationCheck');
 | |
|     check('tlsInsecure', 'tlsDisableOCSPEndpointCheck');
 | |
|     check('tlsAllowInvalidCertificates', 'tlsDisableCertificateRevocationCheck');
 | |
|     check('tlsAllowInvalidCertificates', 'tlsDisableOCSPEndpointCheck');
 | |
|     check('tlsDisableCertificateRevocationCheck', 'tlsDisableOCSPEndpointCheck');
 | |
| }
 | |
| const TRUTHS = new Set(['true', 't', '1', 'y', 'yes']);
 | |
| const FALSEHOODS = new Set(['false', 'f', '0', 'n', 'no', '-1']);
 | |
| function getBoolean(name, value) {
 | |
|     if (typeof value === 'boolean')
 | |
|         return value;
 | |
|     const valueString = String(value).toLowerCase();
 | |
|     if (TRUTHS.has(valueString)) {
 | |
|         if (valueString !== 'true') {
 | |
|             (0, utils_1.emitWarningOnce)(`deprecated value for ${name} : ${valueString} - please update to ${name} : true instead`);
 | |
|         }
 | |
|         return true;
 | |
|     }
 | |
|     if (FALSEHOODS.has(valueString)) {
 | |
|         if (valueString !== 'false') {
 | |
|             (0, utils_1.emitWarningOnce)(`deprecated value for ${name} : ${valueString} - please update to ${name} : false instead`);
 | |
|         }
 | |
|         return false;
 | |
|     }
 | |
|     throw new error_1.MongoParseError(`Expected ${name} to be stringified boolean value, got: ${value}`);
 | |
| }
 | |
| function getIntFromOptions(name, value) {
 | |
|     const parsedInt = (0, utils_1.parseInteger)(value);
 | |
|     if (parsedInt != null) {
 | |
|         return parsedInt;
 | |
|     }
 | |
|     throw new error_1.MongoParseError(`Expected ${name} to be stringified int value, got: ${value}`);
 | |
| }
 | |
| function getUIntFromOptions(name, value) {
 | |
|     const parsedValue = getIntFromOptions(name, value);
 | |
|     if (parsedValue < 0) {
 | |
|         throw new error_1.MongoParseError(`${name} can only be a positive int value, got: ${value}`);
 | |
|     }
 | |
|     return parsedValue;
 | |
| }
 | |
| function* entriesFromString(value) {
 | |
|     const keyValuePairs = value.split(',');
 | |
|     for (const keyValue of keyValuePairs) {
 | |
|         const [key, value] = keyValue.split(':');
 | |
|         if (value == null) {
 | |
|             throw new error_1.MongoParseError('Cannot have undefined values in key value pairs');
 | |
|         }
 | |
|         yield [key, value];
 | |
|     }
 | |
| }
 | |
| class CaseInsensitiveMap extends Map {
 | |
|     constructor(entries = []) {
 | |
|         super(entries.map(([k, v]) => [k.toLowerCase(), v]));
 | |
|     }
 | |
|     has(k) {
 | |
|         return super.has(k.toLowerCase());
 | |
|     }
 | |
|     get(k) {
 | |
|         return super.get(k.toLowerCase());
 | |
|     }
 | |
|     set(k, v) {
 | |
|         return super.set(k.toLowerCase(), v);
 | |
|     }
 | |
|     delete(k) {
 | |
|         return super.delete(k.toLowerCase());
 | |
|     }
 | |
| }
 | |
| function parseOptions(uri, mongoClient = undefined, options = {}) {
 | |
|     if (mongoClient != null && !(mongoClient instanceof mongo_client_1.MongoClient)) {
 | |
|         options = mongoClient;
 | |
|         mongoClient = undefined;
 | |
|     }
 | |
|     const url = new mongodb_connection_string_url_1.default(uri);
 | |
|     const { hosts, isSRV } = url;
 | |
|     const mongoOptions = Object.create(null);
 | |
|     // Feature flags
 | |
|     for (const flag of Object.getOwnPropertySymbols(options)) {
 | |
|         if (exports.FEATURE_FLAGS.has(flag)) {
 | |
|             mongoOptions[flag] = options[flag];
 | |
|         }
 | |
|     }
 | |
|     mongoOptions.hosts = isSRV ? [] : hosts.map(utils_1.HostAddress.fromString);
 | |
|     const urlOptions = new CaseInsensitiveMap();
 | |
|     if (url.pathname !== '/' && url.pathname !== '') {
 | |
|         const dbName = decodeURIComponent(url.pathname[0] === '/' ? url.pathname.slice(1) : url.pathname);
 | |
|         if (dbName) {
 | |
|             urlOptions.set('dbName', [dbName]);
 | |
|         }
 | |
|     }
 | |
|     if (url.username !== '') {
 | |
|         const auth = {
 | |
|             username: decodeURIComponent(url.username)
 | |
|         };
 | |
|         if (typeof url.password === 'string') {
 | |
|             auth.password = decodeURIComponent(url.password);
 | |
|         }
 | |
|         urlOptions.set('auth', [auth]);
 | |
|     }
 | |
|     for (const key of url.searchParams.keys()) {
 | |
|         const values = [...url.searchParams.getAll(key)];
 | |
|         if (values.includes('')) {
 | |
|             throw new error_1.MongoAPIError('URI cannot contain options with no value');
 | |
|         }
 | |
|         if (!urlOptions.has(key)) {
 | |
|             urlOptions.set(key, values);
 | |
|         }
 | |
|     }
 | |
|     const objectOptions = new CaseInsensitiveMap(Object.entries(options).filter(([, v]) => v != null));
 | |
|     // Validate options that can only be provided by one of uri or object
 | |
|     if (urlOptions.has('serverApi')) {
 | |
|         throw new error_1.MongoParseError('URI cannot contain `serverApi`, it can only be passed to the client');
 | |
|     }
 | |
|     if (objectOptions.has('loadBalanced')) {
 | |
|         throw new error_1.MongoParseError('loadBalanced is only a valid option in the URI');
 | |
|     }
 | |
|     // All option collection
 | |
|     const allOptions = new CaseInsensitiveMap();
 | |
|     const allKeys = new Set([
 | |
|         ...urlOptions.keys(),
 | |
|         ...objectOptions.keys(),
 | |
|         ...exports.DEFAULT_OPTIONS.keys()
 | |
|     ]);
 | |
|     for (const key of allKeys) {
 | |
|         const values = [];
 | |
|         const objectOptionValue = objectOptions.get(key);
 | |
|         if (objectOptionValue != null) {
 | |
|             values.push(objectOptionValue);
 | |
|         }
 | |
|         const urlValue = urlOptions.get(key);
 | |
|         if (urlValue != null) {
 | |
|             values.push(...urlValue);
 | |
|         }
 | |
|         const defaultOptionsValue = exports.DEFAULT_OPTIONS.get(key);
 | |
|         if (defaultOptionsValue != null) {
 | |
|             values.push(defaultOptionsValue);
 | |
|         }
 | |
|         allOptions.set(key, values);
 | |
|     }
 | |
|     if (allOptions.has('tlsCertificateKeyFile') && !allOptions.has('tlsCertificateFile')) {
 | |
|         allOptions.set('tlsCertificateFile', allOptions.get('tlsCertificateKeyFile'));
 | |
|     }
 | |
|     if (allOptions.has('tls') || allOptions.has('ssl')) {
 | |
|         const tlsAndSslOpts = (allOptions.get('tls') || [])
 | |
|             .concat(allOptions.get('ssl') || [])
 | |
|             .map(getBoolean.bind(null, 'tls/ssl'));
 | |
|         if (new Set(tlsAndSslOpts).size !== 1) {
 | |
|             throw new error_1.MongoParseError('All values of tls/ssl must be the same.');
 | |
|         }
 | |
|     }
 | |
|     checkTLSOptions(allOptions);
 | |
|     const unsupportedOptions = (0, utils_1.setDifference)(allKeys, Array.from(Object.keys(exports.OPTIONS)).map(s => s.toLowerCase()));
 | |
|     if (unsupportedOptions.size !== 0) {
 | |
|         const optionWord = unsupportedOptions.size > 1 ? 'options' : 'option';
 | |
|         const isOrAre = unsupportedOptions.size > 1 ? 'are' : 'is';
 | |
|         throw new error_1.MongoParseError(`${optionWord} ${Array.from(unsupportedOptions).join(', ')} ${isOrAre} not supported`);
 | |
|     }
 | |
|     // Option parsing and setting
 | |
|     for (const [key, descriptor] of Object.entries(exports.OPTIONS)) {
 | |
|         const values = allOptions.get(key);
 | |
|         if (!values || values.length === 0)
 | |
|             continue;
 | |
|         setOption(mongoOptions, key, descriptor, values);
 | |
|     }
 | |
|     if (mongoOptions.credentials) {
 | |
|         const isGssapi = mongoOptions.credentials.mechanism === providers_1.AuthMechanism.MONGODB_GSSAPI;
 | |
|         const isX509 = mongoOptions.credentials.mechanism === providers_1.AuthMechanism.MONGODB_X509;
 | |
|         const isAws = mongoOptions.credentials.mechanism === providers_1.AuthMechanism.MONGODB_AWS;
 | |
|         if ((isGssapi || isX509) &&
 | |
|             allOptions.has('authSource') &&
 | |
|             mongoOptions.credentials.source !== '$external') {
 | |
|             // If authSource was explicitly given and its incorrect, we error
 | |
|             throw new error_1.MongoParseError(`${mongoOptions.credentials} can only have authSource set to '$external'`);
 | |
|         }
 | |
|         if (!(isGssapi || isX509 || isAws) && mongoOptions.dbName && !allOptions.has('authSource')) {
 | |
|             // inherit the dbName unless GSSAPI or X509, then silently ignore dbName
 | |
|             // and there was no specific authSource given
 | |
|             mongoOptions.credentials = mongo_credentials_1.MongoCredentials.merge(mongoOptions.credentials, {
 | |
|                 source: mongoOptions.dbName
 | |
|             });
 | |
|         }
 | |
|         if (isAws && mongoOptions.credentials.username && !mongoOptions.credentials.password) {
 | |
|             throw new error_1.MongoMissingCredentialsError(`When using ${mongoOptions.credentials.mechanism} password must be set when a username is specified`);
 | |
|         }
 | |
|         mongoOptions.credentials.validate();
 | |
|         // Check if the only auth related option provided was authSource, if so we can remove credentials
 | |
|         if (mongoOptions.credentials.password === '' &&
 | |
|             mongoOptions.credentials.username === '' &&
 | |
|             mongoOptions.credentials.mechanism === providers_1.AuthMechanism.MONGODB_DEFAULT &&
 | |
|             Object.keys(mongoOptions.credentials.mechanismProperties).length === 0) {
 | |
|             delete mongoOptions.credentials;
 | |
|         }
 | |
|     }
 | |
|     if (!mongoOptions.dbName) {
 | |
|         // dbName default is applied here because of the credential validation above
 | |
|         mongoOptions.dbName = 'test';
 | |
|     }
 | |
|     validateLoadBalancedOptions(hosts, mongoOptions, isSRV);
 | |
|     if (mongoClient && mongoOptions.autoEncryption) {
 | |
|         encrypter_1.Encrypter.checkForMongoCrypt();
 | |
|         mongoOptions.encrypter = new encrypter_1.Encrypter(mongoClient, uri, options);
 | |
|         mongoOptions.autoEncrypter = mongoOptions.encrypter.autoEncrypter;
 | |
|     }
 | |
|     // Potential SRV Overrides and SRV connection string validations
 | |
|     mongoOptions.userSpecifiedAuthSource =
 | |
|         objectOptions.has('authSource') || urlOptions.has('authSource');
 | |
|     mongoOptions.userSpecifiedReplicaSet =
 | |
|         objectOptions.has('replicaSet') || urlOptions.has('replicaSet');
 | |
|     if (isSRV) {
 | |
|         // SRV Record is resolved upon connecting
 | |
|         mongoOptions.srvHost = hosts[0];
 | |
|         if (mongoOptions.directConnection) {
 | |
|             throw new error_1.MongoAPIError('SRV URI does not support directConnection');
 | |
|         }
 | |
|         if (mongoOptions.srvMaxHosts > 0 && typeof mongoOptions.replicaSet === 'string') {
 | |
|             throw new error_1.MongoParseError('Cannot use srvMaxHosts option with replicaSet');
 | |
|         }
 | |
|         // SRV turns on TLS by default, but users can override and turn it off
 | |
|         const noUserSpecifiedTLS = !objectOptions.has('tls') && !urlOptions.has('tls');
 | |
|         const noUserSpecifiedSSL = !objectOptions.has('ssl') && !urlOptions.has('ssl');
 | |
|         if (noUserSpecifiedTLS && noUserSpecifiedSSL) {
 | |
|             mongoOptions.tls = true;
 | |
|         }
 | |
|     }
 | |
|     else {
 | |
|         const userSpecifiedSrvOptions = urlOptions.has('srvMaxHosts') ||
 | |
|             objectOptions.has('srvMaxHosts') ||
 | |
|             urlOptions.has('srvServiceName') ||
 | |
|             objectOptions.has('srvServiceName');
 | |
|         if (userSpecifiedSrvOptions) {
 | |
|             throw new error_1.MongoParseError('Cannot use srvMaxHosts or srvServiceName with a non-srv connection string');
 | |
|         }
 | |
|     }
 | |
|     if (mongoOptions.directConnection && mongoOptions.hosts.length !== 1) {
 | |
|         throw new error_1.MongoParseError('directConnection option requires exactly one host');
 | |
|     }
 | |
|     if (!mongoOptions.proxyHost &&
 | |
|         (mongoOptions.proxyPort || mongoOptions.proxyUsername || mongoOptions.proxyPassword)) {
 | |
|         throw new error_1.MongoParseError('Must specify proxyHost if other proxy options are passed');
 | |
|     }
 | |
|     if ((mongoOptions.proxyUsername && !mongoOptions.proxyPassword) ||
 | |
|         (!mongoOptions.proxyUsername && mongoOptions.proxyPassword)) {
 | |
|         throw new error_1.MongoParseError('Can only specify both of proxy username/password or neither');
 | |
|     }
 | |
|     const proxyOptions = ['proxyHost', 'proxyPort', 'proxyUsername', 'proxyPassword'].map(key => urlOptions.get(key) ?? []);
 | |
|     if (proxyOptions.some(options => options.length > 1)) {
 | |
|         throw new error_1.MongoParseError('Proxy options cannot be specified multiple times in the connection string');
 | |
|     }
 | |
|     const loggerFeatureFlag = Symbol.for('@@mdb.enableMongoLogger');
 | |
|     mongoOptions[loggerFeatureFlag] = mongoOptions[loggerFeatureFlag] ?? false;
 | |
|     let loggerEnvOptions = {};
 | |
|     let loggerClientOptions = {};
 | |
|     if (mongoOptions[loggerFeatureFlag]) {
 | |
|         loggerEnvOptions = {
 | |
|             MONGODB_LOG_COMMAND: process.env.MONGODB_LOG_COMMAND,
 | |
|             MONGODB_LOG_TOPOLOGY: process.env.MONGODB_LOG_TOPOLOGY,
 | |
|             MONGODB_LOG_SERVER_SELECTION: process.env.MONGODB_LOG_SERVER_SELECTION,
 | |
|             MONGODB_LOG_CONNECTION: process.env.MONGODB_LOG_CONNECTION,
 | |
|             MONGODB_LOG_ALL: process.env.MONGODB_LOG_ALL,
 | |
|             MONGODB_LOG_MAX_DOCUMENT_LENGTH: process.env.MONGODB_LOG_MAX_DOCUMENT_LENGTH,
 | |
|             MONGODB_LOG_PATH: process.env.MONGODB_LOG_PATH
 | |
|         };
 | |
|         loggerClientOptions = {
 | |
|             mongodbLogPath: mongoOptions.mongodbLogPath
 | |
|         };
 | |
|     }
 | |
|     mongoOptions.mongoLoggerOptions = mongo_logger_1.MongoLogger.resolveOptions(loggerEnvOptions, loggerClientOptions);
 | |
|     return mongoOptions;
 | |
| }
 | |
| exports.parseOptions = parseOptions;
 | |
| /**
 | |
|  * #### Throws if LB mode is true:
 | |
|  * - hosts contains more than one host
 | |
|  * - there is a replicaSet name set
 | |
|  * - directConnection is set
 | |
|  * - if srvMaxHosts is used when an srv connection string is passed in
 | |
|  *
 | |
|  * @throws MongoParseError
 | |
|  */
 | |
| function validateLoadBalancedOptions(hosts, mongoOptions, isSrv) {
 | |
|     if (mongoOptions.loadBalanced) {
 | |
|         if (hosts.length > 1) {
 | |
|             throw new error_1.MongoParseError(LB_SINGLE_HOST_ERROR);
 | |
|         }
 | |
|         if (mongoOptions.replicaSet) {
 | |
|             throw new error_1.MongoParseError(LB_REPLICA_SET_ERROR);
 | |
|         }
 | |
|         if (mongoOptions.directConnection) {
 | |
|             throw new error_1.MongoParseError(LB_DIRECT_CONNECTION_ERROR);
 | |
|         }
 | |
|         if (isSrv && mongoOptions.srvMaxHosts > 0) {
 | |
|             throw new error_1.MongoParseError('Cannot limit srv hosts with loadBalanced enabled');
 | |
|         }
 | |
|     }
 | |
|     return;
 | |
| }
 | |
| function setOption(mongoOptions, key, descriptor, values) {
 | |
|     const { target, type, transform, deprecated } = descriptor;
 | |
|     const name = target ?? key;
 | |
|     if (deprecated) {
 | |
|         const deprecatedMsg = typeof deprecated === 'string' ? `: ${deprecated}` : '';
 | |
|         (0, utils_1.emitWarning)(`${key} is a deprecated option${deprecatedMsg}`);
 | |
|     }
 | |
|     switch (type) {
 | |
|         case 'boolean':
 | |
|             mongoOptions[name] = getBoolean(name, values[0]);
 | |
|             break;
 | |
|         case 'int':
 | |
|             mongoOptions[name] = getIntFromOptions(name, values[0]);
 | |
|             break;
 | |
|         case 'uint':
 | |
|             mongoOptions[name] = getUIntFromOptions(name, values[0]);
 | |
|             break;
 | |
|         case 'string':
 | |
|             if (values[0] == null) {
 | |
|                 break;
 | |
|             }
 | |
|             mongoOptions[name] = String(values[0]);
 | |
|             break;
 | |
|         case 'record':
 | |
|             if (!(0, utils_1.isRecord)(values[0])) {
 | |
|                 throw new error_1.MongoParseError(`${name} must be an object`);
 | |
|             }
 | |
|             mongoOptions[name] = values[0];
 | |
|             break;
 | |
|         case 'any':
 | |
|             mongoOptions[name] = values[0];
 | |
|             break;
 | |
|         default: {
 | |
|             if (!transform) {
 | |
|                 throw new error_1.MongoParseError('Descriptors missing a type must define a transform');
 | |
|             }
 | |
|             const transformValue = transform({ name, options: mongoOptions, values });
 | |
|             mongoOptions[name] = transformValue;
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| }
 | |
| exports.OPTIONS = {
 | |
|     appName: {
 | |
|         target: 'metadata',
 | |
|         transform({ options, values: [value] }) {
 | |
|             return (0, utils_1.makeClientMetadata)({ ...options.driverInfo, appName: String(value) });
 | |
|         }
 | |
|     },
 | |
|     auth: {
 | |
|         target: 'credentials',
 | |
|         transform({ name, options, values: [value] }) {
 | |
|             if (!(0, utils_1.isRecord)(value, ['username', 'password'])) {
 | |
|                 throw new error_1.MongoParseError(`${name} must be an object with 'username' and 'password' properties`);
 | |
|             }
 | |
|             return mongo_credentials_1.MongoCredentials.merge(options.credentials, {
 | |
|                 username: value.username,
 | |
|                 password: value.password
 | |
|             });
 | |
|         }
 | |
|     },
 | |
|     authMechanism: {
 | |
|         target: 'credentials',
 | |
|         transform({ options, values: [value] }) {
 | |
|             const mechanisms = Object.values(providers_1.AuthMechanism);
 | |
|             const [mechanism] = mechanisms.filter(m => m.match(RegExp(String.raw `\b${value}\b`, 'i')));
 | |
|             if (!mechanism) {
 | |
|                 throw new error_1.MongoParseError(`authMechanism one of ${mechanisms}, got ${value}`);
 | |
|             }
 | |
|             let source = options.credentials?.source;
 | |
|             if (mechanism === providers_1.AuthMechanism.MONGODB_PLAIN ||
 | |
|                 providers_1.AUTH_MECHS_AUTH_SRC_EXTERNAL.has(mechanism)) {
 | |
|                 // some mechanisms have '$external' as the Auth Source
 | |
|                 source = '$external';
 | |
|             }
 | |
|             let password = options.credentials?.password;
 | |
|             if (mechanism === providers_1.AuthMechanism.MONGODB_X509 && password === '') {
 | |
|                 password = undefined;
 | |
|             }
 | |
|             return mongo_credentials_1.MongoCredentials.merge(options.credentials, {
 | |
|                 mechanism,
 | |
|                 source,
 | |
|                 password
 | |
|             });
 | |
|         }
 | |
|     },
 | |
|     authMechanismProperties: {
 | |
|         target: 'credentials',
 | |
|         transform({ options, values: [optionValue] }) {
 | |
|             if (typeof optionValue === 'string') {
 | |
|                 const mechanismProperties = Object.create(null);
 | |
|                 for (const [key, value] of entriesFromString(optionValue)) {
 | |
|                     try {
 | |
|                         mechanismProperties[key] = getBoolean(key, value);
 | |
|                     }
 | |
|                     catch {
 | |
|                         mechanismProperties[key] = value;
 | |
|                     }
 | |
|                 }
 | |
|                 return mongo_credentials_1.MongoCredentials.merge(options.credentials, {
 | |
|                     mechanismProperties
 | |
|                 });
 | |
|             }
 | |
|             if (!(0, utils_1.isRecord)(optionValue)) {
 | |
|                 throw new error_1.MongoParseError('AuthMechanismProperties must be an object');
 | |
|             }
 | |
|             return mongo_credentials_1.MongoCredentials.merge(options.credentials, { mechanismProperties: optionValue });
 | |
|         }
 | |
|     },
 | |
|     authSource: {
 | |
|         target: 'credentials',
 | |
|         transform({ options, values: [value] }) {
 | |
|             const source = String(value);
 | |
|             return mongo_credentials_1.MongoCredentials.merge(options.credentials, { source });
 | |
|         }
 | |
|     },
 | |
|     autoEncryption: {
 | |
|         type: 'record'
 | |
|     },
 | |
|     bsonRegExp: {
 | |
|         type: 'boolean'
 | |
|     },
 | |
|     serverApi: {
 | |
|         target: 'serverApi',
 | |
|         transform({ values: [version] }) {
 | |
|             const serverApiToValidate = typeof version === 'string' ? { version } : version;
 | |
|             const versionToValidate = serverApiToValidate && serverApiToValidate.version;
 | |
|             if (!versionToValidate) {
 | |
|                 throw new error_1.MongoParseError(`Invalid \`serverApi\` property; must specify a version from the following enum: ["${Object.values(mongo_client_1.ServerApiVersion).join('", "')}"]`);
 | |
|             }
 | |
|             if (!Object.values(mongo_client_1.ServerApiVersion).some(v => v === versionToValidate)) {
 | |
|                 throw new error_1.MongoParseError(`Invalid server API version=${versionToValidate}; must be in the following enum: ["${Object.values(mongo_client_1.ServerApiVersion).join('", "')}"]`);
 | |
|             }
 | |
|             return serverApiToValidate;
 | |
|         }
 | |
|     },
 | |
|     checkKeys: {
 | |
|         type: 'boolean'
 | |
|     },
 | |
|     compressors: {
 | |
|         default: 'none',
 | |
|         target: 'compressors',
 | |
|         transform({ values }) {
 | |
|             const compressionList = new Set();
 | |
|             for (const compVal of values) {
 | |
|                 const compValArray = typeof compVal === 'string' ? compVal.split(',') : compVal;
 | |
|                 if (!Array.isArray(compValArray)) {
 | |
|                     throw new error_1.MongoInvalidArgumentError('compressors must be an array or a comma-delimited list of strings');
 | |
|                 }
 | |
|                 for (const c of compValArray) {
 | |
|                     if (Object.keys(compression_1.Compressor).includes(String(c))) {
 | |
|                         compressionList.add(String(c));
 | |
|                     }
 | |
|                     else {
 | |
|                         throw new error_1.MongoInvalidArgumentError(`${c} is not a valid compression mechanism. Must be one of: ${Object.keys(compression_1.Compressor)}.`);
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|             return [...compressionList];
 | |
|         }
 | |
|     },
 | |
|     connectTimeoutMS: {
 | |
|         default: 30000,
 | |
|         type: 'uint'
 | |
|     },
 | |
|     dbName: {
 | |
|         type: 'string'
 | |
|     },
 | |
|     directConnection: {
 | |
|         default: false,
 | |
|         type: 'boolean'
 | |
|     },
 | |
|     driverInfo: {
 | |
|         target: 'metadata',
 | |
|         default: (0, utils_1.makeClientMetadata)(),
 | |
|         transform({ options, values: [value] }) {
 | |
|             if (!(0, utils_1.isRecord)(value))
 | |
|                 throw new error_1.MongoParseError('DriverInfo must be an object');
 | |
|             return (0, utils_1.makeClientMetadata)({
 | |
|                 driverInfo: value,
 | |
|                 appName: options.metadata?.application?.name
 | |
|             });
 | |
|         }
 | |
|     },
 | |
|     enableUtf8Validation: { type: 'boolean', default: true },
 | |
|     family: {
 | |
|         transform({ name, values: [value] }) {
 | |
|             const transformValue = getIntFromOptions(name, value);
 | |
|             if (transformValue === 4 || transformValue === 6) {
 | |
|                 return transformValue;
 | |
|             }
 | |
|             throw new error_1.MongoParseError(`Option 'family' must be 4 or 6 got ${transformValue}.`);
 | |
|         }
 | |
|     },
 | |
|     fieldsAsRaw: {
 | |
|         type: 'record'
 | |
|     },
 | |
|     forceServerObjectId: {
 | |
|         default: false,
 | |
|         type: 'boolean'
 | |
|     },
 | |
|     fsync: {
 | |
|         deprecated: 'Please use journal instead',
 | |
|         target: 'writeConcern',
 | |
|         transform({ name, options, values: [value] }) {
 | |
|             const wc = write_concern_1.WriteConcern.fromOptions({
 | |
|                 writeConcern: {
 | |
|                     ...options.writeConcern,
 | |
|                     fsync: getBoolean(name, value)
 | |
|                 }
 | |
|             });
 | |
|             if (!wc)
 | |
|                 throw new error_1.MongoParseError(`Unable to make a writeConcern from fsync=${value}`);
 | |
|             return wc;
 | |
|         }
 | |
|     },
 | |
|     heartbeatFrequencyMS: {
 | |
|         default: 10000,
 | |
|         type: 'uint'
 | |
|     },
 | |
|     ignoreUndefined: {
 | |
|         type: 'boolean'
 | |
|     },
 | |
|     j: {
 | |
|         deprecated: 'Please use journal instead',
 | |
|         target: 'writeConcern',
 | |
|         transform({ name, options, values: [value] }) {
 | |
|             const wc = write_concern_1.WriteConcern.fromOptions({
 | |
|                 writeConcern: {
 | |
|                     ...options.writeConcern,
 | |
|                     journal: getBoolean(name, value)
 | |
|                 }
 | |
|             });
 | |
|             if (!wc)
 | |
|                 throw new error_1.MongoParseError(`Unable to make a writeConcern from journal=${value}`);
 | |
|             return wc;
 | |
|         }
 | |
|     },
 | |
|     journal: {
 | |
|         target: 'writeConcern',
 | |
|         transform({ name, options, values: [value] }) {
 | |
|             const wc = write_concern_1.WriteConcern.fromOptions({
 | |
|                 writeConcern: {
 | |
|                     ...options.writeConcern,
 | |
|                     journal: getBoolean(name, value)
 | |
|                 }
 | |
|             });
 | |
|             if (!wc)
 | |
|                 throw new error_1.MongoParseError(`Unable to make a writeConcern from journal=${value}`);
 | |
|             return wc;
 | |
|         }
 | |
|     },
 | |
|     keepAlive: {
 | |
|         default: true,
 | |
|         type: 'boolean'
 | |
|     },
 | |
|     keepAliveInitialDelay: {
 | |
|         default: 120000,
 | |
|         type: 'uint'
 | |
|     },
 | |
|     loadBalanced: {
 | |
|         default: false,
 | |
|         type: 'boolean'
 | |
|     },
 | |
|     localThresholdMS: {
 | |
|         default: 15,
 | |
|         type: 'uint'
 | |
|     },
 | |
|     maxConnecting: {
 | |
|         default: 2,
 | |
|         transform({ name, values: [value] }) {
 | |
|             const maxConnecting = getUIntFromOptions(name, value);
 | |
|             if (maxConnecting === 0) {
 | |
|                 throw new error_1.MongoInvalidArgumentError('maxConnecting must be > 0 if specified');
 | |
|             }
 | |
|             return maxConnecting;
 | |
|         }
 | |
|     },
 | |
|     maxIdleTimeMS: {
 | |
|         default: 0,
 | |
|         type: 'uint'
 | |
|     },
 | |
|     maxPoolSize: {
 | |
|         default: 100,
 | |
|         type: 'uint'
 | |
|     },
 | |
|     maxStalenessSeconds: {
 | |
|         target: 'readPreference',
 | |
|         transform({ name, options, values: [value] }) {
 | |
|             const maxStalenessSeconds = getUIntFromOptions(name, value);
 | |
|             if (options.readPreference) {
 | |
|                 return read_preference_1.ReadPreference.fromOptions({
 | |
|                     readPreference: { ...options.readPreference, maxStalenessSeconds }
 | |
|                 });
 | |
|             }
 | |
|             else {
 | |
|                 return new read_preference_1.ReadPreference('secondary', undefined, { maxStalenessSeconds });
 | |
|             }
 | |
|         }
 | |
|     },
 | |
|     minInternalBufferSize: {
 | |
|         type: 'uint'
 | |
|     },
 | |
|     minPoolSize: {
 | |
|         default: 0,
 | |
|         type: 'uint'
 | |
|     },
 | |
|     minHeartbeatFrequencyMS: {
 | |
|         default: 500,
 | |
|         type: 'uint'
 | |
|     },
 | |
|     monitorCommands: {
 | |
|         default: false,
 | |
|         type: 'boolean'
 | |
|     },
 | |
|     name: {
 | |
|         target: 'driverInfo',
 | |
|         transform({ values: [value], options }) {
 | |
|             return { ...options.driverInfo, name: String(value) };
 | |
|         }
 | |
|     },
 | |
|     noDelay: {
 | |
|         default: true,
 | |
|         type: 'boolean'
 | |
|     },
 | |
|     pkFactory: {
 | |
|         default: utils_1.DEFAULT_PK_FACTORY,
 | |
|         transform({ values: [value] }) {
 | |
|             if ((0, utils_1.isRecord)(value, ['createPk']) && typeof value.createPk === 'function') {
 | |
|                 return value;
 | |
|             }
 | |
|             throw new error_1.MongoParseError(`Option pkFactory must be an object with a createPk function, got ${value}`);
 | |
|         }
 | |
|     },
 | |
|     promoteBuffers: {
 | |
|         type: 'boolean'
 | |
|     },
 | |
|     promoteLongs: {
 | |
|         type: 'boolean'
 | |
|     },
 | |
|     promoteValues: {
 | |
|         type: 'boolean'
 | |
|     },
 | |
|     proxyHost: {
 | |
|         type: 'string'
 | |
|     },
 | |
|     proxyPassword: {
 | |
|         type: 'string'
 | |
|     },
 | |
|     proxyPort: {
 | |
|         type: 'uint'
 | |
|     },
 | |
|     proxyUsername: {
 | |
|         type: 'string'
 | |
|     },
 | |
|     raw: {
 | |
|         default: false,
 | |
|         type: 'boolean'
 | |
|     },
 | |
|     readConcern: {
 | |
|         transform({ values: [value], options }) {
 | |
|             if (value instanceof read_concern_1.ReadConcern || (0, utils_1.isRecord)(value, ['level'])) {
 | |
|                 return read_concern_1.ReadConcern.fromOptions({ ...options.readConcern, ...value });
 | |
|             }
 | |
|             throw new error_1.MongoParseError(`ReadConcern must be an object, got ${JSON.stringify(value)}`);
 | |
|         }
 | |
|     },
 | |
|     readConcernLevel: {
 | |
|         target: 'readConcern',
 | |
|         transform({ values: [level], options }) {
 | |
|             return read_concern_1.ReadConcern.fromOptions({
 | |
|                 ...options.readConcern,
 | |
|                 level: level
 | |
|             });
 | |
|         }
 | |
|     },
 | |
|     readPreference: {
 | |
|         default: read_preference_1.ReadPreference.primary,
 | |
|         transform({ values: [value], options }) {
 | |
|             if (value instanceof read_preference_1.ReadPreference) {
 | |
|                 return read_preference_1.ReadPreference.fromOptions({
 | |
|                     readPreference: { ...options.readPreference, ...value },
 | |
|                     ...value
 | |
|                 });
 | |
|             }
 | |
|             if ((0, utils_1.isRecord)(value, ['mode'])) {
 | |
|                 const rp = read_preference_1.ReadPreference.fromOptions({
 | |
|                     readPreference: { ...options.readPreference, ...value },
 | |
|                     ...value
 | |
|                 });
 | |
|                 if (rp)
 | |
|                     return rp;
 | |
|                 else
 | |
|                     throw new error_1.MongoParseError(`Cannot make read preference from ${JSON.stringify(value)}`);
 | |
|             }
 | |
|             if (typeof value === 'string') {
 | |
|                 const rpOpts = {
 | |
|                     hedge: options.readPreference?.hedge,
 | |
|                     maxStalenessSeconds: options.readPreference?.maxStalenessSeconds
 | |
|                 };
 | |
|                 return new read_preference_1.ReadPreference(value, options.readPreference?.tags, rpOpts);
 | |
|             }
 | |
|             throw new error_1.MongoParseError(`Unknown ReadPreference value: ${value}`);
 | |
|         }
 | |
|     },
 | |
|     readPreferenceTags: {
 | |
|         target: 'readPreference',
 | |
|         transform({ values, options }) {
 | |
|             const tags = Array.isArray(values[0])
 | |
|                 ? values[0]
 | |
|                 : values;
 | |
|             const readPreferenceTags = [];
 | |
|             for (const tag of tags) {
 | |
|                 const readPreferenceTag = Object.create(null);
 | |
|                 if (typeof tag === 'string') {
 | |
|                     for (const [k, v] of entriesFromString(tag)) {
 | |
|                         readPreferenceTag[k] = v;
 | |
|                     }
 | |
|                 }
 | |
|                 if ((0, utils_1.isRecord)(tag)) {
 | |
|                     for (const [k, v] of Object.entries(tag)) {
 | |
|                         readPreferenceTag[k] = v;
 | |
|                     }
 | |
|                 }
 | |
|                 readPreferenceTags.push(readPreferenceTag);
 | |
|             }
 | |
|             return read_preference_1.ReadPreference.fromOptions({
 | |
|                 readPreference: options.readPreference,
 | |
|                 readPreferenceTags
 | |
|             });
 | |
|         }
 | |
|     },
 | |
|     replicaSet: {
 | |
|         type: 'string'
 | |
|     },
 | |
|     retryReads: {
 | |
|         default: true,
 | |
|         type: 'boolean'
 | |
|     },
 | |
|     retryWrites: {
 | |
|         default: true,
 | |
|         type: 'boolean'
 | |
|     },
 | |
|     serializeFunctions: {
 | |
|         type: 'boolean'
 | |
|     },
 | |
|     serverSelectionTimeoutMS: {
 | |
|         default: 30000,
 | |
|         type: 'uint'
 | |
|     },
 | |
|     servername: {
 | |
|         type: 'string'
 | |
|     },
 | |
|     socketTimeoutMS: {
 | |
|         default: 0,
 | |
|         type: 'uint'
 | |
|     },
 | |
|     srvMaxHosts: {
 | |
|         type: 'uint',
 | |
|         default: 0
 | |
|     },
 | |
|     srvServiceName: {
 | |
|         type: 'string',
 | |
|         default: 'mongodb'
 | |
|     },
 | |
|     ssl: {
 | |
|         target: 'tls',
 | |
|         type: 'boolean'
 | |
|     },
 | |
|     sslCA: {
 | |
|         target: 'ca',
 | |
|         transform({ values: [value] }) {
 | |
|             return fs.readFileSync(String(value), { encoding: 'ascii' });
 | |
|         }
 | |
|     },
 | |
|     sslCRL: {
 | |
|         target: 'crl',
 | |
|         transform({ values: [value] }) {
 | |
|             return fs.readFileSync(String(value), { encoding: 'ascii' });
 | |
|         }
 | |
|     },
 | |
|     sslCert: {
 | |
|         target: 'cert',
 | |
|         transform({ values: [value] }) {
 | |
|             return fs.readFileSync(String(value), { encoding: 'ascii' });
 | |
|         }
 | |
|     },
 | |
|     sslKey: {
 | |
|         target: 'key',
 | |
|         transform({ values: [value] }) {
 | |
|             return fs.readFileSync(String(value), { encoding: 'ascii' });
 | |
|         }
 | |
|     },
 | |
|     sslPass: {
 | |
|         deprecated: true,
 | |
|         target: 'passphrase',
 | |
|         type: 'string'
 | |
|     },
 | |
|     sslValidate: {
 | |
|         target: 'rejectUnauthorized',
 | |
|         type: 'boolean'
 | |
|     },
 | |
|     tls: {
 | |
|         type: 'boolean'
 | |
|     },
 | |
|     tlsAllowInvalidCertificates: {
 | |
|         target: 'rejectUnauthorized',
 | |
|         transform({ name, values: [value] }) {
 | |
|             // allowInvalidCertificates is the inverse of rejectUnauthorized
 | |
|             return !getBoolean(name, value);
 | |
|         }
 | |
|     },
 | |
|     tlsAllowInvalidHostnames: {
 | |
|         target: 'checkServerIdentity',
 | |
|         transform({ name, values: [value] }) {
 | |
|             // tlsAllowInvalidHostnames means setting the checkServerIdentity function to a noop
 | |
|             return getBoolean(name, value) ? () => undefined : undefined;
 | |
|         }
 | |
|     },
 | |
|     tlsCAFile: {
 | |
|         target: 'ca',
 | |
|         transform({ values: [value] }) {
 | |
|             return fs.readFileSync(String(value), { encoding: 'ascii' });
 | |
|         }
 | |
|     },
 | |
|     tlsCertificateFile: {
 | |
|         target: 'cert',
 | |
|         transform({ values: [value] }) {
 | |
|             return fs.readFileSync(String(value), { encoding: 'ascii' });
 | |
|         }
 | |
|     },
 | |
|     tlsCertificateKeyFile: {
 | |
|         target: 'key',
 | |
|         transform({ values: [value] }) {
 | |
|             return fs.readFileSync(String(value), { encoding: 'ascii' });
 | |
|         }
 | |
|     },
 | |
|     tlsCertificateKeyFilePassword: {
 | |
|         target: 'passphrase',
 | |
|         type: 'any'
 | |
|     },
 | |
|     tlsInsecure: {
 | |
|         transform({ name, options, values: [value] }) {
 | |
|             const tlsInsecure = getBoolean(name, value);
 | |
|             if (tlsInsecure) {
 | |
|                 options.checkServerIdentity = () => undefined;
 | |
|                 options.rejectUnauthorized = false;
 | |
|             }
 | |
|             else {
 | |
|                 options.checkServerIdentity = options.tlsAllowInvalidHostnames
 | |
|                     ? () => undefined
 | |
|                     : undefined;
 | |
|                 options.rejectUnauthorized = options.tlsAllowInvalidCertificates ? false : true;
 | |
|             }
 | |
|             return tlsInsecure;
 | |
|         }
 | |
|     },
 | |
|     w: {
 | |
|         target: 'writeConcern',
 | |
|         transform({ values: [value], options }) {
 | |
|             return write_concern_1.WriteConcern.fromOptions({ writeConcern: { ...options.writeConcern, w: value } });
 | |
|         }
 | |
|     },
 | |
|     waitQueueTimeoutMS: {
 | |
|         default: 0,
 | |
|         type: 'uint'
 | |
|     },
 | |
|     writeConcern: {
 | |
|         target: 'writeConcern',
 | |
|         transform({ values: [value], options }) {
 | |
|             if ((0, utils_1.isRecord)(value) || value instanceof write_concern_1.WriteConcern) {
 | |
|                 return write_concern_1.WriteConcern.fromOptions({
 | |
|                     writeConcern: {
 | |
|                         ...options.writeConcern,
 | |
|                         ...value
 | |
|                     }
 | |
|                 });
 | |
|             }
 | |
|             else if (value === 'majority' || typeof value === 'number') {
 | |
|                 return write_concern_1.WriteConcern.fromOptions({
 | |
|                     writeConcern: {
 | |
|                         ...options.writeConcern,
 | |
|                         w: value
 | |
|                     }
 | |
|                 });
 | |
|             }
 | |
|             throw new error_1.MongoParseError(`Invalid WriteConcern cannot parse: ${JSON.stringify(value)}`);
 | |
|         }
 | |
|     },
 | |
|     wtimeout: {
 | |
|         deprecated: 'Please use wtimeoutMS instead',
 | |
|         target: 'writeConcern',
 | |
|         transform({ values: [value], options }) {
 | |
|             const wc = write_concern_1.WriteConcern.fromOptions({
 | |
|                 writeConcern: {
 | |
|                     ...options.writeConcern,
 | |
|                     wtimeout: getUIntFromOptions('wtimeout', value)
 | |
|                 }
 | |
|             });
 | |
|             if (wc)
 | |
|                 return wc;
 | |
|             throw new error_1.MongoParseError(`Cannot make WriteConcern from wtimeout`);
 | |
|         }
 | |
|     },
 | |
|     wtimeoutMS: {
 | |
|         target: 'writeConcern',
 | |
|         transform({ values: [value], options }) {
 | |
|             const wc = write_concern_1.WriteConcern.fromOptions({
 | |
|                 writeConcern: {
 | |
|                     ...options.writeConcern,
 | |
|                     wtimeoutMS: getUIntFromOptions('wtimeoutMS', value)
 | |
|                 }
 | |
|             });
 | |
|             if (wc)
 | |
|                 return wc;
 | |
|             throw new error_1.MongoParseError(`Cannot make WriteConcern from wtimeout`);
 | |
|         }
 | |
|     },
 | |
|     zlibCompressionLevel: {
 | |
|         default: 0,
 | |
|         type: 'int'
 | |
|     },
 | |
|     // Custom types for modifying core behavior
 | |
|     connectionType: { type: 'any' },
 | |
|     srvPoller: { type: 'any' },
 | |
|     // Accepted NodeJS Options
 | |
|     minDHSize: { type: 'any' },
 | |
|     pskCallback: { type: 'any' },
 | |
|     secureContext: { type: 'any' },
 | |
|     enableTrace: { type: 'any' },
 | |
|     requestCert: { type: 'any' },
 | |
|     rejectUnauthorized: { type: 'any' },
 | |
|     checkServerIdentity: { type: 'any' },
 | |
|     ALPNProtocols: { type: 'any' },
 | |
|     SNICallback: { type: 'any' },
 | |
|     session: { type: 'any' },
 | |
|     requestOCSP: { type: 'any' },
 | |
|     localAddress: { type: 'any' },
 | |
|     localPort: { type: 'any' },
 | |
|     hints: { type: 'any' },
 | |
|     lookup: { type: 'any' },
 | |
|     ca: { type: 'any' },
 | |
|     cert: { type: 'any' },
 | |
|     ciphers: { type: 'any' },
 | |
|     crl: { type: 'any' },
 | |
|     ecdhCurve: { type: 'any' },
 | |
|     key: { type: 'any' },
 | |
|     passphrase: { type: 'any' },
 | |
|     pfx: { type: 'any' },
 | |
|     secureProtocol: { type: 'any' },
 | |
|     index: { type: 'any' },
 | |
|     // Legacy Options, these are unused but left here to avoid errors with CSFLE lib
 | |
|     useNewUrlParser: { type: 'boolean' },
 | |
|     useUnifiedTopology: { type: 'boolean' }
 | |
| };
 | |
| exports.DEFAULT_OPTIONS = new CaseInsensitiveMap(Object.entries(exports.OPTIONS)
 | |
|     .filter(([, descriptor]) => descriptor.default != null)
 | |
|     .map(([k, d]) => [k, d.default]));
 | |
| /**
 | |
|  * Set of permitted feature flags
 | |
|  * @internal
 | |
|  */
 | |
| exports.FEATURE_FLAGS = new Set([
 | |
|     Symbol.for('@@mdb.skipPingOnConnect'),
 | |
|     Symbol.for('@@mdb.enableMongoLogger')
 | |
| ]);
 | |
| //# sourceMappingURL=connection_string.js.map
 |