concurrently 9.1.2 → 9.2.1
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 +8 -8
- package/dist/bin/concurrently.js +29 -12
- package/dist/bin/read-package.js +18 -9
- package/dist/src/assert.d.ts +5 -0
- package/dist/src/assert.js +15 -0
- package/dist/src/command-parser/expand-arguments.d.ts +5 -5
- package/dist/src/command-parser/expand-arguments.js +14 -12
- package/dist/src/command-parser/expand-wildcard.js +7 -6
- package/dist/src/command-parser/strip-quotes.d.ts +5 -5
- package/dist/src/command.d.ts +10 -6
- package/dist/src/command.js +41 -13
- package/dist/src/completion-listener.d.ts +0 -1
- package/dist/src/completion-listener.js +21 -8
- package/dist/src/concurrently.d.ts +0 -6
- package/dist/src/concurrently.js +15 -13
- package/dist/src/date-format.js +4 -1
- package/dist/src/flow-control/input-handler.d.ts +0 -1
- package/dist/src/flow-control/input-handler.js +18 -8
- package/dist/src/flow-control/kill-on-signal.d.ts +0 -2
- package/dist/src/flow-control/kill-others.d.ts +4 -2
- package/dist/src/flow-control/kill-others.js +19 -6
- package/dist/src/flow-control/log-timings.js +20 -16
- package/dist/src/flow-control/output-error-handler.d.ts +18 -0
- package/dist/src/flow-control/output-error-handler.js +27 -0
- package/dist/src/flow-control/restart-process.js +18 -8
- package/dist/src/flow-control/teardown.js +17 -7
- package/dist/src/index.d.ts +14 -3
- package/dist/src/index.js +12 -9
- package/dist/src/jsonc.d.ts +2 -2
- package/dist/src/logger.js +30 -15
- package/dist/src/observables.d.ts +8 -0
- package/dist/src/observables.js +23 -0
- package/dist/src/output-writer.d.ts +4 -1
- package/dist/src/output-writer.js +33 -8
- package/dist/src/prefix-color-selector.js +1 -1
- package/dist/src/spawn.d.ts +6 -12
- package/dist/src/spawn.js +3 -3
- package/dist/src/utils.d.ts +10 -0
- package/dist/src/utils.js +16 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/docs/README.md +2 -0
- package/docs/cli/input-handling.md +5 -5
- package/docs/cli/output-control.md +3 -3
- package/docs/cli/passthrough-arguments.md +8 -8
- package/docs/cli/prefixing.md +10 -10
- package/docs/cli/restarting.md +3 -3
- package/docs/cli/shortcuts.md +9 -9
- package/docs/cli/success.md +73 -0
- package/docs/cli/terminating.md +52 -0
- package/index.js +1 -1
- package/index.mjs +0 -1
- package/package.json +30 -35
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
|
|
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
|
|
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
|
|
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
|
-
- `
|
|
100
|
-
Can
|
|
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
|
|
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.
|
|
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,8 +172,8 @@ 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
|
- `incoming`: an RxJS observable for the IPC messages received from the underlying process.
|
|
178
178
|
- `outgoing`: an RxJS observable for the IPC messages sent to the underlying process.
|
|
179
179
|
|
package/dist/bin/concurrently.js
CHANGED
|
@@ -16,22 +16,33 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
16
16
|
}) : function(o, v) {
|
|
17
17
|
o["default"] = v;
|
|
18
18
|
});
|
|
19
|
-
var __importStar = (this && this.__importStar) || function (
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
};
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
26
36
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
27
37
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
28
38
|
};
|
|
29
39
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
-
const lodash_1 = __importDefault(require("lodash"));
|
|
31
40
|
const yargs_1 = __importDefault(require("yargs"));
|
|
32
41
|
const helpers_1 = require("yargs/helpers");
|
|
42
|
+
const assert_1 = require("../src/assert");
|
|
33
43
|
const defaults = __importStar(require("../src/defaults"));
|
|
34
44
|
const index_1 = require("../src/index");
|
|
45
|
+
const utils_1 = require("../src/utils");
|
|
35
46
|
const read_package_1 = require("./read-package");
|
|
36
47
|
const version = String((0, read_package_1.readPackage)().version);
|
|
37
48
|
const epilogue = `For documentation and more examples, visit:\nhttps://github.com/open-cli-tools/concurrently/tree/v${version}/docs`;
|
|
@@ -128,7 +139,7 @@ const program = (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
|
|
|
128
139
|
// Kill others
|
|
129
140
|
'kill-others': {
|
|
130
141
|
alias: 'k',
|
|
131
|
-
describe: 'Kill other processes
|
|
142
|
+
describe: 'Kill other processes once the first exits.',
|
|
132
143
|
type: 'boolean',
|
|
133
144
|
},
|
|
134
145
|
'kill-others-on-fail': {
|
|
@@ -141,6 +152,10 @@ const program = (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
|
|
|
141
152
|
type: 'string',
|
|
142
153
|
default: defaults.killSignal,
|
|
143
154
|
},
|
|
155
|
+
'kill-timeout': {
|
|
156
|
+
describe: 'How many milliseconds to wait before forcing process terminating.',
|
|
157
|
+
type: 'number',
|
|
158
|
+
},
|
|
144
159
|
// Prefix
|
|
145
160
|
prefix: {
|
|
146
161
|
alias: 'p',
|
|
@@ -209,13 +224,14 @@ const program = (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
|
|
|
209
224
|
.group(['m', 'n', 'name-separator', 's', 'r', 'no-color', 'hide', 'g', 'timings', 'P', 'teardown'], 'General')
|
|
210
225
|
.group(['p', 'c', 'l', 't', 'pad-prefix'], 'Prefix styling')
|
|
211
226
|
.group(['i', 'default-input-target'], 'Input handling')
|
|
212
|
-
.group(['k', 'kill-others-on-fail', 'kill-signal'], 'Killing other processes')
|
|
227
|
+
.group(['k', 'kill-others-on-fail', 'kill-signal', 'kill-timeout'], 'Killing other processes')
|
|
213
228
|
.group(['restart-tries', 'restart-after'], 'Restarting')
|
|
214
229
|
.epilogue(epilogue);
|
|
215
230
|
const args = program.parseSync();
|
|
231
|
+
(0, assert_1.assertDeprecated)(args.nameSeparator === defaults.nameSeparator, 'name-separator', 'Use commas as name separators instead.');
|
|
216
232
|
// Get names of commands by the specified separator
|
|
217
233
|
const names = (args.names || '').split(args.nameSeparator);
|
|
218
|
-
const additionalArguments =
|
|
234
|
+
const additionalArguments = (0, utils_1.castArray)(args['--'] ?? []).map(String);
|
|
219
235
|
const commands = args.passthroughArguments ? args._ : args._.concat(additionalArguments);
|
|
220
236
|
if (!commands.length) {
|
|
221
237
|
program.showHelp();
|
|
@@ -227,12 +243,13 @@ if (!commands.length) {
|
|
|
227
243
|
})), {
|
|
228
244
|
handleInput: args.handleInput,
|
|
229
245
|
defaultInputTarget: args.defaultInputTarget,
|
|
230
|
-
|
|
246
|
+
killOthersOn: args.killOthers
|
|
231
247
|
? ['success', 'failure']
|
|
232
248
|
: args.killOthersOnFail
|
|
233
249
|
? ['failure']
|
|
234
250
|
: [],
|
|
235
251
|
killSignal: args.killSignal,
|
|
252
|
+
killTimeout: args.killTimeout,
|
|
236
253
|
maxProcesses: args.maxProcesses,
|
|
237
254
|
raw: args.raw,
|
|
238
255
|
hide: args.hide.split(','),
|
package/dist/bin/read-package.js
CHANGED
|
@@ -15,15 +15,25 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
15
15
|
}) : function(o, v) {
|
|
16
16
|
o["default"] = v;
|
|
17
17
|
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
};
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
25
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.readPackage =
|
|
36
|
+
exports.readPackage = readPackage;
|
|
27
37
|
const fs = __importStar(require("fs"));
|
|
28
38
|
const path = __importStar(require("path"));
|
|
29
39
|
/**
|
|
@@ -44,4 +54,3 @@ function readPackage() {
|
|
|
44
54
|
} while (oldDir !== dir);
|
|
45
55
|
throw new Error('package.json not found');
|
|
46
56
|
}
|
|
47
|
-
exports.readPackage = readPackage;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.assertDeprecated = assertDeprecated;
|
|
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 && !deprecations.has(name)) {
|
|
11
|
+
// eslint-disable-next-line no-console
|
|
12
|
+
console.warn(`[concurrently] ${name} is deprecated. ${message}`);
|
|
13
|
+
deprecations.add(name);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -9,10 +9,10 @@ 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
|
|
15
|
-
ipc?: number
|
|
16
|
-
raw?: boolean
|
|
12
|
+
env?: Record<string, unknown>;
|
|
13
|
+
cwd?: string;
|
|
14
|
+
prefixColor?: string;
|
|
15
|
+
ipc?: number;
|
|
16
|
+
raw?: boolean;
|
|
17
17
|
};
|
|
18
18
|
}
|
|
@@ -16,18 +16,20 @@ class ExpandArguments {
|
|
|
16
16
|
if (match.startsWith('\\')) {
|
|
17
17
|
return match.slice(1);
|
|
18
18
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
placeholderTarget
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
19
|
+
if (this.additionalArguments.length > 0) {
|
|
20
|
+
// Replace numeric placeholder if value exists in additional arguments.
|
|
21
|
+
if (!isNaN(placeholderTarget) &&
|
|
22
|
+
placeholderTarget <= this.additionalArguments.length) {
|
|
23
|
+
return (0, shell_quote_1.quote)([this.additionalArguments[placeholderTarget - 1]]);
|
|
24
|
+
}
|
|
25
|
+
// Replace all arguments placeholder.
|
|
26
|
+
if (placeholderTarget === '@') {
|
|
27
|
+
return (0, shell_quote_1.quote)(this.additionalArguments);
|
|
28
|
+
}
|
|
29
|
+
// Replace combined arguments placeholder.
|
|
30
|
+
if (placeholderTarget === '*') {
|
|
31
|
+
return (0, shell_quote_1.quote)([this.additionalArguments.join(' ')]);
|
|
32
|
+
}
|
|
31
33
|
}
|
|
32
34
|
// Replace placeholder with empty string
|
|
33
35
|
// if value doesn't exist in additional arguments.
|
|
@@ -5,8 +5,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.ExpandWildcard = void 0;
|
|
7
7
|
const fs_1 = __importDefault(require("fs"));
|
|
8
|
-
const lodash_1 = __importDefault(require("lodash"));
|
|
9
8
|
const jsonc_1 = __importDefault(require("../jsonc"));
|
|
9
|
+
const utils_1 = require("../utils");
|
|
10
10
|
// Matches a negative filter surrounded by '(!' and ')'.
|
|
11
11
|
const OMISSION = /\(!([^)]+)\)/;
|
|
12
12
|
/**
|
|
@@ -28,7 +28,7 @@ class ExpandWildcard {
|
|
|
28
28
|
}
|
|
29
29
|
return jsonc_1.default.parse(json);
|
|
30
30
|
}
|
|
31
|
-
catch
|
|
31
|
+
catch {
|
|
32
32
|
return {};
|
|
33
33
|
}
|
|
34
34
|
}
|
|
@@ -37,7 +37,7 @@ class ExpandWildcard {
|
|
|
37
37
|
const json = fs_1.default.readFileSync('package.json', { encoding: 'utf-8' });
|
|
38
38
|
return JSON.parse(json);
|
|
39
39
|
}
|
|
40
|
-
catch
|
|
40
|
+
catch {
|
|
41
41
|
return {};
|
|
42
42
|
}
|
|
43
43
|
}
|
|
@@ -79,8 +79,8 @@ class ExpandWildcard {
|
|
|
79
79
|
}
|
|
80
80
|
const [, omission] = OMISSION.exec(scriptGlob) || [];
|
|
81
81
|
const scriptGlobSansOmission = scriptGlob.replace(OMISSION, '');
|
|
82
|
-
const preWildcard =
|
|
83
|
-
const postWildcard =
|
|
82
|
+
const preWildcard = (0, utils_1.escapeRegExp)(scriptGlobSansOmission.slice(0, wildcardPosition));
|
|
83
|
+
const postWildcard = (0, utils_1.escapeRegExp)(scriptGlobSansOmission.slice(wildcardPosition + 1));
|
|
84
84
|
const wildcardRegex = new RegExp(`^${preWildcard}(.*?)${postWildcard}$`);
|
|
85
85
|
// If 'commandInfo.name' doesn't match 'scriptGlob', this means a custom name
|
|
86
86
|
// has been specified and thus becomes the prefix (as described in the README).
|
|
@@ -90,7 +90,8 @@ class ExpandWildcard {
|
|
|
90
90
|
if (omission && RegExp(omission).test(script)) {
|
|
91
91
|
return;
|
|
92
92
|
}
|
|
93
|
-
const
|
|
93
|
+
const result = wildcardRegex.exec(script);
|
|
94
|
+
const match = result?.[1];
|
|
94
95
|
if (match !== undefined) {
|
|
95
96
|
return {
|
|
96
97
|
...commandInfo,
|
|
@@ -7,10 +7,10 @@ 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
|
|
13
|
-
ipc?: number
|
|
14
|
-
raw?: boolean
|
|
10
|
+
env?: Record<string, unknown>;
|
|
11
|
+
cwd?: string;
|
|
12
|
+
prefixColor?: string;
|
|
13
|
+
ipc?: number;
|
|
14
|
+
raw?: boolean;
|
|
15
15
|
};
|
|
16
16
|
}
|
package/dist/src/command.d.ts
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
|
-
/// <reference types="node" />
|
|
3
|
-
/// <reference types="node" />
|
|
4
|
-
/// <reference types="node" />
|
|
5
1
|
import { ChildProcess as BaseChildProcess, MessageOptions, SendHandle, SpawnOptions } from 'child_process';
|
|
6
2
|
import * as Rx from 'rxjs';
|
|
7
3
|
import { EventEmitter, Writable } from 'stream';
|
|
@@ -114,9 +110,16 @@ export declare class Command implements CommandInfo {
|
|
|
114
110
|
readonly ipc?: number;
|
|
115
111
|
readonly close: Rx.Subject<CloseEvent>;
|
|
116
112
|
readonly error: Rx.Subject<unknown>;
|
|
117
|
-
readonly stdout: Rx.Subject<Buffer
|
|
118
|
-
readonly stderr: Rx.Subject<Buffer
|
|
113
|
+
readonly stdout: Rx.Subject<Buffer<ArrayBufferLike>>;
|
|
114
|
+
readonly stderr: Rx.Subject<Buffer<ArrayBufferLike>>;
|
|
119
115
|
readonly timer: Rx.Subject<TimerEvent>;
|
|
116
|
+
/**
|
|
117
|
+
* A stream of changes to the `#state` property.
|
|
118
|
+
*
|
|
119
|
+
* Note that the command never goes back to the `stopped` state, therefore it's not a value
|
|
120
|
+
* that's emitted by this stream.
|
|
121
|
+
*/
|
|
122
|
+
readonly stateChange: Rx.Subject<"started" | "errored" | "exited">;
|
|
120
123
|
readonly messages: {
|
|
121
124
|
incoming: Rx.Subject<MessageEvent>;
|
|
122
125
|
outgoing: Rx.ReplaySubject<OutgoingMessageEvent>;
|
|
@@ -135,6 +138,7 @@ export declare class Command implements CommandInfo {
|
|
|
135
138
|
* Starts this command, piping output, error and close events onto the corresponding observables.
|
|
136
139
|
*/
|
|
137
140
|
start(): void;
|
|
141
|
+
private changeState;
|
|
138
142
|
private maybeSetupIPC;
|
|
139
143
|
/**
|
|
140
144
|
* Sends a message to the underlying process once it starts.
|
package/dist/src/command.js
CHANGED
|
@@ -15,13 +15,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
15
15
|
}) : function(o, v) {
|
|
16
16
|
o["default"] = v;
|
|
17
17
|
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
};
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
25
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
36
|
exports.Command = void 0;
|
|
27
37
|
const Rx = __importStar(require("rxjs"));
|
|
@@ -47,6 +57,13 @@ class Command {
|
|
|
47
57
|
stdout = new Rx.Subject();
|
|
48
58
|
stderr = new Rx.Subject();
|
|
49
59
|
timer = new Rx.Subject();
|
|
60
|
+
/**
|
|
61
|
+
* A stream of changes to the `#state` property.
|
|
62
|
+
*
|
|
63
|
+
* Note that the command never goes back to the `stopped` state, therefore it's not a value
|
|
64
|
+
* that's emitted by this stream.
|
|
65
|
+
*/
|
|
66
|
+
stateChange = new Rx.Subject();
|
|
50
67
|
messages = {
|
|
51
68
|
incoming: new Rx.Subject(),
|
|
52
69
|
outgoing: new Rx.ReplaySubject(),
|
|
@@ -76,7 +93,7 @@ class Command {
|
|
|
76
93
|
*/
|
|
77
94
|
start() {
|
|
78
95
|
const child = this.spawn(this.command, this.spawnOpts);
|
|
79
|
-
this.
|
|
96
|
+
this.changeState('started');
|
|
80
97
|
this.process = child;
|
|
81
98
|
this.pid = child.pid;
|
|
82
99
|
const startDate = new Date(Date.now());
|
|
@@ -88,7 +105,7 @@ class Command {
|
|
|
88
105
|
const endDate = new Date(Date.now());
|
|
89
106
|
this.timer.next({ startDate, endDate });
|
|
90
107
|
this.error.next(event);
|
|
91
|
-
this.
|
|
108
|
+
this.changeState('errored');
|
|
92
109
|
});
|
|
93
110
|
Rx.fromEvent(child, 'close')
|
|
94
111
|
.pipe(Rx.map((event) => event))
|
|
@@ -96,7 +113,7 @@ class Command {
|
|
|
96
113
|
this.cleanUp();
|
|
97
114
|
// Don't override error event
|
|
98
115
|
if (this.state !== 'errored') {
|
|
99
|
-
this.
|
|
116
|
+
this.changeState('exited');
|
|
100
117
|
}
|
|
101
118
|
const endDate = new Date(Date.now());
|
|
102
119
|
this.timer.next({ startDate, endDate });
|
|
@@ -113,12 +130,18 @@ class Command {
|
|
|
113
130
|
},
|
|
114
131
|
});
|
|
115
132
|
});
|
|
116
|
-
child.stdout
|
|
133
|
+
if (child.stdout) {
|
|
117
134
|
pipeTo(Rx.fromEvent(child.stdout, 'data').pipe(Rx.map((event) => event)), this.stdout);
|
|
118
|
-
|
|
135
|
+
}
|
|
136
|
+
if (child.stderr) {
|
|
119
137
|
pipeTo(Rx.fromEvent(child.stderr, 'data').pipe(Rx.map((event) => event)), this.stderr);
|
|
138
|
+
}
|
|
120
139
|
this.stdin = child.stdin || undefined;
|
|
121
140
|
}
|
|
141
|
+
changeState(state) {
|
|
142
|
+
this.state = state;
|
|
143
|
+
this.stateChange.next(state);
|
|
144
|
+
}
|
|
122
145
|
maybeSetupIPC(child) {
|
|
123
146
|
if (!this.ipc) {
|
|
124
147
|
return [];
|
|
@@ -155,7 +178,12 @@ class Command {
|
|
|
155
178
|
handle,
|
|
156
179
|
options,
|
|
157
180
|
onSent(error) {
|
|
158
|
-
|
|
181
|
+
if (error) {
|
|
182
|
+
reject(error);
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
resolve();
|
|
186
|
+
}
|
|
159
187
|
},
|
|
160
188
|
});
|
|
161
189
|
});
|
|
@@ -15,13 +15,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
15
15
|
}) : function(o, v) {
|
|
16
16
|
o["default"] = v;
|
|
17
17
|
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
};
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
25
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
36
|
exports.CompletionListener = void 0;
|
|
27
37
|
const Rx = __importStar(require("rxjs"));
|
|
@@ -61,7 +71,7 @@ class CompletionListener {
|
|
|
61
71
|
// All commands except the specified ones must exit successfully
|
|
62
72
|
return events.every((event) => targetCommandsEvents.includes(event) || event.exitCode === 0);
|
|
63
73
|
}
|
|
64
|
-
// Only the specified commands must exit
|
|
74
|
+
// Only the specified commands must exit successfully
|
|
65
75
|
return (targetCommandsEvents.length > 0 &&
|
|
66
76
|
targetCommandsEvents.every((event) => event.exitCode === 0));
|
|
67
77
|
}
|
|
@@ -73,6 +83,9 @@ class CompletionListener {
|
|
|
73
83
|
* Commands that didn't spawn are filtered out.
|
|
74
84
|
*/
|
|
75
85
|
listen(commands, abortSignal) {
|
|
86
|
+
if (!commands.length) {
|
|
87
|
+
return Promise.resolve([]);
|
|
88
|
+
}
|
|
76
89
|
const abort = abortSignal &&
|
|
77
90
|
Rx.fromEvent(abortSignal, 'abort', { once: true }).pipe(
|
|
78
91
|
// The abort signal must happen before commands are killed, otherwise new commands
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
|
-
/// <reference types="node" />
|
|
3
1
|
import { Writable } from 'stream';
|
|
4
2
|
import { CloseEvent, Command, CommandIdentifier, CommandInfo, KillProcess, SpawnCommand } from './command';
|
|
5
3
|
import { SuccessCondition } from './completion-listener';
|
|
@@ -101,10 +99,6 @@ export type ConcurrentlyOptions = {
|
|
|
101
99
|
* Defaults to the `tree-kill` module.
|
|
102
100
|
*/
|
|
103
101
|
kill: KillProcess;
|
|
104
|
-
/**
|
|
105
|
-
* Signal to send to killed processes.
|
|
106
|
-
*/
|
|
107
|
-
killSignal?: string;
|
|
108
102
|
/**
|
|
109
103
|
* List of additional arguments passed that will get replaced in each command.
|
|
110
104
|
* If not defined, no argument replacing will happen.
|
package/dist/src/concurrently.js
CHANGED
|
@@ -3,10 +3,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.concurrently =
|
|
6
|
+
exports.concurrently = concurrently;
|
|
7
7
|
const assert_1 = __importDefault(require("assert"));
|
|
8
|
-
const
|
|
9
|
-
const
|
|
8
|
+
const os_1 = __importDefault(require("os"));
|
|
9
|
+
const rxjs_1 = require("rxjs");
|
|
10
10
|
const tree_kill_1 = __importDefault(require("tree-kill"));
|
|
11
11
|
const command_1 = require("./command");
|
|
12
12
|
const expand_arguments_1 = require("./command-parser/expand-arguments");
|
|
@@ -17,6 +17,7 @@ const completion_listener_1 = require("./completion-listener");
|
|
|
17
17
|
const output_writer_1 = require("./output-writer");
|
|
18
18
|
const prefix_color_selector_1 = require("./prefix-color-selector");
|
|
19
19
|
const spawn_1 = require("./spawn");
|
|
20
|
+
const utils_1 = require("./utils");
|
|
20
21
|
const defaults = {
|
|
21
22
|
spawn: spawn_1.spawn,
|
|
22
23
|
kill: tree_kill_1.default,
|
|
@@ -33,7 +34,7 @@ const defaults = {
|
|
|
33
34
|
function concurrently(baseCommands, baseOptions) {
|
|
34
35
|
assert_1.default.ok(Array.isArray(baseCommands), '[concurrently] commands should be an array');
|
|
35
36
|
assert_1.default.notStrictEqual(baseCommands.length, 0, '[concurrently] no commands provided');
|
|
36
|
-
const options =
|
|
37
|
+
const options = { ...defaults, ...baseOptions };
|
|
37
38
|
const prefixColorSelector = new prefix_color_selector_1.PrefixColorSelector(options.prefixColors || []);
|
|
38
39
|
const commandParsers = [
|
|
39
40
|
new strip_quotes_1.StripQuotes(),
|
|
@@ -44,7 +45,7 @@ function concurrently(baseCommands, baseOptions) {
|
|
|
44
45
|
commandParsers.push(new expand_arguments_1.ExpandArguments(options.additionalArguments));
|
|
45
46
|
}
|
|
46
47
|
const hide = (options.hide || []).map(String);
|
|
47
|
-
let commands =
|
|
48
|
+
let commands = baseCommands
|
|
48
49
|
.map(mapToCommandInfo)
|
|
49
50
|
.flatMap((command) => parseCommand(command, commandParsers))
|
|
50
51
|
.map((command, index) => {
|
|
@@ -55,17 +56,16 @@ function concurrently(baseCommands, baseOptions) {
|
|
|
55
56
|
...command,
|
|
56
57
|
}, (0, spawn_1.getSpawnOpts)({
|
|
57
58
|
ipc: command.ipc,
|
|
58
|
-
stdio: hidden ? 'hidden' : command.raw ?? options.raw ? 'raw' : 'normal',
|
|
59
|
+
stdio: hidden ? 'hidden' : (command.raw ?? options.raw) ? 'raw' : 'normal',
|
|
59
60
|
env: command.env,
|
|
60
61
|
cwd: command.cwd || options.cwd,
|
|
61
62
|
}), options.spawn, options.kill);
|
|
62
|
-
})
|
|
63
|
-
.value();
|
|
63
|
+
});
|
|
64
64
|
const handleResult = options.controllers.reduce(({ commands: prevCommands, onFinishCallbacks }, controller) => {
|
|
65
65
|
const { commands, onFinish } = controller.handle(prevCommands);
|
|
66
66
|
return {
|
|
67
67
|
commands,
|
|
68
|
-
onFinishCallbacks:
|
|
68
|
+
onFinishCallbacks: onFinishCallbacks.concat(onFinish ? [onFinish] : []),
|
|
69
69
|
};
|
|
70
70
|
}, { commands, onFinishCallbacks: [] });
|
|
71
71
|
commands = handleResult.commands;
|
|
@@ -75,11 +75,14 @@ function concurrently(baseCommands, baseOptions) {
|
|
|
75
75
|
group: !!options.group,
|
|
76
76
|
commands,
|
|
77
77
|
});
|
|
78
|
-
options.logger.output
|
|
78
|
+
options.logger.output
|
|
79
|
+
// Stop trying to write after there's been an error.
|
|
80
|
+
.pipe((0, rxjs_1.takeUntil)(outputWriter.error))
|
|
81
|
+
.subscribe(({ command, text }) => outputWriter.write(command, text));
|
|
79
82
|
}
|
|
80
83
|
const commandsLeft = commands.slice();
|
|
81
84
|
const maxProcesses = Math.max(1, (typeof options.maxProcesses === 'string' && options.maxProcesses.endsWith('%')
|
|
82
|
-
? Math.round((
|
|
85
|
+
? Math.round((os_1.default.cpus().length * Number(options.maxProcesses.slice(0, -1))) / 100)
|
|
83
86
|
: Number(options.maxProcesses)) || commandsLeft.length);
|
|
84
87
|
for (let i = 0; i < maxProcesses; i++) {
|
|
85
88
|
maybeRunMore(commandsLeft, options.abortSignal);
|
|
@@ -92,7 +95,6 @@ function concurrently(baseCommands, baseOptions) {
|
|
|
92
95
|
commands,
|
|
93
96
|
};
|
|
94
97
|
}
|
|
95
|
-
exports.concurrently = concurrently;
|
|
96
98
|
function mapToCommandInfo(command) {
|
|
97
99
|
if (typeof command === 'string') {
|
|
98
100
|
return mapToCommandInfo({ command });
|
|
@@ -117,7 +119,7 @@ function mapToCommandInfo(command) {
|
|
|
117
119
|
};
|
|
118
120
|
}
|
|
119
121
|
function parseCommand(command, parsers) {
|
|
120
|
-
return parsers.reduce((commands, parser) =>
|
|
122
|
+
return parsers.reduce((commands, parser) => commands.flatMap((command) => parser.parse(command)), (0, utils_1.castArray)(command));
|
|
121
123
|
}
|
|
122
124
|
function maybeRunMore(commandsLeft, abortSignal) {
|
|
123
125
|
const command = commandsLeft.shift();
|