concurrently.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. #!/usr/bin/env node
  2. const fs = require('fs');
  3. const yargs = require('yargs');
  4. const defaults = require('../src/defaults');
  5. const concurrently = require('../index');
  6. const args = yargs
  7. .usage('$0 [options] <command ...>')
  8. .help('h')
  9. .alias('h', 'help')
  10. .version('v', require('../package.json').version)
  11. .alias('v', 'V')
  12. .alias('v', 'version')
  13. .options({
  14. // General
  15. 'm': {
  16. alias: 'max-processes',
  17. describe:
  18. 'How many processes should run at once.\n' +
  19. 'New processes only spawn after all restart tries of a process.',
  20. type: 'number'
  21. },
  22. 'n': {
  23. alias: 'names',
  24. describe:
  25. 'List of custom names to be used in prefix template.\n' +
  26. 'Example names: "main,browser,server"',
  27. type: 'string'
  28. },
  29. 'name-separator': {
  30. describe:
  31. 'The character to split <names> on. Example usage:\n' +
  32. 'concurrently -n "styles|scripts|server" --name-separator "|"',
  33. default: defaults.nameSeparator,
  34. },
  35. 's': {
  36. alias: 'success',
  37. describe:
  38. 'Return exit code of zero or one based on the success or failure ' +
  39. 'of the "first" child to terminate, the "last child", or succeed ' +
  40. 'only if "all" child processes succeed.',
  41. choices: ['first', 'last', 'all'],
  42. default: defaults.success
  43. },
  44. 'r': {
  45. alias: 'raw',
  46. describe:
  47. 'Output only raw output of processes, disables prettifying ' +
  48. 'and concurrently coloring.',
  49. type: 'boolean'
  50. },
  51. // This one is provided for free. Chalk reads this itself and removes colours.
  52. // https://www.npmjs.com/package/chalk#chalksupportscolor
  53. 'no-color': {
  54. describe: 'Disables colors from logging',
  55. type: 'boolean'
  56. },
  57. // Kill others
  58. 'k': {
  59. alias: 'kill-others',
  60. describe: 'kill other processes if one exits or dies',
  61. type: 'boolean'
  62. },
  63. 'kill-others-on-fail': {
  64. describe: 'kill other processes if one exits with non zero status code',
  65. type: 'boolean'
  66. },
  67. // Prefix
  68. 'p': {
  69. alias: 'prefix',
  70. describe:
  71. 'Prefix used in logging for each process.\n' +
  72. 'Possible values: index, pid, time, command, name, none, or a template. ' +
  73. 'Example template: "{time}-{pid}"',
  74. defaultDescription: 'index or name (when --names is set)',
  75. type: 'string'
  76. },
  77. 'c': {
  78. alias: 'prefix-colors',
  79. describe:
  80. 'Comma-separated list of chalk colors to use on prefixes. ' +
  81. 'If there are more commands than colors, the last color will be repeated.\n' +
  82. '- Available modifiers: reset, bold, dim, italic, underline, inverse, hidden, strikethrough\n' +
  83. '- Available colors: black, red, green, yellow, blue, magenta, cyan, white, gray \n' +
  84. 'or any hex values for colors, eg #23de43\n' +
  85. '- Available background colors: bgBlack, bgRed, bgGreen, bgYellow, bgBlue, bgMagenta, bgCyan, bgWhite\n' +
  86. 'See https://www.npmjs.com/package/chalk for more information.',
  87. default: defaults.prefixColors,
  88. type: 'string'
  89. },
  90. 'l': {
  91. alias: 'prefix-length',
  92. describe:
  93. 'Limit how many characters of the command is displayed in prefix. ' +
  94. 'The option can be used to shorten the prefix when it is set to "command"',
  95. default: defaults.prefixLength,
  96. type: 'number'
  97. },
  98. 't': {
  99. alias: 'timestamp-format',
  100. describe: 'Specify the timestamp in moment/date-fns format.',
  101. default: defaults.timestampFormat,
  102. type: 'string'
  103. },
  104. // Restarting
  105. 'restart-tries': {
  106. describe:
  107. 'How many times a process that died should restart.\n' +
  108. 'Negative numbers will make the process restart forever.',
  109. default: defaults.restartTries,
  110. type: 'number'
  111. },
  112. 'restart-after': {
  113. describe: 'Delay time to respawn the process, in milliseconds.',
  114. default: defaults.restartDelay,
  115. type: 'number'
  116. },
  117. // Input
  118. 'i': {
  119. alias: 'handle-input',
  120. describe:
  121. 'Whether input should be forwarded to the child processes. ' +
  122. 'See examples for more information.',
  123. type: 'boolean'
  124. },
  125. 'default-input-target': {
  126. default: defaults.defaultInputTarget,
  127. describe:
  128. 'Identifier for child process to which input on stdin ' +
  129. 'should be sent if not specified at start of input.\n' +
  130. 'Can be either the index or the name of the process.'
  131. }
  132. })
  133. .group(['m', 'n', 'name-separator', 'raw', 's', 'no-color'], 'General')
  134. .group(['p', 'c', 'l', 't'], 'Prefix styling')
  135. .group(['i', 'default-input-target'], 'Input handling')
  136. .group(['k', 'kill-others-on-fail'], 'Killing other processes')
  137. .group(['restart-tries', 'restart-after'], 'Restarting')
  138. // Too much text to write as JS strings, .txt file is better
  139. .epilogue(fs.readFileSync(__dirname + '/epilogue.txt', { encoding: 'utf8' }))
  140. .argv;
  141. const prefixColors = args.prefixColors.split(',');
  142. const names = (args.names || '').split(args.nameSeparator);
  143. let lastColor;
  144. concurrently(args._.map((command, index) => {
  145. // Use documented behaviour of repeating last colour when specifying more commands than colours
  146. lastColor = prefixColors[index] || lastColor;
  147. return {
  148. command,
  149. prefixColor: lastColor,
  150. name: names[index]
  151. };
  152. }), {
  153. inputStream: args.handleInput && process.stdin,
  154. defaultInputTarget: args.defaultInputTarget,
  155. killOthers: args.killOthers
  156. ? ['success', 'failure']
  157. : (args.killOthersOnFail ? ['failure'] : []),
  158. maxProcesses: args.maxProcesses,
  159. raw: args.raw,
  160. prefix: args.prefix,
  161. prefixLength: args.prefixLength,
  162. restartDelay: args.restartAfter,
  163. restartTries: args.restartTries,
  164. successCondition: args.success,
  165. timestampFormat: args.timestampFormat
  166. }).then(
  167. () => process.exit(0),
  168. () => process.exit(1)
  169. );