@@ -30,7 +30,6 @@ import { ReadPreference, ReadPreferenceMode } from './read_preference';
3030import type { TagSet } from './sdam/server_description' ;
3131import {
3232 AnyOptions ,
33- Callback ,
3433 DEFAULT_PK_FACTORY ,
3534 emitWarning ,
3635 emitWarningOnce ,
@@ -70,97 +69,89 @@ function matchesParentDomain(srvAddress: string, parentDomain: string): boolean
7069 * @param uri - The connection string to parse
7170 * @param options - Optional user provided connection string options
7271 */
73- export function resolveSRVRecord ( options : MongoOptions , callback : Callback < HostAddress [ ] > ) : void {
72+ export async function resolveSRVRecord ( options : MongoOptions ) : Promise < HostAddress [ ] > {
7473 if ( typeof options . srvHost !== 'string' ) {
75- return callback ( new MongoAPIError ( 'Option "srvHost" must not be empty' ) ) ;
74+ throw new MongoAPIError ( 'Option "srvHost" must not be empty' ) ;
7675 }
7776
7877 if ( options . srvHost . split ( '.' ) . length < 3 ) {
7978 // TODO(NODE-3484): Replace with MongoConnectionStringError
80- return callback ( new MongoAPIError ( 'URI must include hostname, domain name, and tld' ) ) ;
79+ throw new MongoAPIError ( 'URI must include hostname, domain name, and tld' ) ;
8180 }
8281
8382 // Resolve the SRV record and use the result as the list of hosts to connect to.
8483 const lookupAddress = options . srvHost ;
85- dns . resolveSrv ( `_${ options . srvServiceName } ._tcp.${ lookupAddress } ` , ( err , addresses ) => {
86- if ( err ) return callback ( err ) ;
84+ const addresses = await dns . promises . resolveSrv (
85+ `_${ options . srvServiceName } ._tcp.${ lookupAddress } `
86+ ) ;
8787
88- if ( addresses . length === 0 ) {
89- return callback ( new MongoAPIError ( 'No addresses found at host' ) ) ;
90- }
88+ if ( addresses . length === 0 ) {
89+ throw new MongoAPIError ( 'No addresses found at host' ) ;
90+ }
9191
92- for ( const { name } of addresses ) {
93- if ( ! matchesParentDomain ( name , lookupAddress ) ) {
94- return callback ( new MongoAPIError ( 'Server record does not share hostname with parent URI' ) ) ;
95- }
92+ for ( const { name } of addresses ) {
93+ if ( ! matchesParentDomain ( name , lookupAddress ) ) {
94+ throw new MongoAPIError ( 'Server record does not share hostname with parent URI' ) ;
9695 }
96+ }
9797
98- const hostAddresses = addresses . map ( r =>
99- HostAddress . fromString ( ` ${ r . name } : ${ r . port ?? 27017 } ` )
100- ) ;
98+ const hostAddresses = addresses . map ( r => HostAddress . fromString ( ` ${ r . name } : ${ r . port ?? 27017 } ` ) ) ;
99+
100+ validateLoadBalancedOptions ( hostAddresses , options , true ) ;
101101
102- const lbError = validateLoadBalancedOptions ( hostAddresses , options , true ) ;
103- if ( lbError ) {
104- return callback ( lbError ) ;
102+ // Resolve TXT record and add options from there if they exist.
103+ let record ;
104+ try {
105+ record = await dns . promises . resolveTxt ( lookupAddress ) ;
106+ } catch ( error ) {
107+ if ( error . code !== 'ENODATA' && error . code !== 'ENOTFOUND' ) {
108+ throw error ;
105109 }
110+ return hostAddresses ;
111+ }
106112
107- // Resolve TXT record and add options from there if they exist.
108- dns . resolveTxt ( lookupAddress , ( err , record ) => {
109- if ( err ) {
110- if ( err . code !== 'ENODATA' && err . code !== 'ENOTFOUND' ) {
111- return callback ( err ) ;
112- }
113- } else {
114- if ( record . length > 1 ) {
115- return callback ( new MongoParseError ( 'Multiple text records not allowed' ) ) ;
116- }
113+ if ( record . length > 1 ) {
114+ throw new MongoParseError ( 'Multiple text records not allowed' ) ;
115+ }
117116
118- const txtRecordOptions = new URLSearchParams ( record [ 0 ] . join ( '' ) ) ;
119- const txtRecordOptionKeys = [ ...txtRecordOptions . keys ( ) ] ;
120- if ( txtRecordOptionKeys . some ( key => ! VALID_TXT_RECORDS . includes ( key ) ) ) {
121- return callback (
122- new MongoParseError ( `Text record may only set any of: ${ VALID_TXT_RECORDS . join ( ', ' ) } ` )
123- ) ;
124- }
117+ const txtRecordOptions = new URLSearchParams ( record [ 0 ] . join ( '' ) ) ;
118+ const txtRecordOptionKeys = [ ...txtRecordOptions . keys ( ) ] ;
119+ if ( txtRecordOptionKeys . some ( key => ! VALID_TXT_RECORDS . includes ( key ) ) ) {
120+ throw new MongoParseError ( `Text record may only set any of: ${ VALID_TXT_RECORDS . join ( ', ' ) } ` ) ;
121+ }
125122
126- if ( VALID_TXT_RECORDS . some ( option => txtRecordOptions . get ( option ) === '' ) ) {
127- return callback ( new MongoParseError ( 'Cannot have empty URI params in DNS TXT Record' ) ) ;
128- }
123+ if ( VALID_TXT_RECORDS . some ( option => txtRecordOptions . get ( option ) === '' ) ) {
124+ throw new MongoParseError ( 'Cannot have empty URI params in DNS TXT Record' ) ;
125+ }
129126
130- const source = txtRecordOptions . get ( 'authSource' ) ?? undefined ;
131- const replicaSet = txtRecordOptions . get ( 'replicaSet' ) ?? undefined ;
132- const loadBalanced = txtRecordOptions . get ( 'loadBalanced' ) ?? undefined ;
133-
134- if (
135- ! options . userSpecifiedAuthSource &&
136- source &&
137- options . credentials &&
138- ! AUTH_MECHS_AUTH_SRC_EXTERNAL . has ( options . credentials . mechanism )
139- ) {
140- options . credentials = MongoCredentials . merge ( options . credentials , { source } ) ;
141- }
127+ const source = txtRecordOptions . get ( 'authSource' ) ?? undefined ;
128+ const replicaSet = txtRecordOptions . get ( 'replicaSet' ) ?? undefined ;
129+ const loadBalanced = txtRecordOptions . get ( 'loadBalanced' ) ?? undefined ;
142130
143- if ( ! options . userSpecifiedReplicaSet && replicaSet ) {
144- options . replicaSet = replicaSet ;
145- }
131+ if (
132+ ! options . userSpecifiedAuthSource &&
133+ source &&
134+ options . credentials &&
135+ ! AUTH_MECHS_AUTH_SRC_EXTERNAL . has ( options . credentials . mechanism )
136+ ) {
137+ options . credentials = MongoCredentials . merge ( options . credentials , { source } ) ;
138+ }
146139
147- if ( loadBalanced === 'true' ) {
148- options . loadBalanced = true ;
149- }
140+ if ( ! options . userSpecifiedReplicaSet && replicaSet ) {
141+ options . replicaSet = replicaSet ;
142+ }
150143
151- if ( options . replicaSet && options . srvMaxHosts > 0 ) {
152- return callback ( new MongoParseError ( 'Cannot combine replicaSet option with srvMaxHosts' ) ) ;
153- }
144+ if ( loadBalanced === 'true' ) {
145+ options . loadBalanced = true ;
146+ }
154147
155- const lbError = validateLoadBalancedOptions ( hostAddresses , options , true ) ;
156- if ( lbError ) {
157- return callback ( lbError ) ;
158- }
159- }
148+ if ( options . replicaSet && options . srvMaxHosts > 0 ) {
149+ throw new MongoParseError ( 'Cannot combine replicaSet option with srvMaxHosts' ) ;
150+ }
160151
161- callback ( undefined , hostAddresses ) ;
162- } ) ;
163- } ) ;
152+ validateLoadBalancedOptions ( hostAddresses , options , true ) ;
153+
154+ return hostAddresses ;
164155}
165156
166157/**
@@ -442,10 +433,8 @@ export function parseOptions(
442433 PromiseProvider . set ( options . promiseLibrary ) ;
443434 }
444435
445- const lbError = validateLoadBalancedOptions ( hosts , mongoOptions , isSRV ) ;
446- if ( lbError ) {
447- throw lbError ;
448- }
436+ validateLoadBalancedOptions ( hosts , mongoOptions , isSRV ) ;
437+
449438 if ( mongoClient && mongoOptions . autoEncryption ) {
450439 Encrypter . checkForMongoCrypt ( ) ;
451440 mongoOptions . encrypter = new Encrypter ( mongoClient , uri , options ) ;
@@ -522,24 +511,33 @@ export function parseOptions(
522511 return mongoOptions ;
523512}
524513
514+ /**
515+ * #### Throws if LB mode is true:
516+ * - hosts contains more than one host
517+ * - there is a replicaSet name set
518+ * - directConnection is set
519+ * - if srvMaxHosts is used when an srv connection string is passed in
520+ *
521+ * @throws MongoParseError
522+ */
525523function validateLoadBalancedOptions (
526524 hosts : HostAddress [ ] | string [ ] ,
527525 mongoOptions : MongoOptions ,
528526 isSrv : boolean
529- ) : MongoParseError | undefined {
527+ ) : void {
530528 if ( mongoOptions . loadBalanced ) {
531529 if ( hosts . length > 1 ) {
532- return new MongoParseError ( LB_SINGLE_HOST_ERROR ) ;
530+ throw new MongoParseError ( LB_SINGLE_HOST_ERROR ) ;
533531 }
534532 if ( mongoOptions . replicaSet ) {
535- return new MongoParseError ( LB_REPLICA_SET_ERROR ) ;
533+ throw new MongoParseError ( LB_REPLICA_SET_ERROR ) ;
536534 }
537535 if ( mongoOptions . directConnection ) {
538- return new MongoParseError ( LB_DIRECT_CONNECTION_ERROR ) ;
536+ throw new MongoParseError ( LB_DIRECT_CONNECTION_ERROR ) ;
539537 }
540538
541539 if ( isSrv && mongoOptions . srvMaxHosts > 0 ) {
542- return new MongoParseError ( 'Cannot limit srv hosts with loadBalanced enabled' ) ;
540+ throw new MongoParseError ( 'Cannot limit srv hosts with loadBalanced enabled' ) ;
543541 }
544542 }
545543 return ;
0 commit comments