@@ -4,21 +4,34 @@ import argv from "yargs-parser";
44
55import  packageJson  from  "../package.json"  with  {  type : "json"  } ; 
66import  fs  from  "fs" ; 
7+ import  {  ReadConcernLevel ,  ReadPreferenceMode ,  W  }  from  "mongodb" ; 
78const  {  localDataPath,  configPath }  =  getLocalDataPath ( ) ; 
89
910// If we decide to support non-string config options, we'll need to extend the mechanism for parsing 
1011// env variables. 
11- interface  UserConfig  extends   Record < string ,   string   |   undefined >   { 
12+ interface  UserConfig  { 
1213    apiBaseUrl : string ; 
1314    clientId : string ; 
1415    stateFile : string ; 
1516    connectionString ?: string ; 
17+     connectOptions : { 
18+         readConcern : ReadConcernLevel ; 
19+         readPreference : ReadPreferenceMode ; 
20+         writeConcern : W ; 
21+         timeoutMS : number ; 
22+     } ; 
1623} 
1724
1825const  defaults : UserConfig  =  { 
1926    apiBaseUrl : "https://cloud.mongodb.com/" , 
2027    clientId : "0oabtxactgS3gHIR0297" , 
2128    stateFile : path . join ( localDataPath ,  "state.json" ) , 
29+     connectOptions : { 
30+         readConcern : "local" , 
31+         readPreference : "secondaryPreferred" , 
32+         writeConcern : "majority" , 
33+         timeoutMS : 30_000 , 
34+     } , 
2235} ; 
2336
2437const  mergedUserConfig  =  { 
@@ -66,21 +79,52 @@ function getLocalDataPath(): { localDataPath: string; configPath: string } {
6679// are prefixed with `MDB_MCP_` and the keys match the UserConfig keys, but are converted 
6780// to SNAKE_UPPER_CASE. 
6881function  getEnvConfig ( ) : Partial < UserConfig >  { 
69-     const  camelCaseToSNAKE_UPPER_CASE  =  ( str : string ) : string  =>  { 
70-         return  str . replace ( / ( [ a - z ] ) ( [ A - Z ] ) / g,  "$1_$2" ) . toUpperCase ( ) ; 
71-     } ; 
82+     function  setValue ( obj : Record < string ,  unknown > ,  path : string [ ] ,  value : string ) : void { 
83+         const  currentField  =  path . shift ( ) ! ; 
84+         if  ( path . length  ===  0 )  { 
85+             const  numberValue  =  Number ( value ) ; 
86+             if  ( ! isNaN ( numberValue ) )  { 
87+                 obj [ currentField ]  =  numberValue ; 
88+                 return ; 
89+             } 
90+ 
91+             const  booleanValue  =  value . toLocaleLowerCase ( ) ; 
92+             if  ( booleanValue  ===  "true"  ||  booleanValue  ===  "false" )  { 
93+                 obj [ currentField ]  =  booleanValue  ===  "true" ; 
94+                 return ; 
95+             } 
96+ 
97+             obj [ currentField ]  =  value ; 
98+             return ; 
99+         } 
72100
73-     const  result : Partial < UserConfig >  =  { } ; 
74-     for  ( const  key  of  Object . keys ( defaults ) )  { 
75-         const  envVarName  =  `MDB_MCP_${ camelCaseToSNAKE_UPPER_CASE ( key ) }  ; 
76-         if  ( process . env [ envVarName ] )  { 
77-             result [ key ]  =  process . env [ envVarName ] ; 
101+         if  ( ! obj [ currentField ] )  { 
102+             obj [ currentField ]  =  { } ; 
78103        } 
104+ 
105+         setValue ( obj [ currentField ]  as  Record < string ,  unknown > ,  path ,  value ) ; 
106+     } 
107+ 
108+     const  result : Record < string ,  unknown >  =  { } ; 
109+     const  mcpVariables  =  Object . entries ( process . env ) . filter ( 
110+         ( [ key ,  value ] )  =>  value  !==  undefined  &&  key . startsWith ( "MDB_MCP_" ) 
111+     )  as  [ string ,  string ] [ ] ; 
112+     for  ( const  [ key ,  value ]  of  mcpVariables )  { 
113+         const  fieldPath  =  key 
114+             . replace ( "MDB_MCP_" ,  "" ) 
115+             . split ( "." ) 
116+             . map ( ( part )  =>  SNAKE_CASE_toCamelCase ( part ) ) ; 
117+ 
118+         setValue ( result ,  fieldPath ,  value ) ; 
79119    } 
80120
81121    return  result ; 
82122} 
83123
124+ function  SNAKE_CASE_toCamelCase ( str : string ) : string  { 
125+     return  str . toLowerCase ( ) . replace ( / ( [ - _ ] [ a - z ] ) / g,  ( group )  =>  group . toUpperCase ( ) . replace ( "_" ,  "" ) ) ; 
126+ } 
127+ 
84128// Gets the config supplied by the user as a JSON file. The file is expected to be located in the local data path 
85129// and named `config.json`. 
86130function  getFileConfig ( ) : Partial < UserConfig >  { 
0 commit comments