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 +19 -7
- package/dist/bin/concurrently.js +5 -5
- package/dist/bin/epilogue.js +9 -1
- package/dist/src/command-parser/expand-npm-wildcard.js +1 -1
- package/dist/src/command.d.ts +1 -1
- package/dist/src/command.js +2 -2
- package/dist/src/completion-listener.js +4 -4
- package/dist/src/concurrently.js +6 -7
- package/dist/src/flow-control/input-handler.d.ts +1 -4
- package/dist/src/flow-control/input-handler.js +3 -3
- package/dist/src/flow-control/kill-on-signal.js +4 -4
- package/dist/src/flow-control/kill-others.js +5 -5
- package/dist/src/flow-control/log-error.js +1 -1
- package/dist/src/flow-control/log-exit.js +1 -1
- package/dist/src/flow-control/log-output.js +3 -3
- package/dist/src/flow-control/log-timings.js +3 -3
- package/dist/src/flow-control/restart-process.js +3 -3
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/logger.js +7 -7
- package/dist/src/output-writer.js +2 -2
- package/dist/src/prefix-color-selector.d.ts +11 -0
- package/dist/src/prefix-color-selector.js +92 -0
- package/index.js +4 -3
- package/index.mjs +5 -4
- package/package.json +24 -16
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
|
-
|
|
153
|
-
|
|
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
|
-
|
|
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,
|
|
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.
|
package/dist/bin/concurrently.js
CHANGED
|
@@ -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
|
-
'
|
|
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
|
|
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
|
-
'
|
|
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,
|
package/dist/bin/epilogue.js
CHANGED
|
@@ -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]));
|
package/dist/src/command.d.ts
CHANGED
package/dist/src/command.js
CHANGED
|
@@ -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
|
}
|
package/dist/src/concurrently.js
CHANGED
|
@@ -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:
|
|
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;
|
package/dist/src/index.d.ts
CHANGED
|
@@ -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 {
|
|
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.
|
|
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");
|
package/dist/src/logger.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
+
"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.
|
|
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
|
-
"@
|
|
62
|
-
"@swc/core": "^1.2.
|
|
63
|
+
"@hirez_io/observer-spy": "^2.2.0",
|
|
64
|
+
"@swc/core": "^1.2.224",
|
|
63
65
|
"@swc/jest": "^0.2.21",
|
|
64
|
-
"@types/jest": "^
|
|
66
|
+
"@types/jest": "^28.1.8",
|
|
65
67
|
"@types/lodash": "^4.14.178",
|
|
66
|
-
"@types/node": "^
|
|
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.
|
|
70
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
71
|
-
"@typescript-eslint/parser": "^5.
|
|
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
|
-
"
|
|
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
|
-
"
|
|
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
|
-
"
|
|
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
|
|
103
|
+
"*.m?{js,ts}": "eslint --fix",
|
|
104
|
+
"{!(package-lock).json,*.{y?(a)ml,md}}": "prettier --write"
|
|
97
105
|
}
|
|
98
106
|
}
|