concurrently 7.5.0 → 7.6.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
@@ -3,7 +3,7 @@
3
3
  [![Latest Release](https://img.shields.io/github/v/release/open-cli-tools/concurrently?label=Release)](https://github.com/open-cli-tools/concurrently/releases)
4
4
  [![License](https://img.shields.io/github/license/open-cli-tools/concurrently?label=License)](https://github.com/open-cli-tools/concurrently/blob/main/LICENSE)
5
5
  [![Weekly Downloads on NPM](https://img.shields.io/npm/dw/concurrently?label=Downloads&logo=npm)](https://www.npmjs.com/package/concurrently)
6
- [![CI Status](https://img.shields.io/github/workflow/status/open-cli-tools/concurrently/CI?label=CI&logo=github)](https://github.com/open-cli-tools/concurrently/actions/workflows/ci.yml)
6
+ [![CI Status](https://img.shields.io/github/workflow/status/open-cli-tools/concurrently/Test?label=CI&logo=github)](https://github.com/open-cli-tools/concurrently/actions/workflows/test.yml)
7
7
  [![Coverage Status](https://img.shields.io/coveralls/github/open-cli-tools/concurrently/main?label=Coverage&logo=coveralls)](https://coveralls.io/github/open-cli-tools/concurrently?branch=main)
8
8
 
9
9
  Run multiple commands concurrently.
@@ -15,7 +15,7 @@ Like `npm run watch-js & npm run watch-less` but better.
15
15
 
16
16
  - [concurrently](#concurrently)
17
17
  - [Why](#why)
18
- - [Install](#install)
18
+ - [Installation](#installation)
19
19
  - [Usage](#usage)
20
20
  - [API](#api)
21
21
  - [`concurrently(commands[, options])`](#concurrentlycommands-options)
@@ -41,25 +41,24 @@ tired of opening terminals and made **concurrently**.
41
41
  - With `--kill-others` switch, all commands are killed if one dies
42
42
  - Spawns commands with [spawn-command](https://github.com/mmalecki/spawn-command)
43
43
 
44
- ## Install
44
+ ## Installation
45
45
 
46
- The tool is written in Node.js, but you can use it to run **any** commands.
47
-
48
- ```bash
49
- npm install -g concurrently
50
- ```
46
+ **concurrently** can be installed in the global scope (if you'd like to have it available and use it on the whole system) or locally for a specific package (for example if you'd like to use it in the `scripts` section of your package):
51
47
 
52
- or if you are using it from npm scripts:
48
+ | | npm | Yarn | pnpm |
49
+ | ----------- | ----------------------- | ------------------------------ | -------------------------- |
50
+ | **Global** | `npm i -g concurrently` | `yarn global add concurrently` | `pnpm add -g concurrently` |
51
+ | **Local**\* | `npm i concurrently -D` | `yarn add concurrently -D` | `pnpm add -D concurrently` |
53
52
 
54
- ```bash
55
- npm install concurrently --save
56
- ```
53
+ <sub>\* It's recommended to add **concurrently** as `devDependencies` as it's usually used for developing purposes. Please change this flag if this doesn't apply in your case.</sub>
57
54
 
58
55
  ## Usage
59
56
 
60
57
  > **Note**
61
58
  > The `concurrently` command is now also available under the shorthand alias `conc`.
62
59
 
60
+ The tool is written in Node.js, but you can use it to run **any** commands.
61
+
63
62
  Remember to surround separate commands with quotes:
64
63
 
65
64
  ```bash
@@ -146,8 +145,9 @@ concurrently [options] <command ...>
146
145
 
147
146
  General
148
147
  -m, --max-processes How many processes should run at once.
148
+ Exact number or a percent of CPUs available (for example "50%").
149
149
  New processes only spawn after all restart tries
150
- of a process. [number]
150
+ of a process. [string]
151
151
  -n, --names List of custom names to be used in prefix
152
152
  template.
153
153
  Example names: "main,browser,server" [string]
@@ -54,8 +54,9 @@ const args = (0, yargs_1.default)(argsBeforeSep)
54
54
  'max-processes': {
55
55
  alias: 'm',
56
56
  describe: 'How many processes should run at once.\n' +
57
- 'New processes only spawn after all restart tries of a process.',
58
- type: 'number',
57
+ 'New processes only spawn after all restart tries of a process.\n' +
58
+ 'Exact number or a percent of CPUs available (for example "50%")',
59
+ type: 'string',
59
60
  },
60
61
  names: {
61
62
  alias: 'n',
@@ -9,8 +9,8 @@ export declare class ExpandArguments implements CommandParser {
9
9
  parse(commandInfo: CommandInfo): {
10
10
  command: string;
11
11
  name: string;
12
- env?: Record<string, unknown>;
13
- cwd?: string;
14
- prefixColor?: string;
12
+ env?: Record<string, unknown> | undefined;
13
+ cwd?: string | undefined;
14
+ prefixColor?: string | undefined;
15
15
  };
16
16
  }
@@ -12,9 +12,6 @@ const OMISSION = /\(!([^)]+)\)/;
12
12
  * `package.json` file of the current directory.
13
13
  */
14
14
  class ExpandNpmWildcard {
15
- constructor(readPackage = ExpandNpmWildcard.readPackage) {
16
- this.readPackage = readPackage;
17
- }
18
15
  static readPackage() {
19
16
  try {
20
17
  const json = fs_1.default.readFileSync('package.json', { encoding: 'utf-8' });
@@ -24,6 +21,9 @@ class ExpandNpmWildcard {
24
21
  return {};
25
22
  }
26
23
  }
24
+ constructor(readPackage = ExpandNpmWildcard.readPackage) {
25
+ this.readPackage = readPackage;
26
+ }
27
27
  parse(commandInfo) {
28
28
  const [, npmCmd, cmdName, args] = commandInfo.command.match(/(npm|yarn|pnpm) run (\S+)([^&]*)/) || [];
29
29
  const wildcardPosition = (cmdName || '').indexOf('*');
@@ -40,7 +40,9 @@ class ExpandNpmWildcard {
40
40
  const preWildcard = lodash_1.default.escapeRegExp(cmdNameSansOmission.slice(0, wildcardPosition));
41
41
  const postWildcard = lodash_1.default.escapeRegExp(cmdNameSansOmission.slice(wildcardPosition + 1));
42
42
  const wildcardRegex = new RegExp(`^${preWildcard}(.*?)${postWildcard}$`);
43
- const currentName = commandInfo.name || '';
43
+ // If 'commandInfo.name' doesn't match 'cmdName', this means a custom name
44
+ // has been specified and thus becomes the prefix (as described in the README).
45
+ const prefix = commandInfo.name !== cmdName ? commandInfo.name : '';
44
46
  return this.scripts
45
47
  .map((script) => {
46
48
  const match = script.match(wildcardRegex);
@@ -54,9 +56,9 @@ class ExpandNpmWildcard {
54
56
  return {
55
57
  ...commandInfo,
56
58
  command: `${npmCmd} run ${script}${args}`,
57
- // Will use an empty command name if command has no name and the wildcard match is empty,
58
- // e.g. if `npm:watch-*` matches `npm run watch-`.
59
- name: currentName + match[1],
59
+ // Will use an empty command name if no prefix has been specified and
60
+ // the wildcard match is empty, e.g. if `npm:watch-*` matches `npm run watch-`.
61
+ name: prefix + match[1],
60
62
  };
61
63
  }
62
64
  })
@@ -7,8 +7,8 @@ export declare class StripQuotes implements CommandParser {
7
7
  parse(commandInfo: CommandInfo): {
8
8
  command: string;
9
9
  name: string;
10
- env?: Record<string, unknown>;
11
- cwd?: string;
12
- prefixColor?: string;
10
+ env?: Record<string, unknown> | undefined;
11
+ cwd?: string | undefined;
12
+ prefixColor?: string | undefined;
13
13
  };
14
14
  }
@@ -8,7 +8,7 @@ import { EventEmitter, Writable } from 'stream';
8
8
  /**
9
9
  * Identifier for a command; if string, it's the command's name, if number, it's the index.
10
10
  */
11
- export declare type CommandIdentifier = string | number;
11
+ export type CommandIdentifier = string | number;
12
12
  export interface CommandInfo {
13
13
  /**
14
14
  * Command's name.
@@ -58,15 +58,15 @@ export interface TimerEvent {
58
58
  /**
59
59
  * Subtype of NodeJS's child_process including only what's actually needed for a command to work.
60
60
  */
61
- export declare type ChildProcess = EventEmitter & Pick<BaseChildProcess, 'pid' | 'stdin' | 'stdout' | 'stderr'>;
61
+ export type ChildProcess = EventEmitter & Pick<BaseChildProcess, 'pid' | 'stdin' | 'stdout' | 'stderr'>;
62
62
  /**
63
63
  * Interface for a function that must kill the process with `pid`, optionally sending `signal` to it.
64
64
  */
65
- export declare type KillProcess = (pid: number, signal?: string) => void;
65
+ export type KillProcess = (pid: number, signal?: string) => void;
66
66
  /**
67
67
  * Interface for a function that spawns a command and returns its child process instance.
68
68
  */
69
- export declare type SpawnCommand = (command: string, options: SpawnOptions) => ChildProcess;
69
+ export type SpawnCommand = (command: string, options: SpawnOptions) => ChildProcess;
70
70
  export declare class Command implements CommandInfo {
71
71
  private readonly killProcess;
72
72
  private readonly spawn;
@@ -77,7 +77,7 @@ export declare class Command implements CommandInfo {
77
77
  /** @inheritdoc */
78
78
  readonly command: string;
79
79
  /** @inheritdoc */
80
- readonly prefixColor: string;
80
+ readonly prefixColor?: string;
81
81
  /** @inheritdoc */
82
82
  readonly env: Record<string, unknown>;
83
83
  /** @inheritdoc */
@@ -92,6 +92,7 @@ export declare class Command implements CommandInfo {
92
92
  pid?: number;
93
93
  killed: boolean;
94
94
  exited: boolean;
95
+ /** @deprecated */
95
96
  get killable(): boolean;
96
97
  constructor({ index, name, command, prefixColor, env, cwd }: CommandInfo & {
97
98
  index: number;
@@ -104,4 +105,13 @@ export declare class Command implements CommandInfo {
104
105
  * Kills this command, optionally specifying a signal to send to it.
105
106
  */
106
107
  kill(code?: string): void;
108
+ /**
109
+ * Detects whether a command can be killed.
110
+ *
111
+ * Also works as a type guard on the input `command`.
112
+ */
113
+ static canKill(command: Command): command is Command & {
114
+ pid: number;
115
+ process: ChildProcess;
116
+ };
107
117
  }
@@ -26,6 +26,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.Command = void 0;
27
27
  const Rx = __importStar(require("rxjs"));
28
28
  class Command {
29
+ /** @deprecated */
30
+ get killable() {
31
+ return Command.canKill(this);
32
+ }
29
33
  constructor({ index, name, command, prefixColor, env, cwd }, spawnOpts, spawn, killProcess) {
30
34
  this.close = new Rx.Subject();
31
35
  this.error = new Rx.Subject();
@@ -38,15 +42,12 @@ class Command {
38
42
  this.name = name;
39
43
  this.command = command;
40
44
  this.prefixColor = prefixColor;
41
- this.env = env;
45
+ this.env = env || {};
42
46
  this.cwd = cwd;
43
47
  this.killProcess = killProcess;
44
48
  this.spawn = spawn;
45
49
  this.spawnOpts = spawnOpts;
46
50
  }
47
- get killable() {
48
- return !!this.process;
49
- }
50
51
  /**
51
52
  * Starts this command, piping output, error and close events onto the corresponding observables.
52
53
  */
@@ -72,7 +73,7 @@ class Command {
72
73
  this.close.next({
73
74
  command: this,
74
75
  index: this.index,
75
- exitCode: exitCode === null ? signal : exitCode,
76
+ exitCode: exitCode !== null && exitCode !== void 0 ? exitCode : String(signal),
76
77
  killed: this.killed,
77
78
  timings: {
78
79
  startDate,
@@ -83,17 +84,25 @@ class Command {
83
84
  });
84
85
  child.stdout && pipeTo(Rx.fromEvent(child.stdout, 'data'), this.stdout);
85
86
  child.stderr && pipeTo(Rx.fromEvent(child.stderr, 'data'), this.stderr);
86
- this.stdin = child.stdin;
87
+ this.stdin = child.stdin || undefined;
87
88
  }
88
89
  /**
89
90
  * Kills this command, optionally specifying a signal to send to it.
90
91
  */
91
92
  kill(code) {
92
- if (this.killable) {
93
+ if (Command.canKill(this)) {
93
94
  this.killed = true;
94
95
  this.killProcess(this.pid, code);
95
96
  }
96
97
  }
98
+ /**
99
+ * Detects whether a command can be killed.
100
+ *
101
+ * Also works as a type guard on the input `command`.
102
+ */
103
+ static canKill(command) {
104
+ return !!command.pid && !!command.process;
105
+ }
97
106
  }
98
107
  exports.Command = Command;
99
108
  /**
@@ -9,7 +9,7 @@ import { CloseEvent, Command } from './command';
9
9
  * - `command-{name|index}`: only the commands with the specified names or index.
10
10
  * - `!command-{name|index}`: all commands but the ones with the specified names or index.
11
11
  */
12
- export declare type SuccessCondition = 'first' | 'last' | 'all' | `command-${string | number}` | `!command-${string | number}`;
12
+ export type SuccessCondition = 'first' | 'last' | 'all' | `command-${string | number}` | `!command-${string | number}`;
13
13
  /**
14
14
  * Provides logic to determine whether lists of commands ran successfully.
15
15
  */
@@ -36,4 +36,5 @@ export declare class CompletionListener {
36
36
  * @returns A Promise that resolves if the success condition is met, or rejects otherwise.
37
37
  */
38
38
  listen(commands: Command[]): Promise<CloseEvent[]>;
39
+ private emitWithScheduler;
39
40
  }
@@ -67,8 +67,11 @@ class CompletionListener {
67
67
  listen(commands) {
68
68
  const closeStreams = commands.map((command) => command.close);
69
69
  return Rx.lastValueFrom(Rx.merge(...closeStreams).pipe((0, operators_1.bufferCount)(closeStreams.length), (0, operators_1.switchMap)((exitInfos) => this.isSuccess(exitInfos)
70
- ? Rx.of(exitInfos, this.scheduler)
71
- : Rx.throwError(exitInfos, this.scheduler)), (0, operators_1.take)(1)));
70
+ ? this.emitWithScheduler(Rx.of(exitInfos))
71
+ : this.emitWithScheduler(Rx.throwError(exitInfos))), (0, operators_1.take)(1)));
72
+ }
73
+ emitWithScheduler(input) {
74
+ return this.scheduler ? input.pipe(Rx.observeOn(this.scheduler)) : input;
72
75
  }
73
76
  }
74
77
  exports.CompletionListener = CompletionListener;
@@ -9,8 +9,10 @@ import { Logger } from './logger';
9
9
  * If value is a string, then that's the command's command line.
10
10
  * Fine grained options can be defined by using the object format.
11
11
  */
12
- export declare type ConcurrentlyCommandInput = string | Partial<CommandInfo>;
13
- export declare type ConcurrentlyResult = {
12
+ export type ConcurrentlyCommandInput = string | ({
13
+ command: string;
14
+ } & Partial<CommandInfo>);
15
+ export type ConcurrentlyResult = {
14
16
  /**
15
17
  * All commands created and ran by concurrently.
16
18
  */
@@ -23,7 +25,7 @@ export declare type ConcurrentlyResult = {
23
25
  */
24
26
  result: Promise<CloseEvent[]>;
25
27
  };
26
- export declare type ConcurrentlyOptions = {
28
+ export type ConcurrentlyOptions = {
27
29
  logger?: Logger;
28
30
  /**
29
31
  * Which stream should the commands output be written to.
@@ -39,11 +41,12 @@ export declare type ConcurrentlyOptions = {
39
41
  prefixColors?: string[];
40
42
  /**
41
43
  * Maximum number of commands to run at once.
44
+ * Exact number or a percent of CPUs available (for example "50%").
42
45
  *
43
46
  * If undefined, then all processes will start in parallel.
44
47
  * Setting this value to 1 will achieve sequential running.
45
48
  */
46
- maxProcesses?: number;
49
+ maxProcesses?: number | string;
47
50
  /**
48
51
  * Whether commands should be spawned in raw mode.
49
52
  * Defaults to false.
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.concurrently = void 0;
7
7
  const assert_1 = __importDefault(require("assert"));
8
8
  const lodash_1 = __importDefault(require("lodash"));
9
+ const os_1 = require("os");
9
10
  const spawn_command_1 = __importDefault(require("spawn-command"));
10
11
  const tree_kill_1 = __importDefault(require("tree-kill"));
11
12
  const command_1 = require("./command");
@@ -69,13 +70,15 @@ function concurrently(baseCommands, baseOptions) {
69
70
  if (options.logger && options.outputStream) {
70
71
  const outputWriter = new output_writer_1.OutputWriter({
71
72
  outputStream: options.outputStream,
72
- group: options.group,
73
+ group: !!options.group,
73
74
  commands,
74
75
  });
75
76
  options.logger.output.subscribe(({ command, text }) => outputWriter.write(command, text));
76
77
  }
77
78
  const commandsLeft = commands.slice();
78
- const maxProcesses = Math.max(1, Number(options.maxProcesses) || commandsLeft.length);
79
+ const maxProcesses = Math.max(1, (typeof options.maxProcesses === 'string' && options.maxProcesses.endsWith('%')
80
+ ? Math.round(((0, os_1.cpus)().length * Number(options.maxProcesses.slice(0, -1))) / 100)
81
+ : Number(options.maxProcesses)) || commandsLeft.length);
79
82
  for (let i = 0; i < maxProcesses; i++) {
80
83
  maybeRunMore(commandsLeft);
81
84
  }
@@ -92,13 +95,9 @@ function concurrently(baseCommands, baseOptions) {
92
95
  exports.concurrently = concurrently;
93
96
  function mapToCommandInfo(command) {
94
97
  if (typeof command === 'string') {
95
- return {
96
- command,
97
- name: '',
98
- env: {},
99
- cwd: '',
100
- };
98
+ return mapToCommandInfo({ command });
101
99
  }
100
+ assert_1.default.ok(command.command, '[concurrently] command cannot be empty');
102
101
  return {
103
102
  command: command.command,
104
103
  name: command.name || '',
@@ -15,10 +15,10 @@ import { FlowController } from './flow-controller';
15
15
  export declare class InputHandler implements FlowController {
16
16
  private readonly logger;
17
17
  private readonly defaultInputTarget;
18
- private readonly inputStream;
18
+ private readonly inputStream?;
19
19
  private readonly pauseInputStreamOnFinish;
20
20
  constructor({ defaultInputTarget, inputStream, pauseInputStreamOnFinish, logger, }: {
21
- inputStream: Readable;
21
+ inputStream?: Readable;
22
22
  logger: Logger;
23
23
  defaultInputTarget?: CommandIdentifier;
24
24
  pauseInputStreamOnFinish?: boolean;
@@ -44,11 +44,12 @@ class InputHandler {
44
44
  this.pauseInputStreamOnFinish = pauseInputStreamOnFinish !== false;
45
45
  }
46
46
  handle(commands) {
47
- if (!this.inputStream) {
47
+ const { inputStream } = this;
48
+ if (!inputStream) {
48
49
  return { commands };
49
50
  }
50
- Rx.fromEvent(this.inputStream, 'data')
51
- .pipe((0, operators_1.map)((data) => data.toString()))
51
+ Rx.fromEvent(inputStream, 'data')
52
+ .pipe((0, operators_1.map)((data) => String(data)))
52
53
  .subscribe((data) => {
53
54
  const dataParts = data.split(/:(.+)/);
54
55
  const targetId = dataParts.length > 1 ? dataParts[0] : this.defaultInputTarget;
@@ -67,7 +68,7 @@ class InputHandler {
67
68
  onFinish: () => {
68
69
  if (this.pauseInputStreamOnFinish) {
69
70
  // https://github.com/kimmobrunfeldt/concurrently/issues/252
70
- this.inputStream.pause();
71
+ inputStream.pause();
71
72
  }
72
73
  },
73
74
  };
@@ -1,9 +1,9 @@
1
1
  import { Command } from '../command';
2
2
  import { Logger } from '../logger';
3
3
  import { FlowController } from './flow-controller';
4
- export declare type ProcessCloseCondition = 'failure' | 'success';
4
+ export type ProcessCloseCondition = 'failure' | 'success';
5
5
  /**
6
- * Sends a SIGTERM signal to all commands when one of the exits with a matching condition.
6
+ * Sends a SIGTERM signal to all commands when one of the commands exits with a matching condition.
7
7
  */
8
8
  export declare class KillOthers implements FlowController {
9
9
  private readonly logger;
@@ -6,8 +6,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.KillOthers = void 0;
7
7
  const lodash_1 = __importDefault(require("lodash"));
8
8
  const operators_1 = require("rxjs/operators");
9
+ const command_1 = require("../command");
9
10
  /**
10
- * Sends a SIGTERM signal to all commands when one of the exits with a matching condition.
11
+ * Sends a SIGTERM signal to all commands when one of the commands exits with a matching condition.
11
12
  */
12
13
  class KillOthers {
13
14
  constructor({ logger, conditions, }) {
@@ -21,7 +22,7 @@ class KillOthers {
21
22
  }
22
23
  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
24
  closeStates.forEach((closeState) => closeState.subscribe(() => {
24
- const killableCommands = commands.filter((command) => command.killable);
25
+ const killableCommands = commands.filter((command) => command_1.Command.canKill(command));
25
26
  if (killableCommands.length) {
26
27
  this.logger.logGlobalEvent('Sending SIGTERM to other processes..');
27
28
  killableCommands.forEach((command) => command.kill());
@@ -27,6 +27,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
29
  exports.LogTimings = void 0;
30
+ const assert = __importStar(require("assert"));
30
31
  const format_1 = __importDefault(require("date-fns/format"));
31
32
  const lodash_1 = __importDefault(require("lodash"));
32
33
  const Rx = __importStar(require("rxjs"));
@@ -36,10 +37,6 @@ const defaults = __importStar(require("../defaults"));
36
37
  * Logs timing information about commands as they start/stop and then a summary when all commands finish.
37
38
  */
38
39
  class LogTimings {
39
- constructor({ logger, timestampFormat = defaults.timestampFormat, }) {
40
- this.logger = logger;
41
- this.timestampFormat = timestampFormat;
42
- }
43
40
  static mapCloseEventToTimingInfo({ command, timings, killed, exitCode, }) {
44
41
  const readableDurationMs = (timings.endDate.getTime() - timings.startDate.getTime()).toLocaleString();
45
42
  return {
@@ -50,7 +47,12 @@ class LogTimings {
50
47
  command: command.command,
51
48
  };
52
49
  }
50
+ constructor({ logger, timestampFormat = defaults.timestampFormat, }) {
51
+ this.logger = logger;
52
+ this.timestampFormat = timestampFormat;
53
+ }
53
54
  printExitInfoTimingTable(exitInfos) {
55
+ assert.ok(this.logger);
54
56
  const exitInfoTable = (0, lodash_1.default)(exitInfos)
55
57
  .sortBy(({ timings }) => timings.durationSeconds)
56
58
  .reverse()
@@ -61,7 +63,8 @@ class LogTimings {
61
63
  return exitInfos;
62
64
  }
63
65
  handle(commands) {
64
- if (!this.logger) {
66
+ const { logger } = this;
67
+ if (!logger) {
65
68
  return { commands };
66
69
  }
67
70
  // individual process timings
@@ -69,12 +72,12 @@ class LogTimings {
69
72
  command.timer.subscribe(({ startDate, endDate }) => {
70
73
  if (!endDate) {
71
74
  const formattedStartDate = (0, format_1.default)(startDate, this.timestampFormat);
72
- this.logger.logCommandEvent(`${command.command} started at ${formattedStartDate}`, command);
75
+ logger.logCommandEvent(`${command.command} started at ${formattedStartDate}`, command);
73
76
  }
74
77
  else {
75
78
  const durationMs = endDate.getTime() - startDate.getTime();
76
79
  const formattedEndDate = (0, format_1.default)(endDate, this.timestampFormat);
77
- this.logger.logCommandEvent(`${command.command} stopped at ${formattedEndDate} after ${durationMs.toLocaleString()}ms`, command);
80
+ logger.logCommandEvent(`${command.command} stopped at ${formattedEndDate} after ${durationMs.toLocaleString()}ms`, command);
78
81
  }
79
82
  });
80
83
  });
@@ -11,23 +11,23 @@ export declare const getSpawnOpts: ({ colorSupport, cwd, process, raw, env, }: {
11
11
  *
12
12
  * Defaults to whatever the terminal's stdout support is.
13
13
  */
14
- colorSupport?: Pick<supportsColor.supportsColor.Level, 'level'> | false;
14
+ colorSupport?: false | Pick<supportsColor.supportsColor.Level, "level"> | undefined;
15
15
  /**
16
16
  * The NodeJS process.
17
17
  */
18
- process?: Pick<NodeJS.Process, 'cwd' | 'platform' | 'env'>;
18
+ process?: Pick<NodeJS.Process, "cwd" | "env" | "platform"> | undefined;
19
19
  /**
20
20
  * A custom working directory to spawn processes in.
21
21
  * Defaults to `process.cwd()`.
22
22
  */
23
- cwd?: string;
23
+ cwd?: string | undefined;
24
24
  /**
25
25
  * Whether to customize the options for spawning processes in raw mode.
26
26
  * Defaults to false.
27
27
  */
28
- raw?: boolean;
28
+ raw?: boolean | undefined;
29
29
  /**
30
30
  * Map of custom environment variables to include in the spawn options.
31
31
  */
32
- env?: Record<string, unknown>;
32
+ env?: Record<string, unknown> | undefined;
33
33
  }) => SpawnOptions;
@@ -12,7 +12,7 @@ import { LogOutput } from './flow-control/log-output';
12
12
  import { LogTimings } from './flow-control/log-timings';
13
13
  import { RestartProcess } from './flow-control/restart-process';
14
14
  import { Logger } from './logger';
15
- export declare type ConcurrentlyOptions = BaseConcurrentlyOptions & {
15
+ export type ConcurrentlyOptions = BaseConcurrentlyOptions & {
16
16
  /**
17
17
  * Which command(s) should have their output hidden.
18
18
  */
package/dist/src/index.js CHANGED
@@ -46,7 +46,7 @@ exports.default = (commands, options = {}) => {
46
46
  new input_handler_1.InputHandler({
47
47
  logger,
48
48
  defaultInputTarget: options.defaultInputTarget,
49
- inputStream: options.inputStream || (options.handleInput && process.stdin),
49
+ inputStream: options.inputStream || (options.handleInput ? process.stdin : undefined),
50
50
  pauseInputStreamOnFinish: options.pauseInputStreamOnFinish,
51
51
  }),
52
52
  new kill_on_signal_1.KillOnSignal({ process }),
@@ -57,10 +57,10 @@ exports.default = (commands, options = {}) => {
57
57
  }),
58
58
  new kill_others_1.KillOthers({
59
59
  logger,
60
- conditions: options.killOthers,
60
+ conditions: options.killOthers || [],
61
61
  }),
62
62
  new log_timings_1.LogTimings({
63
- logger: options.timings ? logger : null,
63
+ logger: options.timings ? logger : undefined,
64
64
  timestampFormat: options.timestampFormat,
65
65
  }),
66
66
  ],
@@ -86,13 +86,14 @@ class Logger {
86
86
  }, prefix);
87
87
  }
88
88
  colorText(command, text) {
89
+ var _a;
89
90
  let color;
90
91
  if (command.prefixColor && command.prefixColor.startsWith('#')) {
91
92
  color = chalk_1.default.hex(command.prefixColor);
92
93
  }
93
94
  else {
94
95
  const defaultColor = lodash_1.default.get(chalk_1.default, defaults.prefixColors, chalk_1.default.reset);
95
- color = lodash_1.default.get(chalk_1.default, command.prefixColor, defaultColor);
96
+ color = lodash_1.default.get(chalk_1.default, (_a = command.prefixColor) !== null && _a !== void 0 ? _a : '', defaultColor);
96
97
  }
97
98
  return color(text);
98
99
  }
@@ -25,7 +25,7 @@ function* createColorGenerator(customColors) {
25
25
  // There could be more "auto" values than auto colors so this needs to be able to refill
26
26
  nextAutoColors.push(...PrefixColorSelector.ACCEPTABLE_CONSOLE_COLORS);
27
27
  }
28
- currentColor = nextAutoColors.shift();
28
+ currentColor = String(nextAutoColors.shift());
29
29
  }
30
30
  yield currentColor; // Auto color
31
31
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "concurrently",
3
- "version": "7.5.0",
3
+ "version": "7.6.0",
4
4
  "description": "Run commands concurrently",
5
5
  "main": "index.js",
6
6
  "types": "dist/src/index.d.ts",
@@ -25,9 +25,9 @@
25
25
  "build": "tsc --build",
26
26
  "postbuild": "chmod +x dist/bin/concurrently.js",
27
27
  "clean": "tsc --build --clean",
28
- "format": "prettier --ignore-path .gitignore --check '**/{!(package-lock).json,*.y?(a)ml,*.md}'",
28
+ "format": "prettier --check '**/*.{json,y?(a)ml,md}'",
29
29
  "format:fix": "npm run format -- --write",
30
- "lint": "eslint . --ext mjs,js,ts --ignore-path .gitignore",
30
+ "lint": "eslint --ignore-path .gitignore --ext mjs,js,ts .",
31
31
  "lint:fix": "npm run lint -- --fix",
32
32
  "prepublishOnly": "npm run build",
33
33
  "report-coverage": "cat coverage/lcov.info | coveralls",
@@ -86,7 +86,7 @@
86
86
  "prettier": "^2.6.2",
87
87
  "simple-git-hooks": "^2.7.0",
88
88
  "string-argv": "^0.3.1",
89
- "typescript": "~4.8.3"
89
+ "typescript": "~4.9.3"
90
90
  },
91
91
  "files": [
92
92
  "dist",
@@ -101,6 +101,6 @@
101
101
  },
102
102
  "lint-staged": {
103
103
  "*.m?{js,ts}": "eslint --fix",
104
- "{!(package-lock).json,*.{y?(a)ml,md}}": "prettier --write"
104
+ "*.{json,y?(a)ml,md}": "prettier --write"
105
105
  }
106
106
  }