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
			| 
								 
											3 years ago
										 
									 | 
							
								"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
							 |