| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent e218b7c commit 4d8b53e
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -33,6 +33,7 @@ markBootstrapComplete(); | |||
| 33 | 33 | // TODO(MoLow): Make kill signal configurable | |
| 34 | 34 | const kKillSignal = 'SIGTERM'; | |
| 35 | 35 | const kShouldFilterModules = getOptionValue('--watch-path').length === 0; | |
| 36 | + const kEnvFile = getOptionValue('--env-file'); | ||
| 36 | 37 | const kWatchedPaths = ArrayPrototypeMap(getOptionValue('--watch-path'), (path) => resolve(path)); | |
| 37 | 38 | const kPreserveOutput = getOptionValue('--watch-preserve-output'); | |
| 38 | 39 | const kCommand = ArrayPrototypeSlice(process.argv, 1); | |
@@ -73,6 +74,9 @@ function start() { | |||
| 73 | 74 | }, | |
| 74 | 75 | }); | |
| 75 | 76 | watcher.watchChildProcessModules(child); | |
| 77 | + if (kEnvFile) { | ||
| 78 | + watcher.filterFile(resolve(kEnvFile)); | ||
| 79 | + } | ||
| 76 | 80 | child.once('exit', (code) => { | |
| 77 | 81 | exited = true; | |
| 78 | 82 | if (code === 0) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -379,7 +379,10 @@ MaybeLocal<Value> StartExecution(Environment* env, StartExecutionCallback cb) { | |||
| 379 | 379 | } | |
| 380 | 380 | #endif | |
| 381 | 381 | ||
| 382 | - if (env->options()->has_env_file_string) { | ||
| 382 | + // Ignore env file if we're in watch mode. | ||
| 383 | + // Without it env is not updated when restarting child process. | ||
| 384 | + // Child process has --watch flag removed, so it will load the file. | ||
| 385 | + if (env->options()->has_env_file_string && !env->options()->watch_mode) { | ||
| 383 | 386 | per_process::dotenv_file.SetEnvironment(env); | |
| 384 | 387 | } | |
| 385 | 388 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -30,6 +30,66 @@ function createTmpFile(content = 'console.log("running");', ext = '.js', basenam | |||
| 30 | 30 | return file; | |
| 31 | 31 | } | |
| 32 | 32 | ||
| 33 | + function runInBackground({ args = [], options = {}, completed = 'Completed running', shouldFail = false }) { | ||
| 34 | + let future = Promise.withResolvers(); | ||
| 35 | + let child; | ||
| 36 | + let stderr = ''; | ||
| 37 | + let stdout = []; | ||
| 38 | + | ||
| 39 | + const run = () => { | ||
| 40 | + args.unshift('--no-warnings'); | ||
| 41 | + child = spawn(execPath, args, { encoding: 'utf8', stdio: 'pipe', ...options }); | ||
| 42 | + | ||
| 43 | + child.stderr.on('data', (data) => { | ||
| 44 | + stderr += data; | ||
| 45 | + }); | ||
| 46 | + | ||
| 47 | + const rl = createInterface({ input: child.stdout }); | ||
| 48 | + rl.on('line', (data) => { | ||
| 49 | + if (!data.startsWith('Waiting for graceful termination') && !data.startsWith('Gracefully restarted')) { | ||
| 50 | + stdout.push(data); | ||
| 51 | + if (data.startsWith(completed)) { | ||
| 52 | + future.resolve({ stderr, stdout }); | ||
| 53 | + future = Promise.withResolvers(); | ||
| 54 | + stdout = []; | ||
| 55 | + stderr = ''; | ||
| 56 | + } else if (data.startsWith('Failed running')) { | ||
| 57 | + if (shouldFail) { | ||
| 58 | + future.resolve({ stderr, stdout }); | ||
| 59 | + } else { | ||
| 60 | + future.reject({ stderr, stdout }); | ||
| 61 | + } | ||
| 62 | + future = Promise.withResolvers(); | ||
| 63 | + stdout = []; | ||
| 64 | + stderr = ''; | ||
| 65 | + } | ||
| 66 | + } | ||
| 67 | + }); | ||
| 68 | + }; | ||
| 69 | + | ||
| 70 | + return { | ||
| 71 | + async done() { | ||
| 72 | + child?.kill(); | ||
| 73 | + future.resolve(); | ||
| 74 | + return { stdout, stderr }; | ||
| 75 | + }, | ||
| 76 | + restart(timeout = 1000) { | ||
| 77 | + if (!child) { | ||
| 78 | + run(); | ||
| 79 | + } | ||
| 80 | + const timer = setTimeout(() => { | ||
| 81 | + if (!future.resolved) { | ||
| 82 | + child.kill(); | ||
| 83 | + future.reject(new Error('Timed out waiting for restart')); | ||
| 84 | + } | ||
| 85 | + }, timeout); | ||
| 86 | + return future.promise.finally(() => { | ||
| 87 | + clearTimeout(timer); | ||
| 88 | + }); | ||
| 89 | + } | ||
| 90 | + }; | ||
| 91 | + } | ||
| 92 | + | ||
| 33 | 93 | async function runWriteSucceed({ | |
| 34 | 94 | file, | |
| 35 | 95 | watchedFile, | |
@@ -132,6 +192,56 @@ describe('watch mode', { concurrency: !process.env.TEST_PARALLEL, timeout: 60_00 | |||
| 132 | 192 | ]); | |
| 133 | 193 | }); | |
| 134 | 194 | ||
| 195 | + it('should reload env variables when --env-file changes', async () => { | ||
| 196 | + const envKey = `TEST_ENV_${Date.now()}`; | ||
| 197 | + const jsFile = createTmpFile(`console.log('ENV: ' + process.env.${envKey});`); | ||
| 198 | + const envFile = createTmpFile(`${envKey}=value1`, '.env'); | ||
| 199 | + const { done, restart } = runInBackground({ args: ['--watch', `--env-file=${envFile}`, jsFile] }); | ||
| 200 | + | ||
| 201 | + try { | ||
| 202 | + await restart(); | ||
| 203 | + writeFileSync(envFile, `${envKey}=value2`); | ||
| 204 | + | ||
| 205 | + // Second restart, after env change | ||
| 206 | + const { stdout, stderr } = await restart(); | ||
| 207 | + | ||
| 208 | + assert.strictEqual(stderr, ''); | ||
| 209 | + assert.deepStrictEqual(stdout, [ | ||
| 210 | + `Restarting ${inspect(jsFile)}`, | ||
| 211 | + 'ENV: value2', | ||
| 212 | + `Completed running ${inspect(jsFile)}`, | ||
| 213 | + ]); | ||
| 214 | + } finally { | ||
| 215 | + await done(); | ||
| 216 | + } | ||
| 217 | + }); | ||
| 218 | + | ||
| 219 | + it('should load new env variables when --env-file changes', async () => { | ||
| 220 | + const envKey = `TEST_ENV_${Date.now()}`; | ||
| 221 | + const envKey2 = `TEST_ENV_2_${Date.now()}`; | ||
| 222 | + const jsFile = createTmpFile(`console.log('ENV: ' + process.env.${envKey} + '\\n' + 'ENV2: ' + process.env.${envKey2});`); | ||
| 223 | + const envFile = createTmpFile(`${envKey}=value1`, '.env'); | ||
| 224 | + const { done, restart } = runInBackground({ args: ['--watch', `--env-file=${envFile}`, jsFile] }); | ||
| 225 | + | ||
| 226 | + try { | ||
| 227 | + await restart(); | ||
| 228 | + await writeFileSync(envFile, `${envKey}=value1\n${envKey2}=newValue`); | ||
| 229 | + | ||
| 230 | + // Second restart, after env change | ||
| 231 | + const { stderr, stdout } = await restart(); | ||
| 232 | + | ||
| 233 | + assert.strictEqual(stderr, ''); | ||
| 234 | + assert.deepStrictEqual(stdout, [ | ||
| 235 | + `Restarting ${inspect(jsFile)}`, | ||
| 236 | + 'ENV: value1', | ||
| 237 | + 'ENV2: newValue', | ||
| 238 | + `Completed running ${inspect(jsFile)}`, | ||
| 239 | + ]); | ||
| 240 | + } finally { | ||
| 241 | + await done(); | ||
| 242 | + } | ||
| 243 | + }); | ||
| 244 | + | ||
| 135 | 245 | it('should watch changes to a failing file', async () => { | |
| 136 | 246 | const file = createTmpFile('throw new Error("fails");'); | |
| 137 | 247 | const { stderr, stdout } = await runWriteSucceed({ | |
| Back | FazBrowse Home | New Git URL |
0 commit comments