diff --git a/packages/cli/src/commands/app/serve.ts b/packages/cli/src/commands/app/serve.ts index 418e1e9e86..22775242ca 100644 --- a/packages/cli/src/commands/app/serve.ts +++ b/packages/cli/src/commands/app/serve.ts @@ -14,8 +14,7 @@ * limitations under the License. */ -import { spawn } from 'child_process'; -import { waitForExit } from 'lib/run'; +import { run } from 'lib/run'; import { createLogFunc } from 'lib/logging'; import { watchDeps } from 'lib/watchDeps'; @@ -23,18 +22,12 @@ export default async () => { // Start dynamic watch and build of dependencies, then serve the app await watchDeps({ build: true }); - const child = spawn('react-scripts', ['start'], { + await run('react-scripts', ['start'], { env: { - FORCE_COLOR: 'true', EXTEND_ESLINT: 'true', SKIP_PREFLIGHT_CHECK: 'true', - ...process.env, }, - stdio: ['inherit', 'pipe', 'inherit'], - shell: true, + // We need to avoid clearing the terminal, or the build feedback of dependencies will be lost + stdoutLogFunc: createLogFunc(process.stdout), }); - - // We need to avoid clearing the terminal, or the build feedback of dependencies will be lost - child.stdout.on('data', createLogFunc(process.stdout)); - await waitForExit(child); }; diff --git a/packages/cli/src/commands/watch-deps/index.ts b/packages/cli/src/commands/watch-deps/index.ts index 9645dec5fa..ec9e4be58f 100644 --- a/packages/cli/src/commands/watch-deps/index.ts +++ b/packages/cli/src/commands/watch-deps/index.ts @@ -14,9 +14,8 @@ * limitations under the License. */ -import { spawn } from 'child_process'; import { Command } from 'commander'; -import { waitForExit } from 'lib/run'; +import { run } from 'lib/run'; import { createLogPipe } from 'lib/logging'; import { watchDeps, Options } from 'lib/watchDeps'; @@ -39,17 +38,12 @@ export default async (cmd: Command, args: string[]) => { await watchDeps(options); if (args?.length) { - const child = spawn(args[0], args.slice(1), { - env: { FORCE_COLOR: 'true', ...process.env }, - stdio: ['inherit', 'pipe', 'pipe'], - shell: true, - }); - // Use log pipe to avoid clearing the terminal const logPipe = createLogPipe(); - child.stdout.on('data', logPipe(process.stdout)); - child.stderr.on('data', logPipe(process.stderr)); - await waitForExit(child); + await run(args[0], args.slice(1), { + stdoutLogFunc: logPipe(process.stdout), + stderrLogFunc: logPipe(process.stderr), + }); } }; diff --git a/packages/cli/src/lib/run.ts b/packages/cli/src/lib/run.ts index cbeb2c080c..9eac69e673 100644 --- a/packages/cli/src/lib/run.ts +++ b/packages/cli/src/lib/run.ts @@ -22,10 +22,15 @@ import { } from 'child_process'; import { ExitCodeError } from './errors'; import { promisify } from 'util'; +import { LogFunc } from './logging'; const exec = promisify(execCb); type SpawnOptionsPartialEnv = Omit & { env?: Partial; + // Pipe stdout to this log function + stdoutLogFunc?: LogFunc; + // Pipe stderr to this log function + stderrLogFunc?: LogFunc; }; // Runs a child command, returning a promise that is only resolved if the child exits with code 0. @@ -34,19 +39,33 @@ export async function run( args: string[] = [], options: SpawnOptionsPartialEnv = {}, ) { + const { stdoutLogFunc, stderrLogFunc } = options; const env: NodeJS.ProcessEnv = { ...process.env, FORCE_COLOR: 'true', ...(options.env ?? {}), }; + const stdio = [ + 'inherit', + stdoutLogFunc ? 'pipe' : 'inherit', + stderrLogFunc ? 'pipe' : 'inherit', + ] as ('inherit' | 'pipe')[]; + const child = spawn(name, args, { - stdio: 'inherit', + stdio, shell: true, ...options, env, }); + if (stdoutLogFunc && child.stdout) { + child.stdout.on('data', stdoutLogFunc); + } + if (stderrLogFunc && child.stderr) { + child.stderr.on('data', stderrLogFunc); + } + await waitForExit(child, name); }