concurrently 9.1.2 → 9.2.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
@@ -61,7 +61,7 @@ The tool is written in Node.js, but you can use it to run **any** commands.
61
61
  Remember to surround separate commands with quotes:
62
62
 
63
63
  ```bash
64
- concurrently "command1 arg" "command2 arg"
64
+ concurrently 'command1 arg' 'command2 arg'
65
65
  ```
66
66
 
67
67
  Otherwise **concurrently** would try to run 4 separate commands:
@@ -70,7 +70,7 @@ Otherwise **concurrently** would try to run 4 separate commands:
70
70
  In package.json, escape quotes:
71
71
 
72
72
  ```bash
73
- "start": "concurrently \"command1 arg\" \"command2 arg\""
73
+ "start": "concurrently 'command1 arg' 'command2 arg'"
74
74
  ```
75
75
 
76
76
  You can always check concurrently's flag list by running `concurrently --help`.
@@ -88,7 +88,7 @@ Check out documentation and other usage examples in the [`docs` directory](./doc
88
88
  with the shape `{ command, name, prefixColor, env, cwd, ipc }`.
89
89
 
90
90
  - `options` (optional): an object containing any of the below:
91
- - `cwd`: the working directory to be used by all commands. Can be overriden per command.
91
+ - `cwd`: the working directory to be used by all commands. Can be overridden per command.
92
92
  Default: `process.cwd()`.
93
93
  - `defaultInputTarget`: the default input target when reading from `inputStream`.
94
94
  Default: `0`.
@@ -96,8 +96,8 @@ Check out documentation and other usage examples in the [`docs` directory](./doc
96
96
  - `inputStream`: a [`Readable` stream](https://nodejs.org/dist/latest-v10.x/docs/api/stream.html#stream_readable_streams)
97
97
  to read the input from. Should only be used in the rare instance you would like to stream anything other than `process.stdin`. Overrides `handleInput`.
98
98
  - `pauseInputStreamOnFinish`: by default, pauses the input stream (`process.stdin` when `handleInput` is enabled, or `inputStream` if provided) when all of the processes have finished. If you need to read from the input stream after `concurrently` has finished, set this to `false`. ([#252](https://github.com/kimmobrunfeldt/concurrently/issues/252)).
99
- - `killOthers`: an array of exitting conditions that will cause a process to kill others.
100
- Can contain any of `success` or `failure`.
99
+ - `killOthersOn`: once the first command exits with one of these statuses, kill other commands.
100
+ Can be an array containing the strings `success` (status code zero) and/or `failure` (non-zero exit status).
101
101
  - `maxProcesses`: how many processes should run at once.
102
102
  - `outputStream`: a [`Writable` stream](https://nodejs.org/dist/latest-v10.x/docs/api/stream.html#stream_writable_streams)
103
103
  to write logs to. Default: `process.stdout`.
@@ -109,14 +109,14 @@ Check out documentation and other usage examples in the [`docs` directory](./doc
109
109
  Prefix colors specified per-command take precedence over this list.
110
110
  - `prefixLength`: how many characters to show when prefixing with `command`. Default: `10`
111
111
  - `raw`: whether raw mode should be used, meaning strictly process output will
112
- be logged, without any prefixes, coloring or extra stuff. Can be overriden per command.
112
+ be logged, without any prefixes, coloring or extra stuff. Can be overridden per command.
113
113
  - `successCondition`: the condition to consider the run was successful.
114
114
  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.
115
115
  Anything else means all processes should exit successfully.
116
116
  - `restartTries`: how many attempts to restart a process that dies will be made. Default: `0`.
117
117
  - `restartDelay`: how many milliseconds to wait between process restarts. Default: `0`.
118
118
  - `timestampFormat`: a [Unicode format](https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table)
119
- to use when prefixing with `time`. Default: `yyyy-MM-dd HH:mm:ss.ZZZ`
119
+ to use when prefixing with `time`. Default: `yyyy-MM-dd HH:mm:ss.SSS`
120
120
  - `additionalArguments`: list of additional arguments passed that will get replaced in each command. If not defined, no argument replacing will happen.
121
121
 
122
122
  > **Returns:** an object in the shape `{ result, commands }`.
@@ -172,6 +172,7 @@ It has the following properties:
172
172
  - `stderr`: an RxJS observable to the command's `stderr`.
173
173
  - `error`: an RxJS observable to the command's error events (e.g. when it fails to spawn).
174
174
  - `timer`: an RxJS observable to the command's timing events (e.g. starting, stopping).
175
+ - `stateChange`: an RxJS observable for changes to the command's `state` property.
175
176
  - `messages`: an object with the following properties:
176
177
 
177
178
  - `incoming`: an RxJS observable for the IPC messages received from the underlying process.
@@ -30,6 +30,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
30
30
  const lodash_1 = __importDefault(require("lodash"));
31
31
  const yargs_1 = __importDefault(require("yargs"));
32
32
  const helpers_1 = require("yargs/helpers");
33
+ const assert_1 = require("../src/assert");
33
34
  const defaults = __importStar(require("../src/defaults"));
34
35
  const index_1 = require("../src/index");
35
36
  const read_package_1 = require("./read-package");
@@ -128,7 +129,7 @@ const program = (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
128
129
  // Kill others
129
130
  'kill-others': {
130
131
  alias: 'k',
131
- describe: 'Kill other processes if one exits or dies.',
132
+ describe: 'Kill other processes once the first exits.',
132
133
  type: 'boolean',
133
134
  },
134
135
  'kill-others-on-fail': {
@@ -141,6 +142,10 @@ const program = (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
141
142
  type: 'string',
142
143
  default: defaults.killSignal,
143
144
  },
145
+ 'kill-timeout': {
146
+ describe: 'How many milliseconds to wait before forcing process terminating.',
147
+ type: 'number',
148
+ },
144
149
  // Prefix
145
150
  prefix: {
146
151
  alias: 'p',
@@ -209,10 +214,11 @@ const program = (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
209
214
  .group(['m', 'n', 'name-separator', 's', 'r', 'no-color', 'hide', 'g', 'timings', 'P', 'teardown'], 'General')
210
215
  .group(['p', 'c', 'l', 't', 'pad-prefix'], 'Prefix styling')
211
216
  .group(['i', 'default-input-target'], 'Input handling')
212
- .group(['k', 'kill-others-on-fail', 'kill-signal'], 'Killing other processes')
217
+ .group(['k', 'kill-others-on-fail', 'kill-signal', 'kill-timeout'], 'Killing other processes')
213
218
  .group(['restart-tries', 'restart-after'], 'Restarting')
214
219
  .epilogue(epilogue);
215
220
  const args = program.parseSync();
221
+ (0, assert_1.assertDeprecated)(args.nameSeparator === defaults.nameSeparator, 'name-separator', 'Use commas as name separators instead.');
216
222
  // Get names of commands by the specified separator
217
223
  const names = (args.names || '').split(args.nameSeparator);
218
224
  const additionalArguments = lodash_1.default.castArray(args['--'] ?? []).map(String);
@@ -227,12 +233,13 @@ if (!commands.length) {
227
233
  })), {
228
234
  handleInput: args.handleInput,
229
235
  defaultInputTarget: args.defaultInputTarget,
230
- killOthers: args.killOthers
236
+ killOthersOn: args.killOthers
231
237
  ? ['success', 'failure']
232
238
  : args.killOthersOnFail
233
239
  ? ['failure']
234
240
  : [],
235
241
  killSignal: args.killSignal,
242
+ killTimeout: args.killTimeout,
236
243
  maxProcesses: args.maxProcesses,
237
244
  raw: args.raw,
238
245
  hide: args.hide.split(','),
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Asserts that some condition is true, and if not, prints a warning about it being deprecated.
3
+ * The message is printed only once.
4
+ */
5
+ export declare function assertDeprecated(check: boolean, name: string, message: string): void;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.assertDeprecated = void 0;
4
+ const deprecations = new Set();
5
+ /**
6
+ * Asserts that some condition is true, and if not, prints a warning about it being deprecated.
7
+ * The message is printed only once.
8
+ */
9
+ function assertDeprecated(check, name, message) {
10
+ if (!check) {
11
+ // eslint-disable-next-line no-console
12
+ console.warn(`[concurrently] ${name} is deprecated. ${message}`);
13
+ deprecations.add(name);
14
+ }
15
+ }
16
+ exports.assertDeprecated = assertDeprecated;
@@ -117,6 +117,13 @@ export declare class Command implements CommandInfo {
117
117
  readonly stdout: Rx.Subject<Buffer>;
118
118
  readonly stderr: Rx.Subject<Buffer>;
119
119
  readonly timer: Rx.Subject<TimerEvent>;
120
+ /**
121
+ * A stream of changes to the `#state` property.
122
+ *
123
+ * Note that the command never goes back to the `stopped` state, therefore it's not a value
124
+ * that's emitted by this stream.
125
+ */
126
+ readonly stateChange: Rx.Subject<"started" | "errored" | "exited">;
120
127
  readonly messages: {
121
128
  incoming: Rx.Subject<MessageEvent>;
122
129
  outgoing: Rx.ReplaySubject<OutgoingMessageEvent>;
@@ -135,6 +142,7 @@ export declare class Command implements CommandInfo {
135
142
  * Starts this command, piping output, error and close events onto the corresponding observables.
136
143
  */
137
144
  start(): void;
145
+ private changeState;
138
146
  private maybeSetupIPC;
139
147
  /**
140
148
  * Sends a message to the underlying process once it starts.
@@ -47,6 +47,13 @@ class Command {
47
47
  stdout = new Rx.Subject();
48
48
  stderr = new Rx.Subject();
49
49
  timer = new Rx.Subject();
50
+ /**
51
+ * A stream of changes to the `#state` property.
52
+ *
53
+ * Note that the command never goes back to the `stopped` state, therefore it's not a value
54
+ * that's emitted by this stream.
55
+ */
56
+ stateChange = new Rx.Subject();
50
57
  messages = {
51
58
  incoming: new Rx.Subject(),
52
59
  outgoing: new Rx.ReplaySubject(),
@@ -76,7 +83,7 @@ class Command {
76
83
  */
77
84
  start() {
78
85
  const child = this.spawn(this.command, this.spawnOpts);
79
- this.state = 'started';
86
+ this.changeState('started');
80
87
  this.process = child;
81
88
  this.pid = child.pid;
82
89
  const startDate = new Date(Date.now());
@@ -88,7 +95,7 @@ class Command {
88
95
  const endDate = new Date(Date.now());
89
96
  this.timer.next({ startDate, endDate });
90
97
  this.error.next(event);
91
- this.state = 'errored';
98
+ this.changeState('errored');
92
99
  });
93
100
  Rx.fromEvent(child, 'close')
94
101
  .pipe(Rx.map((event) => event))
@@ -96,7 +103,7 @@ class Command {
96
103
  this.cleanUp();
97
104
  // Don't override error event
98
105
  if (this.state !== 'errored') {
99
- this.state = 'exited';
106
+ this.changeState('exited');
100
107
  }
101
108
  const endDate = new Date(Date.now());
102
109
  this.timer.next({ startDate, endDate });
@@ -119,6 +126,10 @@ class Command {
119
126
  pipeTo(Rx.fromEvent(child.stderr, 'data').pipe(Rx.map((event) => event)), this.stderr);
120
127
  this.stdin = child.stdin || undefined;
121
128
  }
129
+ changeState(state) {
130
+ this.state = state;
131
+ this.stateChange.next(state);
132
+ }
122
133
  maybeSetupIPC(child) {
123
134
  if (!this.ipc) {
124
135
  return [];
@@ -61,7 +61,7 @@ class CompletionListener {
61
61
  // All commands except the specified ones must exit successfully
62
62
  return events.every((event) => targetCommandsEvents.includes(event) || event.exitCode === 0);
63
63
  }
64
- // Only the specified commands must exit succesfully
64
+ // Only the specified commands must exit successfully
65
65
  return (targetCommandsEvents.length > 0 &&
66
66
  targetCommandsEvents.every((event) => event.exitCode === 0));
67
67
  }
@@ -73,6 +73,9 @@ class CompletionListener {
73
73
  * Commands that didn't spawn are filtered out.
74
74
  */
75
75
  listen(commands, abortSignal) {
76
+ if (!commands.length) {
77
+ return Promise.resolve([]);
78
+ }
76
79
  const abort = abortSignal &&
77
80
  Rx.fromEvent(abortSignal, 'abort', { once: true }).pipe(
78
81
  // The abort signal must happen before commands are killed, otherwise new commands
@@ -101,10 +101,6 @@ export type ConcurrentlyOptions = {
101
101
  * Defaults to the `tree-kill` module.
102
102
  */
103
103
  kill: KillProcess;
104
- /**
105
- * Signal to send to killed processes.
106
- */
107
- killSignal?: string;
108
104
  /**
109
105
  * List of additional arguments passed that will get replaced in each command.
110
106
  * If not defined, no argument replacing will happen.
@@ -7,6 +7,7 @@ exports.concurrently = void 0;
7
7
  const assert_1 = __importDefault(require("assert"));
8
8
  const lodash_1 = __importDefault(require("lodash"));
9
9
  const os_1 = require("os");
10
+ const rxjs_1 = require("rxjs");
10
11
  const tree_kill_1 = __importDefault(require("tree-kill"));
11
12
  const command_1 = require("./command");
12
13
  const expand_arguments_1 = require("./command-parser/expand-arguments");
@@ -75,7 +76,10 @@ function concurrently(baseCommands, baseOptions) {
75
76
  group: !!options.group,
76
77
  commands,
77
78
  });
78
- options.logger.output.subscribe(({ command, text }) => outputWriter.write(command, text));
79
+ options.logger.output
80
+ // Stop trying to write after there's been an error.
81
+ .pipe((0, rxjs_1.takeUntil)(outputWriter.error))
82
+ .subscribe(({ command, text }) => outputWriter.write(command, text));
79
83
  }
80
84
  const commandsLeft = commands.slice();
81
85
  const maxProcesses = Math.max(1, (typeof options.maxProcesses === 'string' && options.maxProcesses.endsWith('%')
@@ -73,7 +73,7 @@ class InputHandler {
73
73
  command = commandsMap.get(target);
74
74
  input = data;
75
75
  }
76
- if (command && command.stdin) {
76
+ if (command?.stdin) {
77
77
  command.stdin.write(input);
78
78
  }
79
79
  else {
@@ -11,13 +11,16 @@ export declare class KillOthers implements FlowController {
11
11
  private readonly abortController?;
12
12
  private readonly conditions;
13
13
  private readonly killSignal;
14
- constructor({ logger, abortController, conditions, killSignal, }: {
14
+ private readonly timeoutMs?;
15
+ constructor({ logger, abortController, conditions, killSignal, timeoutMs, }: {
15
16
  logger: Logger;
16
17
  abortController?: AbortController;
17
18
  conditions: ProcessCloseCondition | ProcessCloseCondition[];
18
19
  killSignal: string | undefined;
20
+ timeoutMs?: number;
19
21
  });
20
22
  handle(commands: Command[]): {
21
23
  commands: Command[];
22
24
  };
25
+ private maybeForceKill;
23
26
  }
@@ -15,11 +15,13 @@ class KillOthers {
15
15
  abortController;
16
16
  conditions;
17
17
  killSignal;
18
- constructor({ logger, abortController, conditions, killSignal, }) {
18
+ timeoutMs;
19
+ constructor({ logger, abortController, conditions, killSignal, timeoutMs, }) {
19
20
  this.logger = logger;
20
21
  this.abortController = abortController;
21
22
  this.conditions = lodash_1.default.castArray(conditions);
22
23
  this.killSignal = killSignal;
24
+ this.timeoutMs = timeoutMs;
23
25
  }
24
26
  handle(commands) {
25
27
  const conditions = this.conditions.filter((condition) => condition === 'failure' || condition === 'success');
@@ -33,9 +35,23 @@ class KillOthers {
33
35
  if (killableCommands.length) {
34
36
  this.logger.logGlobalEvent(`Sending ${this.killSignal || 'SIGTERM'} to other processes..`);
35
37
  killableCommands.forEach((command) => command.kill(this.killSignal));
38
+ this.maybeForceKill(killableCommands);
36
39
  }
37
40
  }));
38
41
  return { commands };
39
42
  }
43
+ maybeForceKill(commands) {
44
+ // No need to force kill when the signal already is SIGKILL.
45
+ if (!this.timeoutMs || this.killSignal === 'SIGKILL') {
46
+ return;
47
+ }
48
+ setTimeout(() => {
49
+ const killableCommands = commands.filter((command) => command_1.Command.canKill(command));
50
+ if (killableCommands) {
51
+ this.logger.logGlobalEvent(`Sending SIGKILL to ${killableCommands.length} processes..`);
52
+ killableCommands.forEach((command) => command.kill('SIGKILL'));
53
+ }
54
+ }, this.timeoutMs);
55
+ }
40
56
  }
41
57
  exports.KillOthers = KillOthers;
@@ -0,0 +1,20 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ import { Writable } from 'stream';
4
+ import { Command } from '../command';
5
+ import { FlowController } from './flow-controller';
6
+ /**
7
+ * Kills processes and aborts further command spawning on output stream error (namely, SIGPIPE).
8
+ */
9
+ export declare class OutputErrorHandler implements FlowController {
10
+ private readonly outputStream;
11
+ private readonly abortController;
12
+ constructor({ abortController, outputStream, }: {
13
+ abortController: AbortController;
14
+ outputStream: Writable;
15
+ });
16
+ handle(commands: Command[]): {
17
+ commands: Command[];
18
+ onFinish(): void;
19
+ };
20
+ }
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OutputErrorHandler = void 0;
4
+ const observables_1 = require("../observables");
5
+ /**
6
+ * Kills processes and aborts further command spawning on output stream error (namely, SIGPIPE).
7
+ */
8
+ class OutputErrorHandler {
9
+ outputStream;
10
+ abortController;
11
+ constructor({ abortController, outputStream, }) {
12
+ this.abortController = abortController;
13
+ this.outputStream = outputStream;
14
+ }
15
+ handle(commands) {
16
+ const subscription = (0, observables_1.fromSharedEvent)(this.outputStream, 'error').subscribe(() => {
17
+ commands.forEach((command) => command.kill());
18
+ // Avoid further commands from spawning, e.g. if `RestartProcess` is used.
19
+ this.abortController.abort();
20
+ });
21
+ return {
22
+ commands,
23
+ onFinish: () => subscription.unsubscribe(),
24
+ };
25
+ }
26
+ }
27
+ exports.OutputErrorHandler = OutputErrorHandler;
@@ -53,7 +53,7 @@ class RestartProcess {
53
53
  });
54
54
  commands
55
55
  .map((command) => command.close.pipe((0, operators_1.take)(this.tries), (0, operators_1.takeWhile)(({ exitCode }) => exitCode !== 0)))
56
- .map((failure, index) => Rx.merge(
56
+ .forEach((failure, index) => Rx.merge(
57
57
  // Delay the emission (so that the restarts happen on time),
58
58
  // explicitly telling the subscriber that a restart is needed
59
59
  failure.pipe(delayOperator, (0, operators_1.map)(() => true)),
@@ -56,11 +56,23 @@ export type ConcurrentlyOptions = Omit<BaseConcurrentlyOptions, 'abortSignal' |
56
56
  */
57
57
  restartTries?: number;
58
58
  /**
59
- * Under which condition(s) should other commands be killed when the first one exits.
60
- *
59
+ * @deprecated Use `killOthersOn` instead.
61
60
  * @see KillOthers
62
61
  */
63
62
  killOthers?: ProcessCloseCondition | ProcessCloseCondition[];
63
+ /**
64
+ * Once the first command exits with one of these statuses, kill other commands.
65
+ * @see KillOthers
66
+ */
67
+ killOthersOn?: ProcessCloseCondition | ProcessCloseCondition[];
68
+ /**
69
+ * Signal to send to killed processes.
70
+ */
71
+ killSignal?: string;
72
+ /**
73
+ * How many milliseconds to wait before killing processes.
74
+ */
75
+ killTimeout?: number;
64
76
  /**
65
77
  * Whether to output timing information for processes.
66
78
  *
package/dist/src/index.js CHANGED
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.RestartProcess = exports.LogTimings = exports.LogOutput = exports.LogExit = exports.LogError = exports.KillOthers = exports.KillOnSignal = exports.InputHandler = exports.Command = exports.Logger = exports.createConcurrently = exports.concurrently = void 0;
7
7
  const lodash_1 = __importDefault(require("lodash"));
8
+ const assert_1 = require("./assert");
8
9
  const command_1 = require("./command");
9
10
  Object.defineProperty(exports, "Command", { enumerable: true, get: function () { return command_1.Command; } });
10
11
  const concurrently_1 = require("./concurrently");
@@ -24,12 +25,14 @@ Object.defineProperty(exports, "LogOutput", { enumerable: true, get: function ()
24
25
  const log_timings_1 = require("./flow-control/log-timings");
25
26
  Object.defineProperty(exports, "LogTimings", { enumerable: true, get: function () { return log_timings_1.LogTimings; } });
26
27
  const logger_padding_1 = require("./flow-control/logger-padding");
28
+ const output_error_handler_1 = require("./flow-control/output-error-handler");
27
29
  const restart_process_1 = require("./flow-control/restart-process");
28
30
  Object.defineProperty(exports, "RestartProcess", { enumerable: true, get: function () { return restart_process_1.RestartProcess; } });
29
31
  const teardown_1 = require("./flow-control/teardown");
30
32
  const logger_1 = require("./logger");
31
33
  Object.defineProperty(exports, "Logger", { enumerable: true, get: function () { return logger_1.Logger; } });
32
34
  function concurrently(commands, options = {}) {
35
+ (0, assert_1.assertDeprecated)(options.killOthers === undefined, 'killOthers', 'Use killOthersOn instead.');
33
36
  // To avoid empty strings from hiding the output of commands that don't have a name,
34
37
  // keep in the list of commands to hide only strings with some length.
35
38
  // This might happen through the CLI when no `--hide` argument is specified, for example.
@@ -46,6 +49,7 @@ function concurrently(commands, options = {}) {
46
49
  logger.toggleColors(false);
47
50
  }
48
51
  const abortController = new AbortController();
52
+ const outputStream = options.outputStream || process.stdout;
49
53
  return (0, concurrently_1.concurrently)(commands, {
50
54
  maxProcesses: options.maxProcesses,
51
55
  raw: options.raw,
@@ -53,7 +57,7 @@ function concurrently(commands, options = {}) {
53
57
  cwd: options.cwd,
54
58
  hide,
55
59
  logger,
56
- outputStream: options.outputStream || process.stdout,
60
+ outputStream,
57
61
  group: options.group,
58
62
  abortSignal: abortController.signal,
59
63
  controllers: [
@@ -76,10 +80,12 @@ function concurrently(commands, options = {}) {
76
80
  }),
77
81
  new kill_others_1.KillOthers({
78
82
  logger,
79
- conditions: options.killOthers || [],
83
+ conditions: options.killOthersOn || options.killOthers || [],
84
+ timeoutMs: options.killTimeout,
80
85
  killSignal: options.killSignal,
81
86
  abortController,
82
87
  }),
88
+ new output_error_handler_1.OutputErrorHandler({ abortController, outputStream }),
83
89
  new log_timings_1.LogTimings({
84
90
  logger: options.timings ? logger : undefined,
85
91
  timestampFormat: options.timestampFormat,
@@ -77,9 +77,9 @@ class Logger {
77
77
  const prefixLength = this.commandLength - ellipsis.length;
78
78
  const endLength = Math.floor(prefixLength / 2);
79
79
  const beginningLength = prefixLength - endLength;
80
- const beginnning = text.slice(0, beginningLength);
80
+ const beginning = text.slice(0, beginningLength);
81
81
  const end = text.slice(text.length - endLength, text.length);
82
- return beginnning + ellipsis + end;
82
+ return beginning + ellipsis + end;
83
83
  }
84
84
  getPrefixesFor(command) {
85
85
  return {
@@ -121,7 +121,7 @@ class Logger {
121
121
  }
122
122
  colorText(command, text) {
123
123
  let color;
124
- if (command.prefixColor && command.prefixColor.startsWith('#')) {
124
+ if (command.prefixColor?.startsWith('#')) {
125
125
  color = this.chalk.hex(command.prefixColor);
126
126
  }
127
127
  else {
@@ -0,0 +1,9 @@
1
+ /// <reference types="node" />
2
+ import EventEmitter from 'events';
3
+ import { Observable } from 'rxjs';
4
+ /**
5
+ * Creates an observable for a specific event of an `EventEmitter` instance.
6
+ *
7
+ * The underlying event listener is set up only once across the application for that event emitter/name pair.
8
+ */
9
+ export declare function fromSharedEvent(emitter: EventEmitter, event: string): Observable<unknown>;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fromSharedEvent = void 0;
4
+ const rxjs_1 = require("rxjs");
5
+ const sharedEvents = new WeakMap();
6
+ /**
7
+ * Creates an observable for a specific event of an `EventEmitter` instance.
8
+ *
9
+ * The underlying event listener is set up only once across the application for that event emitter/name pair.
10
+ */
11
+ function fromSharedEvent(emitter, event) {
12
+ let emitterEvents = sharedEvents.get(emitter);
13
+ if (!emitterEvents) {
14
+ emitterEvents = new Map();
15
+ sharedEvents.set(emitter, emitterEvents);
16
+ }
17
+ let observable = emitterEvents.get(event);
18
+ if (!observable) {
19
+ observable = (0, rxjs_1.fromEvent)(emitter, event).pipe((0, rxjs_1.share)());
20
+ emitterEvents.set(event, observable);
21
+ }
22
+ return observable;
23
+ }
24
+ exports.fromSharedEvent = fromSharedEvent;
@@ -1,4 +1,5 @@
1
1
  /// <reference types="node" />
2
+ import * as Rx from 'rxjs';
2
3
  import { Writable } from 'stream';
3
4
  import { Command } from './command';
4
5
  /**
@@ -9,11 +10,14 @@ export declare class OutputWriter {
9
10
  private readonly group;
10
11
  readonly buffers: string[][];
11
12
  activeCommandIndex: number;
13
+ readonly error: Rx.Observable<unknown>;
14
+ private get errored();
12
15
  constructor({ outputStream, group, commands, }: {
13
16
  outputStream: Writable;
14
17
  group: boolean;
15
18
  commands: Command[];
16
19
  });
20
+ private ensureWritable;
17
21
  write(command: Command | undefined, text: string): void;
18
22
  private flushBuffer;
19
23
  }
@@ -25,6 +25,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.OutputWriter = void 0;
27
27
  const Rx = __importStar(require("rxjs"));
28
+ const observables_1 = require("./observables");
28
29
  /**
29
30
  * Class responsible for actually writing output onto a writable stream.
30
31
  */
@@ -33,8 +34,14 @@ class OutputWriter {
33
34
  group;
34
35
  buffers;
35
36
  activeCommandIndex = 0;
37
+ error;
38
+ get errored() {
39
+ return this.outputStream.errored;
40
+ }
36
41
  constructor({ outputStream, group, commands, }) {
37
42
  this.outputStream = outputStream;
43
+ this.ensureWritable();
44
+ this.error = (0, observables_1.fromSharedEvent)(this.outputStream, 'error');
38
45
  this.group = group;
39
46
  this.buffers = commands.map(() => []);
40
47
  if (this.group) {
@@ -53,7 +60,13 @@ class OutputWriter {
53
60
  });
54
61
  }
55
62
  }
63
+ ensureWritable() {
64
+ if (this.errored) {
65
+ throw new TypeError('outputStream is in errored state', { cause: this.errored });
66
+ }
67
+ }
56
68
  write(command, text) {
69
+ this.ensureWritable();
57
70
  if (this.group && command) {
58
71
  if (command.index <= this.activeCommandIndex) {
59
72
  this.outputStream.write(text);
@@ -68,7 +81,9 @@ class OutputWriter {
68
81
  }
69
82
  }
70
83
  flushBuffer(index) {
71
- this.buffers[index].forEach((t) => this.outputStream.write(t));
84
+ if (!this.errored) {
85
+ this.buffers[index].forEach((t) => this.outputStream.write(t));
86
+ }
72
87
  this.buffers[index] = [];
73
88
  }
74
89
  }
@@ -34,7 +34,7 @@ function* createColorGenerator(customColors) {
34
34
  const lastCustomColor = customColors[customColors.length - 1] || '';
35
35
  if (lastCustomColor !== 'auto') {
36
36
  while (true) {
37
- yield lastCustomColor; // If last custom color was not "auto" then return same color forever, to maintain existing behaviour
37
+ yield lastCustomColor; // If last custom color was not "auto" then return same color forever, to maintain existing behavior
38
38
  }
39
39
  }
40
40
  // Finish the initial set(s) of auto colors to avoid repetition
package/dist/src/spawn.js CHANGED
@@ -38,7 +38,7 @@ const getSpawnOpts = ({ colorSupport = supports_color_1.default.stdout, cwd, pro
38
38
  return {
39
39
  cwd: cwd || process.cwd(),
40
40
  stdio: stdioValues,
41
- ...(/^win/.test(process.platform) && { detached: false }),
41
+ ...(process.platform.startsWith('win') && { detached: false }),
42
42
  env: {
43
43
  ...(colorSupport ? { FORCE_COLOR: colorSupport.level.toString() } : {}),
44
44
  ...process.env,
package/docs/README.md CHANGED
@@ -6,7 +6,9 @@ These articles cover using concurrently through CLI:
6
6
 
7
7
  - [Prefixing](./cli/prefixing.md)
8
8
  - [Output Control](./cli/output-control.md)
9
+ - [Success Conditions](./cli/success.md)
9
10
  - [Shortcuts](./cli/shortcuts.md)
11
+ - [Terminating Commands](./cli/terminating.md)
10
12
  - [Restarting Commands](./cli/restarting.md)
11
13
  - [Input Handling](./cli/input-handling.md)
12
14
  - [Passthrough Arguments](./cli/passthrough-arguments.md)
@@ -4,7 +4,7 @@ By default, concurrently doesn't send input to any commands it spawns.<br/>
4
4
  In the below example, typing `rs` to manually restart [nodemon](https://nodemon.io/) does nothing:
5
5
 
6
6
  ```bash
7
- $ concurrently "nodemon" "npm run watch-js"
7
+ $ concurrently 'nodemon' 'npm run watch-js'
8
8
  rs
9
9
  ```
10
10
 
@@ -12,7 +12,7 @@ To turn on input handling, it's necessary to set the `--handle-input`/`-i` flag.
12
12
  This will send `rs` to the first command:
13
13
 
14
14
  ```bash
15
- $ concurrently --handle-input "nodemon" "npm run watch-js"
15
+ $ concurrently --handle-input 'nodemon' 'npm run watch-js'
16
16
  rs
17
17
  ```
18
18
 
@@ -20,14 +20,14 @@ To send input to a different command instead, it's possible to prefix the input
20
20
  For example, the below sends `rs` to the second command:
21
21
 
22
22
  ```bash
23
- $ concurrently --handle-input "npm run watch-js" "nodemon"
23
+ $ concurrently --handle-input 'npm run watch-js' 'nodemon'
24
24
  1:rs
25
25
  ```
26
26
 
27
27
  If the command has a name, it's also possible to target it using that command's name:
28
28
 
29
29
  ```bash
30
- $ concurrently --handle-input --names js,server "npm run watch-js" "nodemon"
30
+ $ concurrently --handle-input --names js,server 'npm run watch-js' 'nodemon'
31
31
  server:rs
32
32
  ```
33
33
 
@@ -35,6 +35,6 @@ It's also possible to change the default command that receives input.<br/>
35
35
  To do this, set the `--default-input-target` flag to a command's index or name.
36
36
 
37
37
  ```bash
38
- $ concurrently --handle-input --default-input-target 1 "npm run watch-js" "nodemon"
38
+ $ concurrently --handle-input --default-input-target 1 'npm run watch-js' 'nodemon'
39
39
  rs
40
40
  ```
@@ -7,7 +7,7 @@ concurrently offers a few ways to control a command's output.
7
7
  A command's outputs (and all its events) can be hidden by using the `--hide` flag.
8
8
 
9
9
  ```bash
10
- $ concurrently --hide 0 "echo Hello there" "echo 'General Kenobi!'"
10
+ $ concurrently --hide 0 'echo Hello there' 'echo General Kenobi!'
11
11
  [1] General Kenobi!
12
12
  [1] echo 'General Kenobi!' exited with code 0
13
13
  ```
@@ -18,7 +18,7 @@ It might be useful at times to make sure that the commands outputs are grouped t
18
18
  This can be done with the `--group` flag.
19
19
 
20
20
  ```bash
21
- $ concurrently --group "echo Hello there && sleep 2 && echo 'General Kenobi!'" "echo hi Star Wars fans"
21
+ $ concurrently --group 'echo Hello there && sleep 2 && echo General Kenobi!' 'echo hi Star Wars fans'
22
22
  [0] Hello there
23
23
  [0] General Kenobi!
24
24
  [0] echo Hello there && sleep 2 && echo 'General Kenobi!' exited with code 0
@@ -31,5 +31,5 @@ $ concurrently --group "echo Hello there && sleep 2 && echo 'General Kenobi!'" "
31
31
  When piping concurrently's outputs to another command or file, you might want to force it to not use colors, as these can break the other command's parsing, or reduce the legibility of the output in non-terminal environments.
32
32
 
33
33
  ```bash
34
- $ concurrently -c red,blue --no-color "echo Hello there" "echo 'General Kenobi!'"
34
+ $ concurrently -c red,blue --no-color 'echo Hello there' 'echo General Kenobi!'
35
35
  ```
@@ -5,7 +5,7 @@
5
5
  concurrently will by default prefix each command's outputs with a zero-based index, wrapped in square brackets:
6
6
 
7
7
  ```bash
8
- $ concurrently "echo Hello there" "echo 'General Kenobi!'"
8
+ $ concurrently 'echo Hello there' "echo 'General Kenobi!'"
9
9
  [0] Hello there
10
10
  [1] General Kenobi!
11
11
  [0] echo Hello there exited with code 0
@@ -15,7 +15,7 @@ $ concurrently "echo Hello there" "echo 'General Kenobi!'"
15
15
  If you've given the commands names, they are used instead:
16
16
 
17
17
  ```bash
18
- $ concurrently --names one,two "echo Hello there" "echo 'General Kenobi!'"
18
+ $ concurrently --names one,two 'echo Hello there' "echo 'General Kenobi!'"
19
19
  [one] Hello there
20
20
  [two] General Kenobi!
21
21
  [one] echo Hello there exited with code 0
@@ -36,7 +36,7 @@ There are other prefix styles available too:
36
36
  Any of these can be used by setting the `--prefix`/`-p` flag. For example:
37
37
 
38
38
  ```bash
39
- $ concurrently --prefix pid "echo Hello there" "echo 'General Kenobi!'"
39
+ $ concurrently --prefix pid 'echo Hello there' 'echo General Kenobi!'
40
40
  [2222] Hello there
41
41
  [2223] General Kenobi!
42
42
  [2222] echo Hello there exited with code 0
@@ -47,7 +47,7 @@ It's also possible to have a prefix based on a template. Any of the styles liste
47
47
  Doing so will also remove the square brackets:
48
48
 
49
49
  ```bash
50
- $ concurrently --prefix "{index}-{pid}" "echo Hello there" "echo 'General Kenobi!'"
50
+ $ concurrently --prefix '{index}-{pid}' 'echo Hello there' 'echo General Kenobi!'
51
51
  0-2222 Hello there
52
52
  1-2223 General Kenobi!
53
53
  0-2222 echo Hello there exited with code 0
@@ -62,7 +62,7 @@ This can be changed by using the `--prefix-colors`/`-c` flag, which takes a comm
62
62
  The available values are color names (e.g. `green`, `magenta`, `gray`, etc), a hex value (such as `#23de43`), or `auto`, to automatically select a color.
63
63
 
64
64
  ```bash
65
- $ concurrently -c red,blue "echo Hello there" "echo 'General Kenobi!'"
65
+ $ concurrently -c red,blue 'echo Hello there' 'echo General Kenobi!'
66
66
  ```
67
67
 
68
68
  <details>
@@ -82,7 +82,7 @@ $ concurrently -c red,blue "echo Hello there" "echo 'General Kenobi!'"
82
82
  Colors can take modifiers too. Several can be applied at once by prepending `.<modifier 1>.<modifier 2>` and so on.
83
83
 
84
84
  ```bash
85
- $ concurrently -c red,bold.blue.dim "echo Hello there" "echo 'General Kenobi!'"
85
+ $ concurrently -c red,bold.blue.dim 'echo Hello there' 'echo General Kenobi!'
86
86
  ```
87
87
 
88
88
  <details>
@@ -98,10 +98,10 @@ $ concurrently -c red,bold.blue.dim "echo Hello there" "echo 'General Kenobi!'"
98
98
  - `underline`
99
99
  </details>
100
100
 
101
- A background color can be set in a similary fashion.
101
+ A background color can be set in a similarly fashion.
102
102
 
103
103
  ```bash
104
- $ concurrently -c bgGray,red.bgBlack "echo Hello there" "echo 'General Kenobi!'"
104
+ $ concurrently -c bgGray,red.bgBlack 'echo Hello there' 'echo General Kenobi!'
105
105
  ```
106
106
 
107
107
  <details>
@@ -124,7 +124,7 @@ When using the `command` prefix style, it's possible that it'll be too long.<br/
124
124
  It can be limited by setting the `--prefix-length`/`-l` flag:
125
125
 
126
126
  ```bash
127
- $ concurrently -p command -l 10 "echo Hello there" "echo 'General Kenobi!'"
127
+ $ concurrently -p command -l 10 'echo Hello there' 'echo General Kenobi!'
128
128
  [echo..here] Hello there
129
129
  [echo..bi!'] General Kenobi!
130
130
  [echo..here] echo Hello there exited with code 0
@@ -135,7 +135,7 @@ It's also possible that some prefixes are too short, and you want all of them to
135
135
  This can be done by setting the `--pad-prefix` flag:
136
136
 
137
137
  ```bash
138
- $ concurrently -n foo,barbaz --pad-prefix "echo Hello there" "echo 'General Kenobi!'"
138
+ $ concurrently -n foo,barbaz --pad-prefix 'echo Hello there' 'echo General Kenobi!'
139
139
  [foo ] Hello there
140
140
  [foo ] echo Hello there exited with code 0
141
141
  [barbaz] General Kenobi!
@@ -4,7 +4,7 @@ Sometimes it's useful to have commands that exited with a non-zero status to res
4
4
  concurrently lets you configure how many times you wish for such a command to restart through the `--restart-tries` flag:
5
5
 
6
6
  ```bash
7
- $ concurrently --restart-tries 2 "exit 1"
7
+ $ concurrently --restart-tries 2 'exit 1'
8
8
  [0] exit 1 exited with code 1
9
9
  [0] exit 1 restarted
10
10
  [0] exit 1 exited with code 1
@@ -16,7 +16,7 @@ Sometimes, it might be interesting to have commands wait before restarting.<br/>
16
16
  To do this, simply set `--restart-after` to a the number of milliseconds you'd like to delay restarting.
17
17
 
18
18
  ```bash
19
- $ concurrently -p time --restart-tries 1 --restart-after 3000 "exit 1"
19
+ $ concurrently -p time --restart-tries 1 --restart-after 3000 'exit 1'
20
20
  [2024-09-01 23:43:55.871] exit 1 exited with code 1
21
21
  [2024-09-01 23:43:58.874] exit 1 restarted
22
22
  [2024-09-01 23:43:58.891] exit 1 exited with code 1
@@ -26,7 +26,7 @@ If a command is not having success spawning, you might want to instead apply an
26
26
  Set `--restart-after exponential` to have commands respawn with a `2^N` seconds delay.
27
27
 
28
28
  ```bash
29
- $ concurrently -p time --restart-tries 3 --restart-after exponential "exit 1"
29
+ $ concurrently -p time --restart-tries 3 --restart-after exponential 'exit 1'
30
30
 
31
31
  [2024-09-01 23:49:01.124] exit 1 exited with code 1
32
32
  [2024-09-01 23:49:02.127] exit 1 restarted
@@ -35,9 +35,9 @@ For example, given the following `package.json` contents:
35
35
  It's possible to run some of these with the following command line:
36
36
 
37
37
  ```bash
38
- $ concurrently "pnpm:lint:js"
38
+ $ concurrently 'pnpm:lint:js'
39
39
  # Is equivalent to
40
- $ concurrently -n lint:js "pnpm run lint:js"
40
+ $ concurrently -n lint:js 'pnpm run lint:js'
41
41
  ```
42
42
 
43
43
  Note that the command automatically receives a name equal to the script name.
@@ -46,17 +46,17 @@ If you have several scripts with similar name patterns, you can use the `*` wild
46
46
  The spawned commands will receive names set to whatever the `*` wildcard matched.
47
47
 
48
48
  ```bash
49
- $ concurrently "npm:lint:fix:*"
49
+ $ concurrently 'npm:lint:fix:*'
50
50
  # is equivalent to
51
- $ concurrently -n js,ts "npm run lint:fix:js" "npm run lint:fix:ts"
51
+ $ concurrently -n js,ts 'npm run lint:fix:js' 'npm run lint:fix:ts'
52
52
  ```
53
53
 
54
54
  If you specify a command name when using wildcards, it'll be a prefix of what the `*` wildcard matched:
55
55
 
56
56
  ```bash
57
- $ concurrently -n fix: "npm:lint:fix:*"
57
+ $ concurrently -n fix: 'npm:lint:fix:*'
58
58
  # is equivalent to
59
- $ concurrently -n fix:js,fix:ts "npm run lint:fix:js" "npm run lint:fix:ts"
59
+ $ concurrently -n fix:js,fix:ts 'npm run lint:fix:js' 'npm run lint:fix:ts'
60
60
  ```
61
61
 
62
62
  Filtering out commands matched by wildcard is also possible. Do this with by including `(!<some pattern>)` in the command line:
@@ -64,7 +64,7 @@ Filtering out commands matched by wildcard is also possible. Do this with by inc
64
64
  ```bash
65
65
  $ concurrently 'yarn:lint:*(!fix)'
66
66
  # is equivalent to
67
- $ concurrently -n js,ts "yarn run lint:js" "yarn run lint:ts"
67
+ $ concurrently -n js,ts 'yarn run lint:js' 'yarn run lint:ts'
68
68
  ```
69
69
 
70
70
  > [!NOTE]
@@ -0,0 +1,73 @@
1
+ # Success Conditions
2
+
3
+ When you're using concurrently in shell scripts or CI pipelines, the exit code matters.
4
+ It determines whether the next step runs, or if the script stops with a failure.
5
+
6
+ You can control concurrently's exit code using the `--success` flag.
7
+ This tells it **which command(s)** must succeed (exit with code `0`) for concurrently to return success overall.
8
+
9
+ There are several possible values:
10
+
11
+ ## `all`
12
+
13
+ All commands must exit with code `0`.
14
+ This is the default value.
15
+
16
+ ## `first`
17
+
18
+ The first command to exit must do so with code `0`.
19
+
20
+ ```bash
21
+ # ✅ Exits with code 0 — second command exits first and succeeds
22
+ $ concurrently --success first 'sleep 1 && exit 1' 'exit 0'
23
+
24
+ # ❌ Exits with a non-zero code — second command exits first, but with code 1
25
+ $ concurrently --success first 'sleep 1 && exit 0' 'exit 1'
26
+ ```
27
+
28
+ ## `last`
29
+
30
+ The last command to exit must do so with code `0`.
31
+
32
+ ```bash
33
+ # ✅ Exits with code 0 - first command exits last and succeeds
34
+ $ concurrently --success last 'sleep 1 && exit 0' 'exit 1'
35
+
36
+ # ❌ Exits with a non-zero code — first command exits last, but with code 1
37
+ $ concurrently --success last 'sleep 1 && exit 1' 'exit 0'
38
+ ```
39
+
40
+ ## `command-{name}` or `command-{index}`
41
+
42
+ A specific command, by name or index, must exit with code `0`.
43
+
44
+ ```bash
45
+ # Exits with code 0 only if 'npm test' (index 1) passes.
46
+ $ concurrently --success command-1 --kill-others 'npm run server' 'npm test'
47
+
48
+ # Exits with code 0 only if 'test' command passes.
49
+ $ concurrently --success command-test --names server,test --kill-others \
50
+ 'npm start' \
51
+ 'npm test'
52
+ ```
53
+
54
+ > [!TIP]
55
+ > Use `--kill-others` to kill a long-running process, such as a server, once tests pass.
56
+
57
+ ## `!command-{name}` or `!command-{index}`
58
+
59
+ All but a specific command, by name or index, must exit with code `0`.
60
+
61
+ ```bash
62
+ # Ignores 'npm start'; all others must succeed
63
+ $ concurrently --success '!command-2' --kill-others \
64
+ 'npm test' \
65
+ 'npm build' \
66
+ 'npm start'
67
+
68
+ # Ignores 'server'; all others must succeed
69
+ $ concurrently --success '!command-server' --names test,build,server --kill-others \
70
+ 'npm test' \
71
+ 'npm build' \
72
+ 'npm start'
73
+ ```
@@ -0,0 +1,52 @@
1
+ # Terminating Commands
2
+
3
+ It's possible to have concurrently terminate other commands when one of them exits.<br/>
4
+ This can be done in the following ways:
5
+
6
+ ## Terminating on either success or error
7
+
8
+ By using the `--kill-others` flag, concurrently will terminate other commands once the first one exits,
9
+ no matter the exit code.<br/>
10
+ This is useful to terminate the server process once the test is done.
11
+
12
+ ```bash
13
+ $ concurrently --kill-others --names server,test 'npm start' 'npm test'
14
+ ```
15
+
16
+ ## Terminating on error only
17
+
18
+ By using the `--kill-others-on-fail` flag, concurrently will terminate other commands any command
19
+ exits with a non-zero code.<br/>
20
+ This is useful if you're building multiple applications, and you want to abort the others once you know
21
+ that any of them is broken.
22
+
23
+ ```bash
24
+ $ concurrently --kill-others-on-fail 'npm run app1:build' 'npm run app2:build'
25
+ ```
26
+
27
+ ## Configuring termination
28
+
29
+ ### Kill Signal
30
+
31
+ It's possible to configure which signal you want to send when terminating commands with the `--kill-signal` flag.
32
+ The default is `SIGTERM`, but it's also possible to send `SIGKILL`.
33
+
34
+ ```bash
35
+ $ concurrently --kill-others --kill-signal SIGKILL 'npm start' 'npm test'
36
+ ```
37
+
38
+ ### Timeout
39
+
40
+ In case you have a misbehaving process that ignores the kill signal, you can force kill it after some
41
+ timeout (in milliseconds) by using the `--kill-timeout` flag.
42
+ This sends a `SIGKILL`, which cannot be caught.
43
+
44
+ ```bash
45
+ $ concurrently --kill-others --kill-timeout 1000 'sleep 1 && echo bye' './misbehaving'
46
+ [0] bye
47
+ [0] sleep 1 && echo bye exited with code 0
48
+ --> Sending SIGTERM to other processes..
49
+ [1] IGNORING SIGNAL
50
+ --> Sending SIGKILL to 1 processes..
51
+ [1] ./misbehaving exited with code SIGKILL
52
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "concurrently",
3
- "version": "9.1.2",
3
+ "version": "9.2.0",
4
4
  "description": "Run commands concurrently",
5
5
  "packageManager": "pnpm@8.15.9+sha256.daa27a0b541bc635323ff96c2ded995467ff9fe6d69ff67021558aa9ad9dcc36",
6
6
  "main": "index.js",
@@ -52,10 +52,10 @@
52
52
  },
53
53
  "devDependencies": {
54
54
  "@hirez_io/observer-spy": "^2.2.0",
55
- "@jest/types": "^29.6.3",
55
+ "@jest/types": "^30.0.0",
56
56
  "@swc/core": "^1.7.23",
57
57
  "@swc/jest": "^0.2.36",
58
- "@types/jest": "^29.5.6",
58
+ "@types/jest": "^30.0.0",
59
59
  "@types/lodash": "^4.17.7",
60
60
  "@types/node": "^18.19.50",
61
61
  "@types/shell-quote": "^1.7.5",
@@ -65,7 +65,7 @@
65
65
  "@typescript-eslint/parser": "^7.18.0",
66
66
  "coveralls-next": "^4.2.1",
67
67
  "ctrlc-wrapper": "^0.0.4",
68
- "esbuild": "~0.23.1",
68
+ "esbuild": "~0.25.0",
69
69
  "eslint": "^8.57.0",
70
70
  "eslint-config-prettier": "^9.1.0",
71
71
  "eslint-plugin-import": "^2.30.0",
@@ -73,7 +73,7 @@
73
73
  "eslint-plugin-prettier": "^5.2.1",
74
74
  "eslint-plugin-simple-import-sort": "^10.0.0",
75
75
  "husky": "^9.1.5",
76
- "jest": "^29.7.0",
76
+ "jest": "^30.0.0",
77
77
  "jest-create-mock-instance": "^2.0.0",
78
78
  "lint-staged": "^15.2.10",
79
79
  "prettier": "^3.0.3",