"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.runMultipleScripts = runMultipleScripts;

var _chalk = _interopRequireDefault(require("chalk"));

var _execa = _interopRequireDefault(require("execa"));

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

/**
 * Returns a listener function that prefixes
 * all lines with a certain label and writes
 * the result to the passed stream.
 *
 * The stream should not be asynchrounous, and this
 * function is currently only able to handle process.stdout
 * and process.stdin safely.
 *
 * The implementation of this function is leaned heavily
 * on concurrently's prefixing mechanism.
 * See: https://github.com/kimmobrunfeldt/concurrently/blob/master/src/logger.js#L85
 *
 * @param stream The write stream, typically process.stdout or process.stderr
 * @param prefix The label that will be prepended to each line
 */
function createStreamPrefixHandler(stream, prefix) {
  // The first line of a data chunk should
  // only be prefixed, if the last character
  // of the previous chunk ended with a new line.
  //
  // To prefix the first chunk correctly, lastChar
  // is initially set to a new line
  let lastChar = "\n";
  return data => {
    // replace some ANSI code that would impact clearing lines
    // See concurrently issue #70:
    // https://github.com/kimmobrunfeldt/concurrently/pull/70
    const text = data.toString().replace(/\u2026/g, "...");
    const lines = text // Split the current chunk by new lines to
    // modify each line individually
    .split("\n").map((line, index, array) => {
      if ( // Prefix all lines except the first and the
      // last line - which is an empty line for
      // each chunk
      index > 0 && index < array.length - 1 || // The first line should only be prefixed
      // if the last character of the previous chunk
      // was a new line
      index === 0 && lastChar === "\n") {
        // Color the prefix label using chalk
        return `${_chalk.default.dim(`${prefix} - `)}${line}`;
      } // If no prefix is added, the line is returned
      // unmodified


      return line;
    }); // Set the saved lastChar value to the last
    // character of the current text chunk to determine
    // whether the next chunk's first line needs to be prefixed

    lastChar = text[text.length - 1]; // Write all lines to the stream.
    //
    // Although stream.write is an asynchrounous method,
    // using it with process.stdout and process.stderr is
    // synchrounous and does not need to be awaited.

    stream.write(lines.join("\n"));
  };
}

async function runMultipleScripts(cwd, scripts, args) {
  // Promise.all is used here to create a
  // fail fast behavior that exits once the first
  // script run fails
  await Promise.all(scripts.map(async script => {
    var _task$stdout, _task$stderr;

    // Run scripts in silent mode to surpress
    // any npm specific output
    const npmArgs = ["run", "--silent", script];

    if (args === null || args === void 0 ? void 0 : args.length) {
      // Add two dashes ("--") in order for npm run
      // to pick up the arguments
      npmArgs.push("--", ...args);
    }

    const task = (0, _execa.default)("npm", npmArgs, {
      cwd,
      // Setting FORCE_COLOR to true
      // helps to preserve colored
      // output in a lot of scenarios,
      // even though stdio are piped
      // for these tasks
      env: {
        FORCE_COLOR: "true"
      }
    }); // Attach stream handlers that prefix
    // the outputs to stdout and stderr with
    // the script's name

    (_task$stdout = task.stdout) === null || _task$stdout === void 0 ? void 0 : _task$stdout.on("data", createStreamPrefixHandler(process.stdout, script));
    (_task$stderr = task.stderr) === null || _task$stderr === void 0 ? void 0 : _task$stderr.on("data", createStreamPrefixHandler(process.stderr, script));
    await task;
  }));
}