1import chalk from 'chalk';
2
3import logger from '../Logger';
4import { Package } from '../Packages';
5import { spawnAsync } from '../Utils';
6
7const { cyan, gray, red, reset } = chalk;
8
9/**
10 * Executes the specified script (defined in package.json under "scripts") on the given package.
11 */
12export default async function runPackageScriptAsync(
13  pkg: Package,
14  scriptName: string,
15  args: string[] = []
16): Promise<void> {
17  if (!pkg.scripts[scriptName]) {
18    // Package doesn't have such script.
19    logger.debug(`��‍♂️ ${cyan(scriptName)} script not found`);
20    return;
21  }
22  const spawnArgs = [scriptName, ...args];
23
24  logger.log(`��‍♀️ Running ${cyan.italic(`yarn ${spawnArgs.join(' ')}`)}`);
25
26  try {
27    await spawnAsync('yarn', spawnArgs, {
28      stdio: 'pipe',
29      cwd: pkg.path,
30    });
31  } catch (error) {
32    logger.error(`${cyan(scriptName)} script failed, see process output:`);
33    consoleErrorOutput(error.stdout, 'stdout >', reset);
34    consoleErrorOutput(error.stderr, 'stderr >', red);
35
36    // Rethrow error so we can count how many checks failed
37    throw error;
38  }
39}
40
41function consoleErrorOutput(output: string, label: string, color: (string) => string): void {
42  const lines = output.trim().split(/\r\n?|\n/g);
43  logger.log(lines.map((line) => `${gray(label)} ${color(line)}`).join('\n'));
44}
45