src/index.js
function concurrent(scripts) {
  const {colors, scripts: quotedScripts, names} = Object.keys(scripts)
    .reduce(reduceScripts, {
      colors: [],
      scripts: [],
      names: [],
    })
  const flags = [
    '--kill-others-on-fail',
    `--prefix-colors "${colors.join(',')}"`,
    '--prefix "[{name}]"',
    `--names "${names.join(',')}"`,
    shellEscape(quotedScripts),
  ]
  const concurrently = runBin('concurrently')
  return `${concurrently} ${flags.join(' ')}`

  function reduceScripts(accumulator, scriptName, index) {
    let scriptObj = scripts[scriptName]
    if (!scriptObj) {
      return accumulator
    } else if (typeof scriptObj === 'string') {
      scriptObj = {script: scriptObj}
    }
    const {
      script,
      color = defaultColors[index % defaultColors.length],
    } = scriptObj
    if (!script) {
      return accumulator
    }
    accumulator.names.push(scriptName)
    accumulator.colors.push(color)
    accumulator.scripts.push(script)
    return accumulator
  }
}
function concurrent(scripts) {
  const {colors, scripts: quotedScripts, names} = Object.keys(scripts)
    .reduce(reduceScripts, {
      colors: [],
      scripts: [],
      names: [],
    })
  const flags = [
    '--kill-others-on-fail',
    `--prefix-colors "${colors.join(',')}"`,
    '--prefix "[{name}]"',
    `--names "${names.join(',')}"`,
    shellEscape(quotedScripts),
  ]
  const concurrently = runBin('concurrently')
  return `${concurrently} ${flags.join(' ')}`

  function reduceScripts(accumulator, scriptName, index) {
    let scriptObj = scripts[scriptName]
    if (!scriptObj) {
      return accumulator
    } else if (typeof scriptObj === 'string') {
      scriptObj = {script: scriptObj}
    }
    const {
      script,
      color = defaultColors[index % defaultColors.length],
    } = scriptObj
    if (!script) {
      return accumulator
    }
    accumulator.names.push(scriptName)
    accumulator.colors.push(color)
    accumulator.scripts.push(script)
    return accumulator
  }
}
function concurrent ( scripts ) { const { colors , scripts : quotedScripts , names } = Object . keys ( scripts ) . reduce ( reduceScripts , { colors : [ ] , scripts : [ ] , names : [ ] , } ) const flags = [ '--kill-others-on-fail' , ` ${ colors . join ( ',' ) } ` , '--prefix "[{name}]"' , ` ${ names . join ( ',' ) } ` , shellEscape ( quotedScripts ) , ] const concurrently = runBin ( 'concurrently' ) return ` ${ concurrently } ${ flags . join ( ' ' ) } ` function reduceScripts ( accumulator , scriptName , index ) { let scriptObj = scripts [ scriptName ] if ( ! scriptObj ) { return accumulator } else if ( typeof scriptObj === 'string' ) { scriptObj = { script : scriptObj } } const { script , color = defaultColors [ index % defaultColors . length ] , } = scriptObj if ( ! script ) { return accumulator } accumulator . names . push ( scriptName ) accumulator . colors . push ( color ) accumulator . scripts . push ( script ) return accumulator } }
A concurrent script object
@typedef {Object|string} ConcurrentScript
@property {string} script - the command to run
@property {string} color - the color to use
(see concurrently's docs for valid values)
 
An object of concurrent script objects
@typedef {Object.<ConcurrentScript>} ConcurrentScripts
 
Generates a command that uses `concurrently` to run
scripts concurrently. Adds a few flags to make it
behave as you probably want (like --kill-others-on-fail).
In addition, it adds color and labels where the color
can be specified or is defaulted and the label is based
on the key for the script.
@param {ConcurrentScripts} scripts - the scripts to run
note: this function filters out falsy values :)
@example
// returns a bit of a long script that can vary slightly
// based on your environment... :)
concurrent({
lint: {
script: 'eslint .',
color: 'bgGreen.white.dim',
},
test: 'jest',
build: {
script: 'webpack'
}
})
@return {string} - the command to run
A concurrent script object