@@ -213,12 +213,14 @@ export class Config {
213213
214214 get serverExtraEnv ( ) : Env {
215215 const extraEnv =
216- this . get < { [ key : string ] : string | number } | null > ( "server.extraEnv" ) ?? { } ;
216+ this . get < { [ key : string ] : { toString ( ) : string } | null } | null > (
217+ "server.extraEnv" ,
218+ ) ?? { } ;
217219 return substituteVariablesInEnv (
218220 Object . fromEntries (
219221 Object . entries ( extraEnv ) . map ( ( [ k , v ] ) => [
220222 k ,
221- typeof v !== "string" ? v . toString ( ) : v ,
223+ v !== null && typeof v !== "string" ? v . toString ( ) : v ,
222224 ] ) ,
223225 ) ,
224226 ) ;
@@ -398,22 +400,24 @@ export function prepareVSCodeConfig<T>(resp: T): T {
398400
399401// FIXME: Merge this with `substituteVSCodeVariables` above
400402export function substituteVariablesInEnv ( env : Env ) : Env {
403+ const depRe = new RegExp ( / \$ { (?< depName > .+ ?) } / g) ;
401404 const missingDeps = new Set < string > ( ) ;
402405 // vscode uses `env:ENV_NAME` for env vars resolution, and it's easier
403406 // to follow the same convention for our dependency tracking
404407 const definedEnvKeys = new Set ( Object . keys ( env ) . map ( ( key ) => `env:${ key } ` ) ) ;
405408 const envWithDeps = Object . fromEntries (
406409 Object . entries ( env ) . map ( ( [ key , value ] ) => {
407410 const deps = new Set < string > ( ) ;
408- const depRe = new RegExp ( / \$ { (?< depName > .+ ?) } / g) ;
409- let match = undefined ;
410- while ( ( match = depRe . exec ( value ) ) ) {
411- const depName = unwrapUndefinable ( match . groups ?. [ "depName" ] ) ;
412- deps . add ( depName ) ;
413- // `depName` at this point can have a form of `expression` or
414- // `prefix:expression`
415- if ( ! definedEnvKeys . has ( depName ) ) {
416- missingDeps . add ( depName ) ;
411+ if ( value ) {
412+ let match = undefined ;
413+ while ( ( match = depRe . exec ( value ) ) ) {
414+ const depName = unwrapUndefinable ( match . groups ?. [ "depName" ] ) ;
415+ deps . add ( depName ) ;
416+ // `depName` at this point can have a form of `expression` or
417+ // `prefix:expression`
418+ if ( ! definedEnvKeys . has ( depName ) ) {
419+ missingDeps . add ( depName ) ;
420+ }
417421 }
418422 }
419423 return [ `env:${ key } ` , { deps : [ ...deps ] , value } ] ;
@@ -454,12 +458,12 @@ export function substituteVariablesInEnv(env: Env): Env {
454458 do {
455459 leftToResolveSize = toResolve . size ;
456460 for ( const key of toResolve ) {
457- const item = unwrapUndefinable ( envWithDeps [ key ] ) ;
458- if ( item . deps . every ( ( dep ) => resolved . has ( dep ) ) ) {
459- item . value = item . value . replace ( / \$ { (?< depName > . + ? ) } / g , ( _wholeMatch , depName ) => {
460- const item = unwrapUndefinable ( envWithDeps [ depName ] ) ;
461- return item . value ;
462- } ) ;
461+ const item = envWithDeps [ key ] ;
462+ if ( item && item . deps . every ( ( dep ) => resolved . has ( dep ) ) ) {
463+ item . value =
464+ item . value ?. replace ( / \$ { (?< depName > . + ? ) } / g , ( _wholeMatch , depName ) => {
465+ return envWithDeps [ depName ] ? .value ?? "" ;
466+ } ) ?? null ;
463467 resolved . add ( key ) ;
464468 toResolve . delete ( key ) ;
465469 }
0 commit comments