concurrently 7.3.0 → 7.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -57,6 +57,9 @@ npm install concurrently --save
57
57
 
58
58
  ## Usage
59
59
 
60
+ > **Note**
61
+ > The `concurrently` command is now also available under the shorthand alias `conc`.
62
+
60
63
  Remember to surround separate commands with quotes:
61
64
 
62
65
  ```bash
@@ -149,8 +152,8 @@ General
149
152
  template.
150
153
  Example names: "main,browser,server" [string]
151
154
  --name-separator The character to split <names> on. Example usage:
152
- concurrently -n "styles|scripts|server"
153
- --name-separator "|" [default: ","]
155
+ -n "styles|scripts|server" --name-separator "|"
156
+ [default: ","]
154
157
  -s, --success Which command(s) must exit with code 0 in order
155
158
  for concurrently exit with code 0 too. Options
156
159
  are:
@@ -188,8 +191,9 @@ Prefix styling
188
191
  - Available modifiers: reset, bold, dim, italic,
189
192
  underline, inverse, hidden, strikethrough
190
193
  - Available colors: black, red, green, yellow, blue,
191
- magenta, cyan, white, gray
192
- or any hex values for colors, eg #23de43
194
+ magenta, cyan, white, gray,
195
+ any hex values for colors (e.g. #23de43) or auto for
196
+ an automatically picked color
193
197
  - Available background colors: bgBlack, bgRed,
194
198
  bgGreen, bgYellow, bgBlue, bgMagenta, bgCyan, bgWhite
195
199
  See https://www.npmjs.com/package/chalk for more
@@ -247,6 +251,14 @@ Examples:
247
251
  $ concurrently --names "HTTP,WATCH" -c "bgBlue.bold,bgMagenta.bold"
248
252
  "http-server" "npm run watch"
249
253
 
254
+ - Auto varying colored prefixes
255
+
256
+ $ concurrently -c "auto" "npm run watch" "http-server"
257
+
258
+ - Mixing auto and manual colored prefixes
259
+
260
+ $ concurrently -c "red,auto" "npm run watch" "http-server" "echo hello"
261
+
250
262
  - Configuring via environment variables with CONCURRENTLY_ prefix
251
263
 
252
264
  $ CONCURRENTLY_RAW=true CONCURRENTLY_KILL_OTHERS=true concurrently "echo
@@ -321,12 +333,12 @@ For more details, visit https://github.com/open-cli-tools/concurrently
321
333
  - `prefix`: the prefix type to use when logging processes output.
322
334
  Possible values: `index`, `pid`, `time`, `command`, `name`, `none`, or a template (eg `[{time} process: {pid}]`).
323
335
  Default: the name of the process, or its index if no name is set.
324
- - `prefixColors`: a list of colors as supported by [chalk](https://www.npmjs.com/package/chalk).
325
- If concurrently would run more commands than there are colors, the last color is repeated.
336
+ - `prefixColors`: a list of colors as supported by [chalk](https://www.npmjs.com/package/chalk) or `auto` for an automatically picked color.
337
+ If concurrently would run more commands than there are colors, the last color is repeated, unless if the last color value is `auto` which means following colors are automatically picked to vary.
326
338
  Prefix colors specified per-command take precedence over this list.
327
339
  - `prefixLength`: how many characters to show when prefixing with `command`. Default: `10`
328
340
  - `raw`: whether raw mode should be used, meaning strictly process output will
329
- be logged, without any prefixes, colouring or extra stuff.
341
+ be logged, without any prefixes, coloring or extra stuff.
330
342
  - `successCondition`: the condition to consider the run was successful.
331
343
  If `first`, only the first process to exit will make up the success of the run; if `last`, the last process that exits will determine whether the run succeeds.
332
344
  Anything else means all processes should exit successfully.
@@ -35,7 +35,7 @@ const epilogue_1 = require("./epilogue");
35
35
  // Clean-up arguments (yargs expects only the arguments after the program name)
36
36
  const cleanArgs = (0, helpers_1.hideBin)(process.argv);
37
37
  // Find argument separator (double dash)
38
- const argsSepIdx = cleanArgs.findIndex(arg => arg === '--');
38
+ const argsSepIdx = cleanArgs.findIndex((arg) => arg === '--');
39
39
  // Arguments before separator
40
40
  const argsBeforeSep = argsSepIdx >= 0 ? cleanArgs.slice(0, argsSepIdx) : cleanArgs;
41
41
  // Arguments after separator
@@ -65,7 +65,7 @@ const args = (0, yargs_1.default)(argsBeforeSep)
65
65
  },
66
66
  'name-separator': {
67
67
  describe: 'The character to split <names> on. Example usage:\n' +
68
- 'concurrently -n "styles|scripts|server" --name-separator "|"',
68
+ '-n "styles|scripts|server" --name-separator "|"',
69
69
  default: defaults.nameSeparator,
70
70
  },
71
71
  success: {
@@ -87,7 +87,7 @@ const args = (0, yargs_1.default)(argsBeforeSep)
87
87
  'and concurrently coloring.',
88
88
  type: 'boolean',
89
89
  },
90
- // This one is provided for free. Chalk reads this itself and removes colours.
90
+ // This one is provided for free. Chalk reads this itself and removes colors.
91
91
  // https://www.npmjs.com/package/chalk#chalksupportscolor
92
92
  'no-color': {
93
93
  describe: 'Disables colors from logging',
@@ -140,8 +140,8 @@ const args = (0, yargs_1.default)(argsBeforeSep)
140
140
  describe: 'Comma-separated list of chalk colors to use on prefixes. ' +
141
141
  'If there are more commands than colors, the last color will be repeated.\n' +
142
142
  '- Available modifiers: reset, bold, dim, italic, underline, inverse, hidden, strikethrough\n' +
143
- '- Available colors: black, red, green, yellow, blue, magenta, cyan, white, gray \n' +
144
- 'or any hex values for colors, eg #23de43\n' +
143
+ '- Available colors: black, red, green, yellow, blue, magenta, cyan, white, gray, \n' +
144
+ 'any hex values for colors (e.g. #23de43) or auto for an automatically picked color\n' +
145
145
  '- Available background colors: bgBlack, bgRed, bgGreen, bgYellow, bgBlue, bgMagenta, bgCyan, bgWhite\n' +
146
146
  'See https://www.npmjs.com/package/chalk for more information.',
147
147
  default: defaults.prefixColors,
@@ -20,6 +20,14 @@ const examples = [
20
20
  description: 'Custom names and colored prefixes',
21
21
  example: '$ $0 --names "HTTP,WATCH" -c "bgBlue.bold,bgMagenta.bold" "http-server" "npm run watch"',
22
22
  },
23
+ {
24
+ description: 'Auto varying colored prefixes',
25
+ example: '$ $0 -c "auto" "npm run watch" "http-server"',
26
+ },
27
+ {
28
+ description: 'Mixing auto and manual colored prefixes',
29
+ example: '$ $0 -c "red,auto" "npm run watch" "http-server" "echo hello"',
30
+ },
23
31
  {
24
32
  description: 'Configuring via environment variables with CONCURRENTLY_ prefix',
25
33
  example: '$ CONCURRENTLY_RAW=true CONCURRENTLY_KILL_OTHERS=true $0 "echo hello" "echo world"',
@@ -69,7 +77,7 @@ const examplesString = examples
69
77
  ` - ${description}`,
70
78
  example
71
79
  .split('\n')
72
- .map(line => ` ${line}`)
80
+ .map((line) => ` ${line}`)
73
81
  .join('\n'),
74
82
  ].join('\n\n'))
75
83
  .join('\n\n');
@@ -42,7 +42,7 @@ class ExpandNpmWildcard {
42
42
  const wildcardRegex = new RegExp(`^${preWildcard}(.*?)${postWildcard}$`);
43
43
  const currentName = commandInfo.name || '';
44
44
  return this.scripts
45
- .map(script => {
45
+ .map((script) => {
46
46
  const match = script.match(wildcardRegex);
47
47
  if (omissionRegex) {
48
48
  const toOmit = script.match(new RegExp(omissionRegex[1]));
@@ -27,7 +27,7 @@ export interface CommandInfo {
27
27
  */
28
28
  cwd?: string;
29
29
  /**
30
- * Color to use on prefix of command.
30
+ * Color to use on prefix of the command.
31
31
  */
32
32
  prefixColor?: string;
33
33
  }
@@ -57,7 +57,7 @@ class Command {
57
57
  const startDate = new Date(Date.now());
58
58
  const highResStartTime = process.hrtime();
59
59
  this.timer.next({ startDate });
60
- Rx.fromEvent(child, 'error').subscribe(event => {
60
+ Rx.fromEvent(child, 'error').subscribe((event) => {
61
61
  this.process = undefined;
62
62
  const endDate = new Date(Date.now());
63
63
  this.timer.next({ startDate, endDate });
@@ -100,5 +100,5 @@ exports.Command = Command;
100
100
  * Pipes all events emitted by `stream` into `subject`.
101
101
  */
102
102
  function pipeTo(stream, subject) {
103
- stream.subscribe(event => subject.next(event));
103
+ stream.subscribe((event) => subject.next(event));
104
104
  }
@@ -53,11 +53,11 @@ class CompletionListener {
53
53
  const targetCommandsEvents = events.filter(({ command, index }) => command.name === nameOrIndex || index === Number(nameOrIndex));
54
54
  if (this.successCondition.startsWith('!')) {
55
55
  // All commands except the specified ones must exit succesfully
56
- return events.every(event => targetCommandsEvents.includes(event) || event.exitCode === 0);
56
+ return events.every((event) => targetCommandsEvents.includes(event) || event.exitCode === 0);
57
57
  }
58
58
  // Only the specified commands must exit succesfully
59
59
  return (targetCommandsEvents.length > 0 &&
60
- targetCommandsEvents.every(event => event.exitCode === 0));
60
+ targetCommandsEvents.every((event) => event.exitCode === 0));
61
61
  }
62
62
  /**
63
63
  * Given a list of commands, wait for all of them to exit and then evaluate their exit codes.
@@ -65,8 +65,8 @@ class CompletionListener {
65
65
  * @returns A Promise that resolves if the success condition is met, or rejects otherwise.
66
66
  */
67
67
  listen(commands) {
68
- const closeStreams = commands.map(command => command.close);
69
- return Rx.lastValueFrom(Rx.merge(...closeStreams).pipe((0, operators_1.bufferCount)(closeStreams.length), (0, operators_1.switchMap)(exitInfos => this.isSuccess(exitInfos)
68
+ const closeStreams = commands.map((command) => command.close);
69
+ return Rx.lastValueFrom(Rx.merge(...closeStreams).pipe((0, operators_1.bufferCount)(closeStreams.length), (0, operators_1.switchMap)((exitInfos) => this.isSuccess(exitInfos)
70
70
  ? Rx.of(exitInfos, this.scheduler)
71
71
  : Rx.throwError(exitInfos, this.scheduler)), (0, operators_1.take)(1)));
72
72
  }
@@ -16,6 +16,7 @@ const strip_quotes_1 = require("./command-parser/strip-quotes");
16
16
  const completion_listener_1 = require("./completion-listener");
17
17
  const get_spawn_opts_1 = require("./get-spawn-opts");
18
18
  const output_writer_1 = require("./output-writer");
19
+ const prefix_color_selector_1 = require("./prefix-color-selector");
19
20
  const defaults = {
20
21
  spawn: spawn_command_1.default,
21
22
  kill: tree_kill_1.default,
@@ -33,6 +34,7 @@ function concurrently(baseCommands, baseOptions) {
33
34
  assert_1.default.ok(Array.isArray(baseCommands), '[concurrently] commands should be an array');
34
35
  assert_1.default.notStrictEqual(baseCommands.length, 0, '[concurrently] no commands provided');
35
36
  const options = lodash_1.default.defaults(baseOptions, defaults);
37
+ const prefixColorSelector = new prefix_color_selector_1.PrefixColorSelector(options.prefixColors);
36
38
  const commandParsers = [
37
39
  new strip_quotes_1.StripQuotes(),
38
40
  new expand_npm_shortcut_1.ExpandNpmShortcut(),
@@ -41,16 +43,13 @@ function concurrently(baseCommands, baseOptions) {
41
43
  if (options.additionalArguments) {
42
44
  commandParsers.push(new expand_arguments_1.ExpandArguments(options.additionalArguments));
43
45
  }
44
- let lastColor = '';
45
46
  let commands = (0, lodash_1.default)(baseCommands)
46
47
  .map(mapToCommandInfo)
47
- .flatMap(command => parseCommand(command, commandParsers))
48
+ .flatMap((command) => parseCommand(command, commandParsers))
48
49
  .map((command, index) => {
49
- // Use documented behaviour of repeating last color when specifying more commands than colors
50
- lastColor = (options.prefixColors && options.prefixColors[index]) || lastColor;
51
50
  return new command_1.Command({
52
51
  index,
53
- prefixColor: lastColor,
52
+ prefixColor: prefixColorSelector.getNextColor(),
54
53
  ...command,
55
54
  }, (0, get_spawn_opts_1.getSpawnOpts)({
56
55
  raw: options.raw,
@@ -83,7 +82,7 @@ function concurrently(baseCommands, baseOptions) {
83
82
  const result = new completion_listener_1.CompletionListener({ successCondition: options.successCondition })
84
83
  .listen(commands)
85
84
  .finally(() => {
86
- handleResult.onFinishCallbacks.forEach(onFinish => onFinish());
85
+ handleResult.onFinishCallbacks.forEach((onFinish) => onFinish());
87
86
  });
88
87
  return {
89
88
  result,
@@ -113,7 +112,7 @@ function mapToCommandInfo(command) {
113
112
  };
114
113
  }
115
114
  function parseCommand(command, parsers) {
116
- return parsers.reduce((commands, parser) => lodash_1.default.flatMap(commands, command => parser.parse(command)), lodash_1.default.castArray(command));
115
+ return parsers.reduce((commands, parser) => lodash_1.default.flatMap(commands, (command) => parser.parse(command)), lodash_1.default.castArray(command));
117
116
  }
118
117
  function maybeRunMore(commandsLeft) {
119
118
  const command = commandsLeft.shift();
@@ -25,9 +25,6 @@ export declare class InputHandler implements FlowController {
25
25
  });
26
26
  handle(commands: Command[]): {
27
27
  commands: Command[];
28
- onFinish?: undefined;
29
- } | {
30
- commands: Command[];
31
- onFinish: () => void;
28
+ onFinish?: () => void | undefined;
32
29
  };
33
30
  }
@@ -48,12 +48,12 @@ class InputHandler {
48
48
  return { commands };
49
49
  }
50
50
  Rx.fromEvent(this.inputStream, 'data')
51
- .pipe((0, operators_1.map)(data => data.toString()))
52
- .subscribe(data => {
51
+ .pipe((0, operators_1.map)((data) => data.toString()))
52
+ .subscribe((data) => {
53
53
  const dataParts = data.split(/:(.+)/);
54
54
  const targetId = dataParts.length > 1 ? dataParts[0] : this.defaultInputTarget;
55
55
  const input = dataParts[1] || data;
56
- const command = commands.find(command => command.name === targetId ||
56
+ const command = commands.find((command) => command.name === targetId ||
57
57
  command.index.toString() === targetId.toString());
58
58
  if (command && command.stdin) {
59
59
  command.stdin.write(input);
@@ -12,15 +12,15 @@ class KillOnSignal {
12
12
  }
13
13
  handle(commands) {
14
14
  let caughtSignal;
15
- ['SIGINT', 'SIGTERM', 'SIGHUP'].forEach(signal => {
15
+ ['SIGINT', 'SIGTERM', 'SIGHUP'].forEach((signal) => {
16
16
  this.process.on(signal, () => {
17
17
  caughtSignal = signal;
18
- commands.forEach(command => command.kill(signal));
18
+ commands.forEach((command) => command.kill(signal));
19
19
  });
20
20
  });
21
21
  return {
22
- commands: commands.map(command => {
23
- const closeStream = command.close.pipe((0, operators_1.map)(exitInfo => {
22
+ commands: commands.map((command) => {
23
+ const closeStream = command.close.pipe((0, operators_1.map)((exitInfo) => {
24
24
  const exitCode = caughtSignal === 'SIGINT' ? 0 : exitInfo.exitCode;
25
25
  return { ...exitInfo, exitCode };
26
26
  }));
@@ -15,16 +15,16 @@ class KillOthers {
15
15
  this.conditions = lodash_1.default.castArray(conditions);
16
16
  }
17
17
  handle(commands) {
18
- const conditions = this.conditions.filter(condition => condition === 'failure' || condition === 'success');
18
+ const conditions = this.conditions.filter((condition) => condition === 'failure' || condition === 'success');
19
19
  if (!conditions.length) {
20
20
  return { commands };
21
21
  }
22
- const closeStates = commands.map(command => command.close.pipe((0, operators_1.map)(({ exitCode }) => exitCode === 0 ? 'success' : 'failure'), (0, operators_1.filter)(state => conditions.includes(state))));
23
- closeStates.forEach(closeState => closeState.subscribe(() => {
24
- const killableCommands = commands.filter(command => command.killable);
22
+ const closeStates = commands.map((command) => command.close.pipe((0, operators_1.map)(({ exitCode }) => exitCode === 0 ? 'success' : 'failure'), (0, operators_1.filter)((state) => conditions.includes(state))));
23
+ closeStates.forEach((closeState) => closeState.subscribe(() => {
24
+ const killableCommands = commands.filter((command) => command.killable);
25
25
  if (killableCommands.length) {
26
26
  this.logger.logGlobalEvent('Sending SIGTERM to other processes..');
27
- killableCommands.forEach(command => command.kill());
27
+ killableCommands.forEach((command) => command.kill());
28
28
  }
29
29
  }));
30
30
  return { commands };
@@ -9,7 +9,7 @@ class LogError {
9
9
  this.logger = logger;
10
10
  }
11
11
  handle(commands) {
12
- commands.forEach(command => command.error.subscribe(event => {
12
+ commands.forEach((command) => command.error.subscribe((event) => {
13
13
  this.logger.logCommandEvent(`Error occurred when executing command: ${command.command}`, command);
14
14
  const errorText = String(event instanceof Error ? event.stack || event : event);
15
15
  this.logger.logCommandEvent(errorText, command);
@@ -9,7 +9,7 @@ class LogExit {
9
9
  this.logger = logger;
10
10
  }
11
11
  handle(commands) {
12
- commands.forEach(command => command.close.subscribe(({ exitCode }) => {
12
+ commands.forEach((command) => command.close.subscribe(({ exitCode }) => {
13
13
  this.logger.logCommandEvent(`${command.command} exited with code ${exitCode}`, command);
14
14
  }));
15
15
  return { commands };
@@ -9,9 +9,9 @@ class LogOutput {
9
9
  this.logger = logger;
10
10
  }
11
11
  handle(commands) {
12
- commands.forEach(command => {
13
- command.stdout.subscribe(text => this.logger.logCommandText(text.toString(), command));
14
- command.stderr.subscribe(text => this.logger.logCommandText(text.toString(), command));
12
+ commands.forEach((command) => {
13
+ command.stdout.subscribe((text) => this.logger.logCommandText(text.toString(), command));
14
+ command.stderr.subscribe((text) => this.logger.logCommandText(text.toString(), command));
15
15
  });
16
16
  return { commands };
17
17
  }
@@ -65,7 +65,7 @@ class LogTimings {
65
65
  return { commands };
66
66
  }
67
67
  // individual process timings
68
- commands.forEach(command => {
68
+ commands.forEach((command) => {
69
69
  command.timer.subscribe(({ startDate, endDate }) => {
70
70
  if (!endDate) {
71
71
  const formattedStartDate = (0, format_1.default)(startDate, this.timestampFormat);
@@ -79,9 +79,9 @@ class LogTimings {
79
79
  });
80
80
  });
81
81
  // overall summary timings
82
- const closeStreams = commands.map(command => command.close);
82
+ const closeStreams = commands.map((command) => command.close);
83
83
  const allProcessesClosed = Rx.merge(...closeStreams).pipe((0, operators_1.bufferCount)(closeStreams.length), (0, operators_1.take)(1));
84
- allProcessesClosed.subscribe(exitInfos => this.printExitInfoTimingTable(exitInfos));
84
+ allProcessesClosed.subscribe((exitInfos) => this.printExitInfoTimingTable(exitInfos));
85
85
  return { commands };
86
86
  }
87
87
  }
@@ -43,7 +43,7 @@ class RestartProcess {
43
43
  return { commands };
44
44
  }
45
45
  commands
46
- .map(command => command.close.pipe((0, operators_1.take)(this.tries), (0, operators_1.takeWhile)(({ exitCode }) => exitCode !== 0)))
46
+ .map((command) => command.close.pipe((0, operators_1.take)(this.tries), (0, operators_1.takeWhile)(({ exitCode }) => exitCode !== 0)))
47
47
  .map((failure, index) => Rx.merge(
48
48
  // Delay the emission (so that the restarts happen on time),
49
49
  // explicitly telling the subscriber that a restart is needed
@@ -51,7 +51,7 @@ class RestartProcess {
51
51
  // Skip the first N emissions (as these would be duplicates of the above),
52
52
  // meaning it will be empty because of success, or failed all N times,
53
53
  // and no more restarts should be attempted.
54
- failure.pipe((0, operators_1.skip)(this.tries), (0, operators_1.mapTo)(false), (0, operators_1.defaultIfEmpty)(false))).subscribe(restart => {
54
+ failure.pipe((0, operators_1.skip)(this.tries), (0, operators_1.mapTo)(false), (0, operators_1.defaultIfEmpty)(false))).subscribe((restart) => {
55
55
  const command = commands[index];
56
56
  if (restart) {
57
57
  this.logger.logCommandEvent(`${command.command} restarted`, command);
@@ -59,7 +59,7 @@ class RestartProcess {
59
59
  }
60
60
  }));
61
61
  return {
62
- commands: commands.map(command => {
62
+ commands: commands.map((command) => {
63
63
  const closeStream = command.close.pipe((0, operators_1.filter)(({ exitCode }, emission) => {
64
64
  // We let all success codes pass, and failures only after restarting won't happen again
65
65
  return exitCode === 0 || emission >= this.tries;
@@ -71,4 +71,4 @@ export declare type ConcurrentlyOptions = BaseConcurrentlyOptions & {
71
71
  };
72
72
  declare const _default: (commands: ConcurrentlyCommandInput[], options?: Partial<ConcurrentlyOptions>) => ConcurrentlyResult;
73
73
  export default _default;
74
- export { concurrently, ConcurrentlyCommandInput, ConcurrentlyResult, Logger, Command, CloseEvent, TimerEvent, CommandIdentifier, FlowController, InputHandler, KillOnSignal, KillOthers, LogError, LogExit, LogOutput, LogTimings, RestartProcess, };
74
+ export { CloseEvent, Command, CommandIdentifier, concurrently, ConcurrentlyCommandInput, ConcurrentlyResult, FlowController, InputHandler, KillOnSignal, KillOthers, LogError, LogExit, Logger, LogOutput, LogTimings, RestartProcess, TimerEvent, };
package/dist/src/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RestartProcess = exports.LogTimings = exports.LogOutput = exports.LogExit = exports.LogError = exports.KillOthers = exports.KillOnSignal = exports.InputHandler = exports.Command = exports.Logger = exports.concurrently = void 0;
3
+ exports.RestartProcess = exports.LogTimings = exports.LogOutput = exports.Logger = exports.LogExit = exports.LogError = exports.KillOthers = exports.KillOnSignal = exports.InputHandler = exports.concurrently = exports.Command = void 0;
4
4
  const command_1 = require("./command");
5
5
  Object.defineProperty(exports, "Command", { enumerable: true, get: function () { return command_1.Command; } });
6
6
  const concurrently_1 = require("./concurrently");
@@ -28,8 +28,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
29
  exports.Logger = void 0;
30
30
  const chalk_1 = __importDefault(require("chalk"));
31
- const lodash_1 = __importDefault(require("lodash"));
32
31
  const format_1 = __importDefault(require("date-fns/format"));
32
+ const lodash_1 = __importDefault(require("lodash"));
33
33
  const Rx = __importStar(require("rxjs"));
34
34
  const defaults = __importStar(require("./defaults"));
35
35
  class Logger {
@@ -43,7 +43,7 @@ class Logger {
43
43
  // keep in the list of commands to hide only strings with some length.
44
44
  // This might happen through the CLI when no `--hide` argument is specified, for example.
45
45
  this.hide = lodash_1.default.castArray(hide)
46
- .filter(name => name || name === 0)
46
+ .filter((name) => name || name === 0)
47
47
  .map(String);
48
48
  this.raw = raw;
49
49
  this.prefixFormat = prefixFormat;
@@ -137,9 +137,9 @@ class Logger {
137
137
  }
138
138
  let nextColIndex = 0;
139
139
  const headers = {};
140
- const contentRows = tableContents.map(row => {
140
+ const contentRows = tableContents.map((row) => {
141
141
  const rowContents = [];
142
- Object.keys(row).forEach(col => {
142
+ Object.keys(row).forEach((col) => {
143
143
  if (!headers[col]) {
144
144
  headers[col] = {
145
145
  index: nextColIndex++,
@@ -155,16 +155,16 @@ class Logger {
155
155
  });
156
156
  return rowContents;
157
157
  });
158
- const headersFormatted = Object.keys(headers).map(header => header.padEnd(headers[header].length, ' '));
158
+ const headersFormatted = Object.keys(headers).map((header) => header.padEnd(headers[header].length, ' '));
159
159
  if (!headersFormatted.length) {
160
160
  // No columns exist.
161
161
  return;
162
162
  }
163
- const borderRowFormatted = headersFormatted.map(header => '─'.padEnd(header.length, '─'));
163
+ const borderRowFormatted = headersFormatted.map((header) => '─'.padEnd(header.length, '─'));
164
164
  this.logGlobalEvent(`┌─${borderRowFormatted.join('─┬─')}─┐`);
165
165
  this.logGlobalEvent(`│ ${headersFormatted.join(' │ ')} │`);
166
166
  this.logGlobalEvent(`├─${borderRowFormatted.join('─┼─')}─┤`);
167
- contentRows.forEach(contentRow => {
167
+ contentRows.forEach((contentRow) => {
168
168
  const contentRowFormatted = headersFormatted.map((header, colIndex) => {
169
169
  // If the table was expanded after this row was processed, it won't have this column.
170
170
  // Use an empty string in this case.
@@ -35,7 +35,7 @@ class OutputWriter {
35
35
  this.group = group;
36
36
  this.buffers = commands.map(() => []);
37
37
  if (this.group) {
38
- Rx.merge(...commands.map(c => c.close)).subscribe(command => {
38
+ Rx.merge(...commands.map((c) => c.close)).subscribe((command) => {
39
39
  if (command.index !== this.activeCommandIndex) {
40
40
  return;
41
41
  }
@@ -64,7 +64,7 @@ class OutputWriter {
64
64
  }
65
65
  }
66
66
  flushBuffer(index) {
67
- this.buffers[index].forEach(t => this.outputStream.write(t));
67
+ this.buffers[index].forEach((t) => this.outputStream.write(t));
68
68
  this.buffers[index] = [];
69
69
  }
70
70
  }
@@ -0,0 +1,11 @@
1
+ import chalk from 'chalk';
2
+ export declare class PrefixColorSelector {
3
+ private colorGenerator;
4
+ constructor(customColors?: string[]);
5
+ /** A list of colors that are readable in a terminal. */
6
+ static get ACCEPTABLE_CONSOLE_COLORS(): ("stderr" | keyof chalk.Chalk | "supportsColor" | "Level" | "Color" | "ForegroundColor" | "BackgroundColor" | "Modifiers")[];
7
+ /**
8
+ * @returns The given custom colors then a set of acceptable console colors indefinitely.
9
+ */
10
+ getNextColor(): string;
11
+ }
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PrefixColorSelector = void 0;
4
+ function getConsoleColorsWithoutCustomColors(customColors) {
5
+ return PrefixColorSelector.ACCEPTABLE_CONSOLE_COLORS.filter(
6
+ // Consider the "Bright" variants of colors to be the same as the plain color to avoid similar colors
7
+ (color) => !customColors.includes(color.replace(/Bright$/, '')));
8
+ }
9
+ /**
10
+ * Creates a generator that yields an infinite stream of colors.
11
+ */
12
+ function* createColorGenerator(customColors) {
13
+ // Custom colors should be used as is, except for "auto"
14
+ const nextAutoColors = getConsoleColorsWithoutCustomColors(customColors);
15
+ let lastColor;
16
+ for (const customColor of customColors) {
17
+ let currentColor = customColor;
18
+ if (currentColor !== 'auto') {
19
+ yield currentColor; // Manual color
20
+ }
21
+ else {
22
+ // Find the first auto color that is not the same as the last color
23
+ while (currentColor === 'auto' || lastColor === currentColor) {
24
+ if (!nextAutoColors.length) {
25
+ // There could be more "auto" values than auto colors so this needs to be able to refill
26
+ nextAutoColors.push(...PrefixColorSelector.ACCEPTABLE_CONSOLE_COLORS);
27
+ }
28
+ currentColor = nextAutoColors.shift();
29
+ }
30
+ yield currentColor; // Auto color
31
+ }
32
+ lastColor = currentColor;
33
+ }
34
+ const lastCustomColor = customColors[customColors.length - 1] || '';
35
+ if (lastCustomColor !== 'auto') {
36
+ while (true) {
37
+ yield lastCustomColor; // If last custom color was not "auto" then return same color forever, to maintain existing behaviour
38
+ }
39
+ }
40
+ // Finish the initial set(s) of auto colors to avoid repetition
41
+ for (const color of nextAutoColors) {
42
+ yield color;
43
+ }
44
+ // Yield an infinite stream of acceptable console colors
45
+ //
46
+ // If the given custom colors use every ACCEPTABLE_CONSOLE_COLORS except one then there is a chance a color will be repeated,
47
+ // however its highly unlikely and low consequence so not worth the extra complexity to account for it
48
+ while (true) {
49
+ for (const color of PrefixColorSelector.ACCEPTABLE_CONSOLE_COLORS) {
50
+ yield color; // Repeat colors forever
51
+ }
52
+ }
53
+ }
54
+ class PrefixColorSelector {
55
+ constructor(customColors = []) {
56
+ this.colorGenerator = createColorGenerator(customColors);
57
+ }
58
+ /** A list of colors that are readable in a terminal. */
59
+ static get ACCEPTABLE_CONSOLE_COLORS() {
60
+ // Colors picked randomly, can be amended if required
61
+ return [
62
+ // Prevent duplicates, in case the list becomes significantly large
63
+ ...new Set([
64
+ // Text colors
65
+ 'cyan',
66
+ 'yellow',
67
+ 'greenBright',
68
+ 'blueBright',
69
+ 'magentaBright',
70
+ 'white',
71
+ 'grey',
72
+ 'red',
73
+ // Background colors
74
+ 'bgCyan',
75
+ 'bgYellow',
76
+ 'bgGreenBright',
77
+ 'bgBlueBright',
78
+ 'bgMagenta',
79
+ 'bgWhiteBright',
80
+ 'bgGrey',
81
+ 'bgRed',
82
+ ]),
83
+ ];
84
+ }
85
+ /**
86
+ * @returns The given custom colors then a set of acceptable console colors indefinitely.
87
+ */
88
+ getNextColor() {
89
+ return this.colorGenerator.next().value;
90
+ }
91
+ }
92
+ exports.PrefixColorSelector = PrefixColorSelector;
package/index.js CHANGED
@@ -1,8 +1,9 @@
1
- //
2
- // While in local development, make sure you've run `npm run build` first.
3
- //
1
+ /*
2
+ * While in local development, make sure you've run `npm run build` first.
3
+ */
4
4
 
5
5
  // eslint-disable-next-line @typescript-eslint/no-var-requires
6
6
  const concurrently = require('./dist/src/index.js');
7
+
7
8
  module.exports = exports = concurrently.default;
8
9
  Object.assign(exports, concurrently);
package/index.mjs CHANGED
@@ -1,9 +1,10 @@
1
- //
2
- // While in local development, make sure you've run `npm run build` first.
3
- //
1
+ /*
2
+ * While in local development, make sure you've run `npm run build` first.
3
+ */
4
+
5
+ import concurrently from './dist/src/index.js';
4
6
 
5
7
  // NOTE: the star reexport doesn't work in Node <12.20, <14.13 and <15.
6
8
  export * from './dist/src/index.js';
7
9
 
8
- import concurrently from './dist/src/index.js';
9
10
  export default concurrently.default;
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "concurrently",
3
- "version": "7.3.0",
3
+ "version": "7.5.0",
4
4
  "description": "Run commands concurrently",
5
5
  "main": "index.js",
6
6
  "types": "dist/src/index.d.ts",
7
7
  "type": "commonjs",
8
8
  "bin": {
9
- "concurrently": "./dist/bin/concurrently.js"
9
+ "concurrently": "./dist/bin/concurrently.js",
10
+ "conc": "./dist/bin/concurrently.js"
10
11
  },
11
12
  "engines": {
12
13
  "node": "^12.20.0 || ^14.13.0 || >=16.0.0"
@@ -26,7 +27,7 @@
26
27
  "clean": "tsc --build --clean",
27
28
  "format": "prettier --ignore-path .gitignore --check '**/{!(package-lock).json,*.y?(a)ml,*.md}'",
28
29
  "format:fix": "npm run format -- --write",
29
- "lint": "eslint . --ext js,ts --ignore-path .gitignore",
30
+ "lint": "eslint . --ext mjs,js,ts --ignore-path .gitignore",
30
31
  "lint:fix": "npm run lint -- --fix",
31
32
  "prepublishOnly": "npm run build",
32
33
  "report-coverage": "cat coverage/lcov.info | coveralls",
@@ -36,6 +37,7 @@
36
37
  "type": "git",
37
38
  "url": "https://github.com/open-cli-tools/concurrently.git"
38
39
  },
40
+ "funding": "https://github.com/open-cli-tools/concurrently?sponsor=1",
39
41
  "keywords": [
40
42
  "bash",
41
43
  "concurrent",
@@ -48,7 +50,7 @@
48
50
  "license": "MIT",
49
51
  "dependencies": {
50
52
  "chalk": "^4.1.0",
51
- "date-fns": "^2.16.1",
53
+ "date-fns": "^2.29.1",
52
54
  "lodash": "^4.17.21",
53
55
  "rxjs": "^7.0.0",
54
56
  "shell-quote": "^1.7.3",
@@ -58,27 +60,33 @@
58
60
  "yargs": "^17.3.1"
59
61
  },
60
62
  "devDependencies": {
61
- "@swc-node/register": "^1.5.1",
62
- "@swc/core": "^1.2.204",
63
+ "@hirez_io/observer-spy": "^2.2.0",
64
+ "@swc/core": "^1.2.224",
63
65
  "@swc/jest": "^0.2.21",
64
- "@types/jest": "^27.0.3",
66
+ "@types/jest": "^28.1.8",
65
67
  "@types/lodash": "^4.14.178",
66
- "@types/node": "^17.0.0",
68
+ "@types/node": "^16.11.47",
67
69
  "@types/shell-quote": "^1.7.1",
68
70
  "@types/supports-color": "^8.1.1",
69
- "@types/yargs": "^17.0.8",
70
- "@typescript-eslint/eslint-plugin": "^5.8.1",
71
- "@typescript-eslint/parser": "^5.8.1",
71
+ "@types/yargs": "^17.0.11",
72
+ "@typescript-eslint/eslint-plugin": "^5.33.0",
73
+ "@typescript-eslint/parser": "^5.33.0",
72
74
  "coveralls-next": "^4.1.2",
73
- "eslint": "^8.15.0",
75
+ "ctrlc-wrapper": "^0.0.4",
76
+ "esbuild": "^0.15.1",
77
+ "eslint": "^8.21.0",
74
78
  "eslint-config-prettier": "^8.5.0",
79
+ "eslint-plugin-import": "^2.26.0",
80
+ "eslint-plugin-jest": "^27.0.4",
75
81
  "eslint-plugin-prettier": "^4.0.0",
76
- "jest": "^27.5.1",
82
+ "eslint-plugin-simple-import-sort": "^8.0.0",
83
+ "jest": "^28.1.3",
77
84
  "jest-create-mock-instance": "^2.0.0",
78
85
  "lint-staged": "^12.4.1",
79
86
  "prettier": "^2.6.2",
80
87
  "simple-git-hooks": "^2.7.0",
81
- "typescript": "^4.5.4"
88
+ "string-argv": "^0.3.1",
89
+ "typescript": "~4.8.3"
82
90
  },
83
91
  "files": [
84
92
  "dist",
@@ -92,7 +100,7 @@
92
100
  "pre-commit": "npx lint-staged"
93
101
  },
94
102
  "lint-staged": {
95
- "*.{js,ts}": "eslint --fix",
96
- "{!(package-lock).json,*.y?(a)ml,*.md}": "prettier --write"
103
+ "*.m?{js,ts}": "eslint --fix",
104
+ "{!(package-lock).json,*.{y?(a)ml,md}}": "prettier --write"
97
105
  }
98
106
  }