diff --git a/lib/internal/main/watch_mode.js b/lib/internal/main/watch_mode.js index bf70f7606f5e03..225436661f5e56 100644 --- a/lib/internal/main/watch_mode.js +++ b/lib/internal/main/watch_mode.js @@ -34,7 +34,10 @@ markBootstrapComplete(); const kKillSignal = convertToValidSignal(getOptionValue('--watch-kill-signal')); const kShouldFilterModules = getOptionValue('--watch-path').length === 0; -const kEnvFile = getOptionValue('--env-file') || getOptionValue('--env-file-if-exists'); +const kEnvFiles = [ + ...getOptionValue('--env-file'), + ...getOptionValue('--env-file-if-exists'), +]; const kWatchedPaths = ArrayPrototypeMap(getOptionValue('--watch-path'), (path) => resolve(path)); const kPreserveOutput = getOptionValue('--watch-preserve-output'); const kCommand = ArrayPrototypeSlice(process.argv, 1); @@ -100,8 +103,8 @@ function start() { }, }); watcher.watchChildProcessModules(child); - if (kEnvFile) { - watcher.filterFile(resolve(kEnvFile)); + if (kEnvFiles.length > 0) { + ArrayPrototypeForEach(kEnvFiles, (file) => watcher.filterFile(resolve(file))); } child.once('exit', (code) => { exited = true; diff --git a/src/node_options.h b/src/node_options.h index 79b90d59014cb9..41d4718f011a69 100644 --- a/src/node_options.h +++ b/src/node_options.h @@ -185,8 +185,8 @@ class EnvironmentOptions : public Options { #endif // HAVE_INSPECTOR std::string redirect_warnings; std::string diagnostic_dir; - std::string env_file; - std::string optional_env_file; + std::vector env_file; + std::vector optional_env_file; bool has_env_file_string = false; bool test_runner = false; uint64_t test_runner_concurrency = 0; diff --git a/test/parallel/test-dotenv-edge-cases.js b/test/parallel/test-dotenv-edge-cases.js index 084265e80a68a4..aa5c5f548f1376 100644 --- a/test/parallel/test-dotenv-edge-cases.js +++ b/test/parallel/test-dotenv-edge-cases.js @@ -39,6 +39,17 @@ describe('.env supports edge cases', () => { }))); }); + it('should not support comma-separated env files', async () => { + const code = 'assert.strictEqual(1, 1)'; + const child = await common.spawnPromisified( + process.execPath, + [`--env-file=${validEnvFilePath},${nodeOptionsEnvFilePath}`, '--eval', code], + { cwd: __dirname }, + ); + assert.notStrictEqual(child.stderr, ''); + assert.strictEqual(child.code, 9); + }); + it('supports absolute paths', async () => { const code = ` assert.strictEqual(process.env.BASIC, 'basic'); diff --git a/test/sequential/test-watch-mode.mjs b/test/sequential/test-watch-mode.mjs index b0318f3505c66a..dc7ccf6cf6d2e7 100644 --- a/test/sequential/test-watch-mode.mjs +++ b/test/sequential/test-watch-mode.mjs @@ -860,4 +860,28 @@ process.on('message', (message) => { `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, ]); }); + + it('should support multiple --env-file flags', async () => { + const envKey = `TEST_ENV_A_${Date.now()}`; + const envKey2 = `TEST_ENV_B_${Date.now()}`; + const jsFile = createTmpFile(`console.log('ENV_A: ' + process.env.${envKey} + '\\n' + 'ENV_B: ' + process.env.${envKey2});`); + const envFileA = createTmpFile(`${envKey}=123`, '.env'); + const envFileB = createTmpFile(`${envKey2}=456`, '.env'); + const { done, restart } = runInBackground({ + args: ['--watch', `--env-file=${envFileA}`, `--env-file=${envFileB}`, jsFile] + }); + + try { + const { stderr, stdout } = await restart(); + + assert.strictEqual(stderr, ''); + assert.deepStrictEqual(stdout, [ + 'ENV_A: 123', + 'ENV_B: 456', + `Completed running ${inspect(jsFile)}. Waiting for file changes before restarting...`, + ]); + } finally { + await done(); + } + }); });