1
1
import { readFileSync , writeFileSync } from 'fs' ;
2
- import * as dotenv from 'dotenv' ;
2
+ import { config as loadDotEnvFile } from 'dotenv' ;
3
3
import { ChildProcess , fork , Serializable } from 'child_process' ;
4
4
import * as chalk from 'chalk' ;
5
5
import * as logTransformer from 'strong-log-transformer' ;
@@ -301,8 +301,6 @@ export class ForkedProcessTaskRunner {
301
301
// region Environment Variables
302
302
private getEnvVariablesForProcess ( ) {
303
303
return {
304
- // Start With Dotenv Variables
305
- ...this . getDotenvVariablesForForkedProcess ( ) ,
306
304
// User Process Env Variables override Dotenv Variables
307
305
...process . env ,
308
306
// Nx Env Variables overrides everything
@@ -318,11 +316,15 @@ export class ForkedProcessTaskRunner {
318
316
outputPath : string ,
319
317
streamOutput : boolean
320
318
) {
319
+ // Unload any dot env files at the root of the workspace that were loaded on init of Nx.
320
+ const taskEnv = this . unloadDotEnvFiles ( { ...process . env } ) ;
321
+
321
322
const res = {
322
323
// Start With Dotenv Variables
323
- ...this . getDotenvVariablesForTask ( task ) ,
324
- // User Process Env Variables override Dotenv Variables
325
- ...process . env ,
324
+ ...( process . env . NX_LOAD_DOT_ENV_FILES === 'true'
325
+ ? this . loadDotEnvFilesForTask ( task , taskEnv )
326
+ : // If not loading dot env files, ensure env vars created by system are still loaded
327
+ taskEnv ) ,
326
328
// Nx Env Variables overrides everything
327
329
...this . getNxEnvVariablesForTask (
328
330
task ,
@@ -397,57 +399,76 @@ export class ForkedProcessTaskRunner {
397
399
} ;
398
400
}
399
401
400
- private getDotenvVariablesForForkedProcess ( ) {
401
- return {
402
- ...parseEnv ( '.env' ) ,
403
- ...parseEnv ( '.local.env' ) ,
404
- ...parseEnv ( '.env.local' ) ,
405
- } ;
402
+ private loadDotEnvFilesForTask (
403
+ task : Task ,
404
+ environmentVariables : NodeJS . ProcessEnv
405
+ ) {
406
+ // Collect dot env files that may pertain to a task
407
+ const dotEnvFiles = [
408
+ // Load DotEnv Files for a configuration in the project root
409
+ ...( task . target . configuration
410
+ ? [
411
+ `${ task . projectRoot } /.env.${ task . target . target } .${ task . target . configuration } ` ,
412
+ `${ task . projectRoot } /.env.${ task . target . configuration } ` ,
413
+ `${ task . projectRoot } /.${ task . target . target } .${ task . target . configuration } .env` ,
414
+ `${ task . projectRoot } /.${ task . target . configuration } .env` ,
415
+ ]
416
+ : [ ] ) ,
417
+
418
+ // Load DotEnv Files for a target in the project root
419
+ `${ task . projectRoot } /.env.${ task . target . target } ` ,
420
+ `${ task . projectRoot } /.${ task . target . target } .env` ,
421
+ `${ task . projectRoot } /.env.local` ,
422
+ `${ task . projectRoot } /.local.env` ,
423
+ `${ task . projectRoot } /.env` ,
424
+
425
+ // Load DotEnv Files for a configuration in the workspace root
426
+ ...( task . target . configuration
427
+ ? [
428
+ `.env.${ task . target . target } .${ task . target . configuration } ` ,
429
+ `.env.${ task . target . configuration } ` ,
430
+ `.${ task . target . target } .${ task . target . configuration } .env` ,
431
+ `.${ task . target . configuration } .env` ,
432
+ ]
433
+ : [ ] ) ,
434
+
435
+ // Load DotEnv Files for a target in the workspace root
436
+ `.env.${ task . target . target } ` ,
437
+ `.${ task . target . target } .env` ,
438
+
439
+ // Load base DotEnv Files at workspace root
440
+ `.env` ,
441
+ `.local.env` ,
442
+ `.env.local` ,
443
+ ] ;
444
+
445
+ for ( const file of dotEnvFiles ) {
446
+ loadDotEnvFile ( {
447
+ path : file ,
448
+ processEnv : environmentVariables ,
449
+ // Do not override existing env variables as we load
450
+ override : false ,
451
+ } ) ;
452
+ }
453
+
454
+ return environmentVariables ;
406
455
}
407
456
408
- private getDotenvVariablesForTask ( task : Task ) {
409
- if ( process . env . NX_LOAD_DOT_ENV_FILES == 'true' ) {
410
- return {
411
- ...this . getDotenvVariablesForForkedProcess ( ) ,
412
- ...parseEnv ( `.${ task . target . target } .env` ) ,
413
- ...parseEnv ( `.env.${ task . target . target } ` ) ,
414
- ...( task . target . configuration
415
- ? {
416
- ...parseEnv ( `.${ task . target . configuration } .env` ) ,
417
- ...parseEnv (
418
- `.${ task . target . target } .${ task . target . configuration } .env`
419
- ) ,
420
- ...parseEnv ( `.env.${ task . target . configuration } ` ) ,
421
- ...parseEnv (
422
- `.env.${ task . target . target } .${ task . target . configuration } `
423
- ) ,
424
- }
425
- : { } ) ,
426
- ...parseEnv ( `${ task . projectRoot } /.env` ) ,
427
- ...parseEnv ( `${ task . projectRoot } /.local.env` ) ,
428
- ...parseEnv ( `${ task . projectRoot } /.env.local` ) ,
429
- ...parseEnv ( `${ task . projectRoot } /.${ task . target . target } .env` ) ,
430
- ...parseEnv ( `${ task . projectRoot } /.env.${ task . target . target } ` ) ,
431
- ...( task . target . configuration
432
- ? {
433
- ...parseEnv (
434
- `${ task . projectRoot } /.${ task . target . configuration } .env`
435
- ) ,
436
- ...parseEnv (
437
- `${ task . projectRoot } /.${ task . target . target } .${ task . target . configuration } .env`
438
- ) ,
439
- ...parseEnv (
440
- `${ task . projectRoot } /.env.${ task . target . configuration } `
441
- ) ,
442
- ...parseEnv (
443
- `${ task . projectRoot } /.env.${ task . target . target } .${ task . target . configuration } `
444
- ) ,
445
- }
446
- : { } ) ,
447
- } ;
448
- } else {
449
- return { } ;
457
+ private unloadDotEnvFiles ( environmentVariables : NodeJS . ProcessEnv ) {
458
+ const unloadDotEnvFile = ( filename : string ) => {
459
+ let parsedDotEnvFile : NodeJS . ProcessEnv = { } ;
460
+ loadDotEnvFile ( { path : filename , processEnv : parsedDotEnvFile } ) ;
461
+ Object . keys ( parsedDotEnvFile ) . forEach ( ( envVarKey ) => {
462
+ if ( environmentVariables [ envVarKey ] === parsedDotEnvFile [ envVarKey ] ) {
463
+ delete environmentVariables [ envVarKey ] ;
464
+ }
465
+ } ) ;
466
+ } ;
467
+
468
+ for ( const file of [ '.env' , '.local.env' , '.env.local' ] ) {
469
+ unloadDotEnvFile ( file ) ;
450
470
}
471
+ return environmentVariables ;
451
472
}
452
473
453
474
// endregion Environment Variables
@@ -507,13 +528,6 @@ export class ForkedProcessTaskRunner {
507
528
}
508
529
}
509
530
510
- function parseEnv ( path : string ) {
511
- try {
512
- const envContents = readFileSync ( path ) ;
513
- return dotenv . parse ( envContents ) ;
514
- } catch ( e ) { }
515
- }
516
-
517
531
const colors = [
518
532
chalk . green ,
519
533
chalk . greenBright ,
0 commit comments