1- import { promisify } from ' util' ;
2- import { URL , URLSearchParams } from ' whatwg-url' ;
1+ import { promisify } from " util" ;
2+ import { URL , URLSearchParams } from " whatwg-url" ;
33
44class MongoParseError extends Error { }
55
@@ -11,114 +11,120 @@ type Options = {
1111 } ;
1212} ;
1313
14- const ALLOWED_TXT_OPTIONS : Readonly < string [ ] > = [ ' authSource' , ' replicaSet' , ' loadBalanced' ] ;
14+ const ALLOWED_TXT_OPTIONS : Readonly < string [ ] > = [ " authSource" , " replicaSet" , " loadBalanced" ] ;
1515
16- function matchesParentDomain ( srvAddress : string , parentDomain : string ) : boolean {
16+ function matchesParentDomain ( srvAddress : string , parentDomain : string ) : boolean {
1717 const regex = / ^ .* ?\. / ;
18- const srv = `.${ srvAddress . replace ( regex , '' ) } ` ;
19- const parent = `.${ parentDomain . replace ( regex , '' ) } ` ;
18+ const srv = `.${ ( srvAddress . endsWith ( "." ) ? srvAddress . slice ( 0 , - 1 ) : srvAddress ) . replace ( regex , "" ) } ` ;
19+ const parent = `.${ ( parentDomain . endsWith ( "." ) ? parentDomain . slice ( 0 , - 1 ) : parentDomain ) . replace ( regex , "" ) } ` ;
2020 return srv . endsWith ( parent ) ;
2121}
2222
23- async function resolveDnsSrvRecord ( dns : NonNullable < Options [ 'dns' ] > , lookupAddress : string , srvServiceName : string ) : Promise < string [ ] > {
23+ async function resolveDnsSrvRecord (
24+ dns : NonNullable < Options [ "dns" ] > ,
25+ lookupAddress : string ,
26+ srvServiceName : string
27+ ) : Promise < string [ ] > {
2428 const addresses = await promisify ( dns . resolveSrv ) ( `_${ srvServiceName } ._tcp.${ lookupAddress } ` ) ;
2529 if ( ! addresses ?. length ) {
26- throw new MongoParseError ( ' No addresses found at host' ) ;
30+ throw new MongoParseError ( " No addresses found at host" ) ;
2731 }
2832
2933 for ( const { name } of addresses ) {
3034 if ( ! matchesParentDomain ( name , lookupAddress ) ) {
31- throw new MongoParseError ( ' Server record does not share hostname with parent URI' ) ;
35+ throw new MongoParseError ( " Server record does not share hostname with parent URI" ) ;
3236 }
3337 }
3438
35- return addresses . map ( r => r . name + ( ( r . port ?? 27017 ) === 27017 ? '' : `:${ r . port } ` ) ) ;
39+ return addresses . map ( ( r ) => r . name + ( ( r . port ?? 27017 ) === 27017 ? "" : `:${ r . port } ` ) ) ;
3640}
3741
38- async function resolveDnsTxtRecord ( dns : NonNullable < Options [ ' dns' ] > , lookupAddress : string ) : Promise < URLSearchParams > {
42+ async function resolveDnsTxtRecord ( dns : NonNullable < Options [ " dns" ] > , lookupAddress : string ) : Promise < URLSearchParams > {
3943 let records : string [ ] [ ] | undefined ;
4044 try {
4145 records = await promisify ( dns . resolveTxt ) ( lookupAddress ) ;
4246 } catch ( err : any ) {
43- if ( err ?. code && ( err . code !== ' ENODATA' && err . code !== ' ENOTFOUND' ) ) {
47+ if ( err ?. code && err . code !== " ENODATA" && err . code !== " ENOTFOUND" ) {
4448 throw err ;
4549 }
4650 }
4751
4852 let txtRecord : string ;
4953 if ( records && records . length > 1 ) {
50- throw new MongoParseError ( ' Multiple text records not allowed' ) ;
54+ throw new MongoParseError ( " Multiple text records not allowed" ) ;
5155 } else {
52- txtRecord = records ?. [ 0 ] ?. join ( '' ) ?? '' ;
56+ txtRecord = records ?. [ 0 ] ?. join ( "" ) ?? "" ;
5357 }
5458
5559 const txtRecordOptions = new URLSearchParams ( txtRecord ) ;
5660 const txtRecordOptionKeys = [ ...txtRecordOptions . keys ( ) ] ;
57- if ( txtRecordOptionKeys . some ( key => ! ALLOWED_TXT_OPTIONS . includes ( key ) ) ) {
58- throw new MongoParseError ( `Text record must only set ${ ALLOWED_TXT_OPTIONS . join ( ', ' ) } ` ) ;
61+ if ( txtRecordOptionKeys . some ( ( key ) => ! ALLOWED_TXT_OPTIONS . includes ( key ) ) ) {
62+ throw new MongoParseError ( `Text record must only set ${ ALLOWED_TXT_OPTIONS . join ( ", " ) } ` ) ;
5963 }
6064
61- const source = txtRecordOptions . get ( ' authSource' ) ?? undefined ;
62- const replicaSet = txtRecordOptions . get ( ' replicaSet' ) ?? undefined ;
63- const loadBalanced = txtRecordOptions . get ( ' loadBalanced' ) ?? undefined ;
65+ const source = txtRecordOptions . get ( " authSource" ) ?? undefined ;
66+ const replicaSet = txtRecordOptions . get ( " replicaSet" ) ?? undefined ;
67+ const loadBalanced = txtRecordOptions . get ( " loadBalanced" ) ?? undefined ;
6468
65- if ( source === '' || replicaSet === '' || loadBalanced === '' ) {
66- throw new MongoParseError ( ' Cannot have empty URI params in DNS TXT Record' ) ;
69+ if ( source === "" || replicaSet === "" || loadBalanced === "" ) {
70+ throw new MongoParseError ( " Cannot have empty URI params in DNS TXT Record" ) ;
6771 }
6872
69- if ( loadBalanced !== undefined && loadBalanced !== 'true' && loadBalanced !== 'false' ) {
70- throw new MongoParseError ( `DNS TXT Record contains invalid value ${ loadBalanced } for loadBalanced option (allowed: true, false)` ) ;
73+ if ( loadBalanced !== undefined && loadBalanced !== "true" && loadBalanced !== "false" ) {
74+ throw new MongoParseError (
75+ `DNS TXT Record contains invalid value ${ loadBalanced } for loadBalanced option (allowed: true, false)`
76+ ) ;
7177 }
7278
7379 return txtRecordOptions ;
7480}
7581
76- async function resolveMongodbSrv ( input : string , options ?: Options ) : Promise < string > {
77- const dns = options ?. dns ?? require ( ' dns' ) ;
82+ async function resolveMongodbSrv ( input : string , options ?: Options ) : Promise < string > {
83+ const dns = options ?. dns ?? require ( " dns" ) ;
7884
79- if ( input . startsWith ( ' mongodb://' ) ) {
85+ if ( input . startsWith ( " mongodb://" ) ) {
8086 return input ;
8187 }
82- if ( ! input . startsWith ( ' mongodb+srv://' ) ) {
83- throw new MongoParseError ( ' Unknown URL scheme' ) ;
88+ if ( ! input . startsWith ( " mongodb+srv://" ) ) {
89+ throw new MongoParseError ( " Unknown URL scheme" ) ;
8490 }
8591
8692 const url = new URL ( input ) ;
8793 if ( url . port ) {
88- throw new Error ( ' mongodb+srv:// URL cannot have port number' ) ;
94+ throw new Error ( " mongodb+srv:// URL cannot have port number" ) ;
8995 }
9096
9197 const lookupAddress = url . hostname ;
92- const srvServiceName = url . searchParams . get ( ' srvServiceName' ) || ' mongodb' ;
93- const srvMaxHosts = + ( url . searchParams . get ( ' srvMaxHosts' ) || '0' ) ;
98+ const srvServiceName = url . searchParams . get ( " srvServiceName" ) || " mongodb" ;
99+ const srvMaxHosts = + ( url . searchParams . get ( " srvMaxHosts" ) || "0" ) ;
94100
95101 const [ srvResult , txtResult ] = await Promise . all ( [
96102 resolveDnsSrvRecord ( dns , lookupAddress , srvServiceName ) ,
97- resolveDnsTxtRecord ( dns , lookupAddress )
103+ resolveDnsTxtRecord ( dns , lookupAddress ) ,
98104 ] ) ;
99105
100106 if ( srvMaxHosts && srvMaxHosts < srvResult . length ) {
101107 // Replace srvResult with shuffled + limited srvResult
102108 srvResult . splice ( 0 , srvResult . length , ...shuffle ( srvResult , srvMaxHosts ) ) ;
103109 }
104110
105- url . protocol = ' mongodb:' ;
106- url . hostname = ' __DUMMY_HOSTNAME__' ;
111+ url . protocol = " mongodb:" ;
112+ url . hostname = " __DUMMY_HOSTNAME__" ;
107113 if ( ! url . pathname ) {
108- url . pathname = '/' ;
114+ url . pathname = "/" ;
109115 }
110116 for ( const [ key , value ] of txtResult ) {
111117 if ( ! url . searchParams . has ( key ) ) {
112118 url . searchParams . set ( key , value ) ;
113119 }
114120 }
115- if ( ! url . searchParams . has ( ' tls' ) && ! url . searchParams . has ( ' ssl' ) ) {
116- url . searchParams . set ( ' tls' , ' true' ) ;
121+ if ( ! url . searchParams . has ( " tls" ) && ! url . searchParams . has ( " ssl" ) ) {
122+ url . searchParams . set ( " tls" , " true" ) ;
117123 }
118- url . searchParams . delete ( ' srvServiceName' ) ;
119- url . searchParams . delete ( ' srvMaxHosts' ) ;
124+ url . searchParams . delete ( " srvServiceName" ) ;
125+ url . searchParams . delete ( " srvMaxHosts" ) ;
120126
121- return url . toString ( ) . replace ( ' __DUMMY_HOSTNAME__' , srvResult . join ( ',' ) ) ;
127+ return url . toString ( ) . replace ( " __DUMMY_HOSTNAME__" , srvResult . join ( "," ) ) ;
122128}
123129
124130/**
@@ -129,7 +135,7 @@ async function resolveMongodbSrv (input: string, options?: Options): Promise<str
129135 * @param sequence - items to be shuffled
130136 * @param limit - Defaults to `0`. If nonzero shuffle will slice the randomized array e.g, `.slice(0, limit)` otherwise will return the entire randomized array.
131137 */
132- function shuffle < T > ( sequence : Iterable < T > , limit = 0 ) : Array < T > {
138+ function shuffle < T > ( sequence : Iterable < T > , limit = 0 ) : Array < T > {
133139 const items = Array . from ( sequence ) ; // shallow copy in order to never shuffle the input
134140
135141 limit = Math . min ( limit , items . length ) ;
0 commit comments