concurrently 6.5.1 → 7.0.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 +58 -19
- package/dist/bin/concurrently.d.ts +2 -0
- package/dist/bin/concurrently.js +193 -0
- package/dist/bin/concurrently.spec.d.ts +1 -0
- package/dist/bin/epilogue.d.ts +1 -0
- package/dist/bin/epilogue.js +65 -0
- package/dist/src/command-parser/command-parser.d.ts +19 -0
- package/dist/src/command-parser/command-parser.js +2 -0
- package/dist/src/command-parser/expand-npm-shortcut.d.ts +8 -0
- package/{src → dist/src}/command-parser/expand-npm-shortcut.js +10 -3
- package/dist/src/command-parser/expand-npm-shortcut.spec.d.ts +1 -0
- package/dist/src/command-parser/expand-npm-wildcard.d.ts +13 -0
- package/dist/src/command-parser/expand-npm-wildcard.js +73 -0
- package/dist/src/command-parser/expand-npm-wildcard.spec.d.ts +1 -0
- package/dist/src/command-parser/strip-quotes.d.ts +10 -0
- package/{src → dist/src}/command-parser/strip-quotes.js +10 -4
- package/dist/src/command-parser/strip-quotes.spec.d.ts +1 -0
- package/dist/src/command.d.ts +101 -0
- package/{src → dist/src}/command.js +53 -29
- package/dist/src/command.spec.d.ts +1 -0
- package/dist/src/completion-listener.d.ts +37 -0
- package/dist/src/completion-listener.js +60 -0
- package/dist/src/completion-listener.spec.d.ts +1 -0
- package/dist/src/concurrently.d.ts +77 -0
- package/dist/src/concurrently.js +120 -0
- package/dist/src/concurrently.spec.d.ts +1 -0
- package/dist/src/defaults.d.ts +52 -0
- package/dist/src/defaults.js +58 -0
- package/dist/src/flow-control/flow-controller.d.ts +13 -0
- package/dist/src/flow-control/flow-controller.js +2 -0
- package/dist/src/flow-control/input-handler.d.ts +33 -0
- package/dist/src/flow-control/input-handler.js +73 -0
- package/dist/src/flow-control/input-handler.spec.d.ts +1 -0
- package/dist/src/flow-control/kill-on-signal.d.ts +17 -0
- package/{src → dist/src}/flow-control/kill-on-signal.js +13 -11
- package/dist/src/flow-control/kill-on-signal.spec.d.ts +1 -0
- package/dist/src/flow-control/kill-others.d.ts +18 -0
- package/dist/src/flow-control/kill-others.js +35 -0
- package/dist/src/flow-control/kill-others.spec.d.ts +1 -0
- package/dist/src/flow-control/log-error.d.ts +15 -0
- package/dist/src/flow-control/log-error.js +21 -0
- package/dist/src/flow-control/log-error.spec.d.ts +1 -0
- package/dist/src/flow-control/log-exit.d.ts +15 -0
- package/dist/src/flow-control/log-exit.js +19 -0
- package/dist/src/flow-control/log-exit.spec.d.ts +1 -0
- package/dist/src/flow-control/log-output.d.ts +15 -0
- package/{src → dist/src}/flow-control/log-output.js +13 -5
- package/dist/src/flow-control/log-output.spec.d.ts +1 -0
- package/dist/src/flow-control/log-timings.d.ts +27 -0
- package/dist/src/flow-control/log-timings.js +88 -0
- package/dist/src/flow-control/log-timings.spec.d.ts +1 -0
- package/dist/src/flow-control/restart-process.d.ts +22 -0
- package/dist/src/flow-control/restart-process.js +71 -0
- package/dist/src/flow-control/restart-process.spec.d.ts +1 -0
- package/dist/src/get-spawn-opts.d.ts +30 -0
- package/dist/src/get-spawn-opts.js +11 -0
- package/dist/src/get-spawn-opts.spec.d.ts +1 -0
- package/dist/src/index.d.ts +69 -0
- package/dist/src/index.js +69 -0
- package/dist/src/logger.d.ts +72 -0
- package/{src → dist/src}/logger.js +77 -58
- package/dist/src/logger.spec.d.ts +1 -0
- package/dist/src/output-writer.d.ts +19 -0
- package/dist/src/output-writer.js +69 -0
- package/dist/src/output-writer.spec.d.ts +1 -0
- package/index.js +6 -68
- package/index.mjs +9 -0
- package/package.json +37 -11
- package/bin/concurrently.js +0 -186
- package/bin/concurrently.spec.js +0 -428
- package/bin/epilogue.txt +0 -46
- package/src/command-parser/expand-npm-shortcut.spec.js +0 -36
- package/src/command-parser/expand-npm-wildcard.js +0 -52
- package/src/command-parser/expand-npm-wildcard.spec.js +0 -104
- package/src/command-parser/strip-quotes.spec.js +0 -20
- package/src/command.spec.js +0 -275
- package/src/completion-listener.js +0 -39
- package/src/completion-listener.spec.js +0 -89
- package/src/concurrently.js +0 -116
- package/src/concurrently.spec.js +0 -199
- package/src/defaults.js +0 -35
- package/src/flow-control/base-handler.js +0 -16
- package/src/flow-control/base-handler.spec.js +0 -22
- package/src/flow-control/input-handler.js +0 -50
- package/src/flow-control/input-handler.spec.js +0 -113
- package/src/flow-control/kill-on-signal.spec.js +0 -79
- package/src/flow-control/kill-others.js +0 -38
- package/src/flow-control/kill-others.spec.js +0 -66
- package/src/flow-control/log-error.js +0 -18
- package/src/flow-control/log-error.spec.js +0 -40
- package/src/flow-control/log-exit.js +0 -11
- package/src/flow-control/log-exit.spec.js +0 -36
- package/src/flow-control/log-output.spec.js +0 -41
- package/src/flow-control/log-timings.js +0 -64
- package/src/flow-control/log-timings.spec.js +0 -137
- package/src/flow-control/restart-process.js +0 -56
- package/src/flow-control/restart-process.spec.js +0 -139
- package/src/get-spawn-opts.js +0 -16
- package/src/get-spawn-opts.spec.js +0 -30
- package/src/logger.spec.js +0 -318
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { ChildProcess as BaseChildProcess, SpawnOptions } from 'child_process';
|
|
3
|
+
import * as Rx from 'rxjs';
|
|
4
|
+
import { EventEmitter, Writable } from 'stream';
|
|
5
|
+
/**
|
|
6
|
+
* Identifier for a command; if string, it's the command's name, if number, it's the index.
|
|
7
|
+
*/
|
|
8
|
+
export declare type CommandIdentifier = string | number;
|
|
9
|
+
export interface CommandInfo {
|
|
10
|
+
/**
|
|
11
|
+
* Command's name.
|
|
12
|
+
*/
|
|
13
|
+
name: string;
|
|
14
|
+
/**
|
|
15
|
+
* Which command line the command has.
|
|
16
|
+
*/
|
|
17
|
+
command: string;
|
|
18
|
+
/**
|
|
19
|
+
* Which environment variables should the spawned process have.
|
|
20
|
+
*/
|
|
21
|
+
env?: Record<string, any>;
|
|
22
|
+
/**
|
|
23
|
+
* The current working directory of the process when spawned.
|
|
24
|
+
*/
|
|
25
|
+
cwd?: string;
|
|
26
|
+
prefixColor?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface CloseEvent {
|
|
29
|
+
command: CommandInfo;
|
|
30
|
+
/**
|
|
31
|
+
* The command's index among all commands ran.
|
|
32
|
+
*/
|
|
33
|
+
index: number;
|
|
34
|
+
/**
|
|
35
|
+
* Whether the command exited because it was killed.
|
|
36
|
+
*/
|
|
37
|
+
killed: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* The exit code or signal for the command.
|
|
40
|
+
*/
|
|
41
|
+
exitCode: string | number;
|
|
42
|
+
timings: {
|
|
43
|
+
startDate: Date;
|
|
44
|
+
endDate: Date;
|
|
45
|
+
durationSeconds: number;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export interface TimerEvent {
|
|
49
|
+
startDate: Date;
|
|
50
|
+
endDate?: Date;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Subtype of NodeJS's child_process including only what's actually needed for a command to work.
|
|
54
|
+
*/
|
|
55
|
+
export declare type ChildProcess = EventEmitter & Pick<BaseChildProcess, 'pid' | 'stdin' | 'stdout' | 'stderr'>;
|
|
56
|
+
/**
|
|
57
|
+
* Interface for a function that must kill the process with `pid`, optionally sending `signal` to it.
|
|
58
|
+
*/
|
|
59
|
+
export declare type KillProcess = (pid: number, signal?: string) => void;
|
|
60
|
+
/**
|
|
61
|
+
* Interface for a function that spawns a command and returns its child process instance.
|
|
62
|
+
*/
|
|
63
|
+
export declare type SpawnCommand = (command: string, options: SpawnOptions) => ChildProcess;
|
|
64
|
+
export declare class Command implements CommandInfo {
|
|
65
|
+
private readonly killProcess;
|
|
66
|
+
private readonly spawn;
|
|
67
|
+
private readonly spawnOpts;
|
|
68
|
+
readonly index: number;
|
|
69
|
+
/** @inheritdoc */
|
|
70
|
+
readonly name: string;
|
|
71
|
+
/** @inheritdoc */
|
|
72
|
+
readonly command: string;
|
|
73
|
+
/** @inheritdoc */
|
|
74
|
+
readonly prefixColor: string;
|
|
75
|
+
/** @inheritdoc */
|
|
76
|
+
readonly env: Record<string, any>;
|
|
77
|
+
/** @inheritdoc */
|
|
78
|
+
readonly cwd?: string;
|
|
79
|
+
readonly close: Rx.Subject<CloseEvent>;
|
|
80
|
+
readonly error: Rx.Subject<unknown>;
|
|
81
|
+
readonly stdout: Rx.Subject<Buffer>;
|
|
82
|
+
readonly stderr: Rx.Subject<Buffer>;
|
|
83
|
+
readonly timer: Rx.Subject<TimerEvent>;
|
|
84
|
+
process?: ChildProcess;
|
|
85
|
+
stdin?: Writable;
|
|
86
|
+
pid?: number;
|
|
87
|
+
killed: boolean;
|
|
88
|
+
exited: boolean;
|
|
89
|
+
get killable(): boolean;
|
|
90
|
+
constructor({ index, name, command, prefixColor, env, cwd }: CommandInfo & {
|
|
91
|
+
index: number;
|
|
92
|
+
}, spawnOpts: SpawnOptions, spawn: SpawnCommand, killProcess: KillProcess);
|
|
93
|
+
/**
|
|
94
|
+
* Starts this command, piping output, error and close events onto the corresponding observables.
|
|
95
|
+
*/
|
|
96
|
+
start(): void;
|
|
97
|
+
/**
|
|
98
|
+
* Kills this command, optionally specifying a signal to send to it.
|
|
99
|
+
*/
|
|
100
|
+
kill(code?: string): void;
|
|
101
|
+
}
|
|
@@ -1,54 +1,72 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
get
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
+
}) : function(o, v) {
|
|
12
|
+
o["default"] = v;
|
|
13
|
+
});
|
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
+
if (mod && mod.__esModule) return mod;
|
|
16
|
+
var result = {};
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
+
__setModuleDefault(result, mod);
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.Command = void 0;
|
|
23
|
+
const Rx = __importStar(require("rxjs"));
|
|
24
|
+
class Command {
|
|
25
|
+
constructor({ index, name, command, prefixColor, env, cwd }, spawnOpts, spawn, killProcess) {
|
|
26
|
+
this.close = new Rx.Subject();
|
|
27
|
+
this.error = new Rx.Subject();
|
|
28
|
+
this.stdout = new Rx.Subject();
|
|
29
|
+
this.stderr = new Rx.Subject();
|
|
30
|
+
this.timer = new Rx.Subject();
|
|
31
|
+
this.killed = false;
|
|
32
|
+
this.exited = false;
|
|
9
33
|
this.index = index;
|
|
10
34
|
this.name = name;
|
|
11
35
|
this.command = command;
|
|
12
36
|
this.prefixColor = prefixColor;
|
|
13
37
|
this.env = env;
|
|
38
|
+
this.cwd = cwd;
|
|
14
39
|
this.killProcess = killProcess;
|
|
15
40
|
this.spawn = spawn;
|
|
16
41
|
this.spawnOpts = spawnOpts;
|
|
17
|
-
this.killed = false;
|
|
18
|
-
|
|
19
|
-
this.error = new Rx.Subject();
|
|
20
|
-
this.timer = new Rx.Subject();
|
|
21
|
-
this.close = new Rx.Subject();
|
|
22
|
-
this.stdout = new Rx.Subject();
|
|
23
|
-
this.stderr = new Rx.Subject();
|
|
24
42
|
}
|
|
25
|
-
|
|
43
|
+
get killable() {
|
|
44
|
+
return !!this.process;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Starts this command, piping output, error and close events onto the corresponding observables.
|
|
48
|
+
*/
|
|
26
49
|
start() {
|
|
27
50
|
const child = this.spawn(this.command, this.spawnOpts);
|
|
28
51
|
this.process = child;
|
|
29
52
|
this.pid = child.pid;
|
|
30
53
|
const startDate = new Date(Date.now());
|
|
31
54
|
const highResStartTime = process.hrtime();
|
|
32
|
-
this.timer.next({startDate});
|
|
33
|
-
|
|
55
|
+
this.timer.next({ startDate });
|
|
34
56
|
Rx.fromEvent(child, 'error').subscribe(event => {
|
|
35
57
|
this.process = undefined;
|
|
36
58
|
const endDate = new Date(Date.now());
|
|
37
|
-
this.timer.next({startDate, endDate});
|
|
59
|
+
this.timer.next({ startDate, endDate });
|
|
38
60
|
this.error.next(event);
|
|
39
61
|
});
|
|
40
62
|
Rx.fromEvent(child, 'close').subscribe(([exitCode, signal]) => {
|
|
41
63
|
this.process = undefined;
|
|
64
|
+
this.exited = true;
|
|
42
65
|
const endDate = new Date(Date.now());
|
|
43
|
-
this.timer.next({startDate, endDate});
|
|
66
|
+
this.timer.next({ startDate, endDate });
|
|
44
67
|
const [durationSeconds, durationNanoSeconds] = process.hrtime(highResStartTime);
|
|
45
68
|
this.close.next({
|
|
46
|
-
command:
|
|
47
|
-
command: this.command,
|
|
48
|
-
name: this.name,
|
|
49
|
-
prefixColor: this.prefixColor,
|
|
50
|
-
env: this.env,
|
|
51
|
-
},
|
|
69
|
+
command: this,
|
|
52
70
|
index: this.index,
|
|
53
71
|
exitCode: exitCode === null ? signal : exitCode,
|
|
54
72
|
killed: this.killed,
|
|
@@ -63,15 +81,21 @@ module.exports = class Command {
|
|
|
63
81
|
child.stderr && pipeTo(Rx.fromEvent(child.stderr, 'data'), this.stderr);
|
|
64
82
|
this.stdin = child.stdin;
|
|
65
83
|
}
|
|
66
|
-
|
|
84
|
+
/**
|
|
85
|
+
* Kills this command, optionally specifying a signal to send to it.
|
|
86
|
+
*/
|
|
67
87
|
kill(code) {
|
|
68
88
|
if (this.killable) {
|
|
69
89
|
this.killed = true;
|
|
70
90
|
this.killProcess(this.pid, code);
|
|
71
91
|
}
|
|
72
92
|
}
|
|
73
|
-
}
|
|
74
|
-
|
|
93
|
+
}
|
|
94
|
+
exports.Command = Command;
|
|
95
|
+
;
|
|
96
|
+
/**
|
|
97
|
+
* Pipes all events emitted by `stream` into `subject`.
|
|
98
|
+
*/
|
|
75
99
|
function pipeTo(stream, subject) {
|
|
76
100
|
stream.subscribe(event => subject.next(event));
|
|
77
101
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import * as Rx from 'rxjs';
|
|
2
|
+
import { CloseEvent, Command } from './command';
|
|
3
|
+
/**
|
|
4
|
+
* Defines which command(s) in a list must exit successfully (with an exit code of `0`):
|
|
5
|
+
*
|
|
6
|
+
* - `first`: only the first specified command;
|
|
7
|
+
* - `last`: only the last specified command;
|
|
8
|
+
* - `all`: all commands.
|
|
9
|
+
*/
|
|
10
|
+
export declare type SuccessCondition = 'first' | 'last' | 'all';
|
|
11
|
+
/**
|
|
12
|
+
* Provides logic to determine whether lists of commands ran successfully.
|
|
13
|
+
*/
|
|
14
|
+
export declare class CompletionListener {
|
|
15
|
+
private readonly successCondition;
|
|
16
|
+
private readonly scheduler?;
|
|
17
|
+
constructor({ successCondition, scheduler }: {
|
|
18
|
+
/**
|
|
19
|
+
* How this instance will define that a list of commands ran successfully.
|
|
20
|
+
* Defaults to `all`.
|
|
21
|
+
*
|
|
22
|
+
* @see {SuccessCondition}
|
|
23
|
+
*/
|
|
24
|
+
successCondition?: SuccessCondition;
|
|
25
|
+
/**
|
|
26
|
+
* For testing only.
|
|
27
|
+
*/
|
|
28
|
+
scheduler?: Rx.SchedulerLike;
|
|
29
|
+
});
|
|
30
|
+
private isSuccess;
|
|
31
|
+
/**
|
|
32
|
+
* Given a list of commands, wait for all of them to exit and then evaluate their exit codes.
|
|
33
|
+
*
|
|
34
|
+
* @returns A Promise that resolves if the success condition is met, or rejects otherwise.
|
|
35
|
+
*/
|
|
36
|
+
listen(commands: Command[]): Promise<CloseEvent[]>;
|
|
37
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
+
}) : function(o, v) {
|
|
12
|
+
o["default"] = v;
|
|
13
|
+
});
|
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
+
if (mod && mod.__esModule) return mod;
|
|
16
|
+
var result = {};
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
+
__setModuleDefault(result, mod);
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.CompletionListener = void 0;
|
|
23
|
+
const Rx = __importStar(require("rxjs"));
|
|
24
|
+
const operators_1 = require("rxjs/operators");
|
|
25
|
+
/**
|
|
26
|
+
* Provides logic to determine whether lists of commands ran successfully.
|
|
27
|
+
*/
|
|
28
|
+
class CompletionListener {
|
|
29
|
+
constructor({ successCondition = 'all', scheduler }) {
|
|
30
|
+
this.successCondition = successCondition;
|
|
31
|
+
this.scheduler = scheduler;
|
|
32
|
+
}
|
|
33
|
+
isSuccess(exitCodes) {
|
|
34
|
+
switch (this.successCondition) {
|
|
35
|
+
/* eslint-disable indent */
|
|
36
|
+
case 'first':
|
|
37
|
+
return exitCodes[0] === 0;
|
|
38
|
+
case 'last':
|
|
39
|
+
return exitCodes[exitCodes.length - 1] === 0;
|
|
40
|
+
default:
|
|
41
|
+
return exitCodes.every(exitCode => exitCode === 0);
|
|
42
|
+
/* eslint-enable indent */
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Given a list of commands, wait for all of them to exit and then evaluate their exit codes.
|
|
47
|
+
*
|
|
48
|
+
* @returns A Promise that resolves if the success condition is met, or rejects otherwise.
|
|
49
|
+
*/
|
|
50
|
+
listen(commands) {
|
|
51
|
+
const closeStreams = commands.map(command => command.close);
|
|
52
|
+
return Rx.merge(...closeStreams)
|
|
53
|
+
.pipe((0, operators_1.bufferCount)(closeStreams.length), (0, operators_1.switchMap)(exitInfos => this.isSuccess(exitInfos.map(({ exitCode }) => exitCode))
|
|
54
|
+
? Rx.of(exitInfos, this.scheduler)
|
|
55
|
+
: Rx.throwError(exitInfos, this.scheduler)), (0, operators_1.take)(1))
|
|
56
|
+
.toPromise();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
exports.CompletionListener = CompletionListener;
|
|
60
|
+
;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { Writable } from 'stream';
|
|
3
|
+
import { CloseEvent, Command, CommandInfo, KillProcess, SpawnCommand } from './command';
|
|
4
|
+
import { SuccessCondition } from './completion-listener';
|
|
5
|
+
import { FlowController } from './flow-control/flow-controller';
|
|
6
|
+
import { Logger } from './logger';
|
|
7
|
+
/**
|
|
8
|
+
* A command that is to be passed into `concurrently()`.
|
|
9
|
+
* If value is a string, then that's the command's command line.
|
|
10
|
+
* Fine grained options can be defined by using the object format.
|
|
11
|
+
*/
|
|
12
|
+
export declare type ConcurrentlyCommandInput = string | Partial<CommandInfo>;
|
|
13
|
+
export declare type ConcurrentlyResult = {
|
|
14
|
+
/**
|
|
15
|
+
* All commands created and ran by concurrently.
|
|
16
|
+
*/
|
|
17
|
+
commands: Command[];
|
|
18
|
+
/**
|
|
19
|
+
* A promise that resolves when concurrently ran successfully according to the specified
|
|
20
|
+
* success condition, or reject otherwise.
|
|
21
|
+
*
|
|
22
|
+
* Both the resolved and rejected value is the list of all command's close events.
|
|
23
|
+
*/
|
|
24
|
+
result: Promise<CloseEvent[]>;
|
|
25
|
+
};
|
|
26
|
+
export declare type ConcurrentlyOptions = {
|
|
27
|
+
logger?: Logger;
|
|
28
|
+
/**
|
|
29
|
+
* Which stream should the commands output be written to.
|
|
30
|
+
*/
|
|
31
|
+
outputStream?: Writable;
|
|
32
|
+
group?: boolean;
|
|
33
|
+
prefixColors?: string[];
|
|
34
|
+
/**
|
|
35
|
+
* Maximum number of commands to run at once.
|
|
36
|
+
*
|
|
37
|
+
* If undefined, then all processes will start in parallel.
|
|
38
|
+
* Setting this value to 1 will achieve sequential running.
|
|
39
|
+
*/
|
|
40
|
+
maxProcesses?: number;
|
|
41
|
+
/**
|
|
42
|
+
* Whether commands should be spawned in raw mode.
|
|
43
|
+
* Defaults to false.
|
|
44
|
+
*/
|
|
45
|
+
raw?: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* The current working directory of commands which didn't specify one.
|
|
48
|
+
* Defaults to `process.cwd()`.
|
|
49
|
+
*/
|
|
50
|
+
cwd?: string;
|
|
51
|
+
/**
|
|
52
|
+
* @see CompletionListener
|
|
53
|
+
*/
|
|
54
|
+
successCondition?: SuccessCondition;
|
|
55
|
+
/**
|
|
56
|
+
* Which flow controllers should be applied on commands spawned by concurrently.
|
|
57
|
+
* Defaults to an empty array.
|
|
58
|
+
*/
|
|
59
|
+
controllers: FlowController[];
|
|
60
|
+
/**
|
|
61
|
+
* A function that will spawn commands.
|
|
62
|
+
* Defaults to the `spawn-command` module.
|
|
63
|
+
*/
|
|
64
|
+
spawn: SpawnCommand;
|
|
65
|
+
/**
|
|
66
|
+
* A function that will kill processes.
|
|
67
|
+
* Defaults to the `tree-kill` module.
|
|
68
|
+
*/
|
|
69
|
+
kill: KillProcess;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Core concurrently functionality -- spawns the given commands concurrently and
|
|
73
|
+
* returns the commands themselves + the result according to the specified success condition.
|
|
74
|
+
*
|
|
75
|
+
* @see CompletionListener
|
|
76
|
+
*/
|
|
77
|
+
export declare function concurrently(baseCommands: ConcurrentlyCommandInput[], baseOptions?: Partial<ConcurrentlyOptions>): ConcurrentlyResult;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.concurrently = void 0;
|
|
7
|
+
const assert_1 = __importDefault(require("assert"));
|
|
8
|
+
const lodash_1 = __importDefault(require("lodash"));
|
|
9
|
+
const spawn_command_1 = __importDefault(require("spawn-command"));
|
|
10
|
+
const tree_kill_1 = __importDefault(require("tree-kill"));
|
|
11
|
+
const command_1 = require("./command");
|
|
12
|
+
const expand_npm_shortcut_1 = require("./command-parser/expand-npm-shortcut");
|
|
13
|
+
const expand_npm_wildcard_1 = require("./command-parser/expand-npm-wildcard");
|
|
14
|
+
const strip_quotes_1 = require("./command-parser/strip-quotes");
|
|
15
|
+
const completion_listener_1 = require("./completion-listener");
|
|
16
|
+
const get_spawn_opts_1 = require("./get-spawn-opts");
|
|
17
|
+
const output_writer_1 = require("./output-writer");
|
|
18
|
+
const defaults = {
|
|
19
|
+
spawn: spawn_command_1.default,
|
|
20
|
+
kill: tree_kill_1.default,
|
|
21
|
+
raw: false,
|
|
22
|
+
controllers: [],
|
|
23
|
+
cwd: undefined,
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Core concurrently functionality -- spawns the given commands concurrently and
|
|
27
|
+
* returns the commands themselves + the result according to the specified success condition.
|
|
28
|
+
*
|
|
29
|
+
* @see CompletionListener
|
|
30
|
+
*/
|
|
31
|
+
function concurrently(baseCommands, baseOptions) {
|
|
32
|
+
assert_1.default.ok(Array.isArray(baseCommands), '[concurrently] commands should be an array');
|
|
33
|
+
assert_1.default.notStrictEqual(baseCommands.length, 0, '[concurrently] no commands provided');
|
|
34
|
+
const options = lodash_1.default.defaults(baseOptions, defaults);
|
|
35
|
+
const commandParsers = [
|
|
36
|
+
new strip_quotes_1.StripQuotes(),
|
|
37
|
+
new expand_npm_shortcut_1.ExpandNpmShortcut(),
|
|
38
|
+
new expand_npm_wildcard_1.ExpandNpmWildcard()
|
|
39
|
+
];
|
|
40
|
+
let lastColor = '';
|
|
41
|
+
let commands = (0, lodash_1.default)(baseCommands)
|
|
42
|
+
.map(mapToCommandInfo)
|
|
43
|
+
.flatMap(command => parseCommand(command, commandParsers))
|
|
44
|
+
.map((command, index) => {
|
|
45
|
+
// Use documented behaviour of repeating last color when specifying more commands than colors
|
|
46
|
+
lastColor = options.prefixColors && options.prefixColors[index] || lastColor;
|
|
47
|
+
return new command_1.Command(Object.assign({
|
|
48
|
+
index,
|
|
49
|
+
prefixColor: lastColor,
|
|
50
|
+
}, command), (0, get_spawn_opts_1.getSpawnOpts)({
|
|
51
|
+
raw: options.raw,
|
|
52
|
+
env: command.env,
|
|
53
|
+
cwd: command.cwd || options.cwd,
|
|
54
|
+
}), options.spawn, options.kill);
|
|
55
|
+
})
|
|
56
|
+
.value();
|
|
57
|
+
const handleResult = options.controllers.reduce(({ commands: prevCommands, onFinishCallbacks }, controller) => {
|
|
58
|
+
const { commands, onFinish } = controller.handle(prevCommands);
|
|
59
|
+
return {
|
|
60
|
+
commands,
|
|
61
|
+
onFinishCallbacks: lodash_1.default.concat(onFinishCallbacks, onFinish ? [onFinish] : [])
|
|
62
|
+
};
|
|
63
|
+
}, { commands, onFinishCallbacks: [] });
|
|
64
|
+
commands = handleResult.commands;
|
|
65
|
+
if (options.logger) {
|
|
66
|
+
const outputWriter = new output_writer_1.OutputWriter({
|
|
67
|
+
outputStream: options.outputStream,
|
|
68
|
+
group: options.group,
|
|
69
|
+
commands,
|
|
70
|
+
});
|
|
71
|
+
options.logger.output.subscribe(({ command, text }) => outputWriter.write(command, text));
|
|
72
|
+
}
|
|
73
|
+
const commandsLeft = commands.slice();
|
|
74
|
+
const maxProcesses = Math.max(1, Number(options.maxProcesses) || commandsLeft.length);
|
|
75
|
+
for (let i = 0; i < maxProcesses; i++) {
|
|
76
|
+
maybeRunMore(commandsLeft);
|
|
77
|
+
}
|
|
78
|
+
const result = new completion_listener_1.CompletionListener({ successCondition: options.successCondition })
|
|
79
|
+
.listen(commands)
|
|
80
|
+
.finally(() => {
|
|
81
|
+
handleResult.onFinishCallbacks.forEach((onFinish) => onFinish());
|
|
82
|
+
});
|
|
83
|
+
return {
|
|
84
|
+
result,
|
|
85
|
+
commands,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
exports.concurrently = concurrently;
|
|
89
|
+
;
|
|
90
|
+
function mapToCommandInfo(command) {
|
|
91
|
+
if (typeof command === 'string') {
|
|
92
|
+
return {
|
|
93
|
+
command,
|
|
94
|
+
name: '',
|
|
95
|
+
env: {},
|
|
96
|
+
cwd: '',
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
return Object.assign({
|
|
100
|
+
command: command.command,
|
|
101
|
+
name: command.name || '',
|
|
102
|
+
env: command.env || {},
|
|
103
|
+
cwd: command.cwd || '',
|
|
104
|
+
}, command.prefixColor ? {
|
|
105
|
+
prefixColor: command.prefixColor,
|
|
106
|
+
} : {});
|
|
107
|
+
}
|
|
108
|
+
function parseCommand(command, parsers) {
|
|
109
|
+
return parsers.reduce((commands, parser) => lodash_1.default.flatMap(commands, command => parser.parse(command)), lodash_1.default.castArray(command));
|
|
110
|
+
}
|
|
111
|
+
function maybeRunMore(commandsLeft) {
|
|
112
|
+
const command = commandsLeft.shift();
|
|
113
|
+
if (!command) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
command.start();
|
|
117
|
+
command.close.subscribe(() => {
|
|
118
|
+
maybeRunMore(commandsLeft);
|
|
119
|
+
});
|
|
120
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { SuccessCondition } from './completion-listener';
|
|
2
|
+
export declare const defaultInputTarget = 0;
|
|
3
|
+
/**
|
|
4
|
+
* Whether process.stdin should be forwarded to child processes
|
|
5
|
+
*/
|
|
6
|
+
export declare const handleInput = false;
|
|
7
|
+
/**
|
|
8
|
+
* How many processes to run at once.
|
|
9
|
+
*/
|
|
10
|
+
export declare const maxProcesses = 0;
|
|
11
|
+
export declare const hide = "";
|
|
12
|
+
export declare const nameSeparator = ",";
|
|
13
|
+
/**
|
|
14
|
+
* Which prefix style to use when logging processes output.
|
|
15
|
+
*/
|
|
16
|
+
export declare const prefix = "";
|
|
17
|
+
/**
|
|
18
|
+
* Default prefix color.
|
|
19
|
+
* @see https://www.npmjs.com/package/chalk
|
|
20
|
+
*/
|
|
21
|
+
export declare const prefixColors = "reset";
|
|
22
|
+
/**
|
|
23
|
+
* How many bytes we'll show on the command prefix
|
|
24
|
+
*/
|
|
25
|
+
export declare const prefixLength = 10;
|
|
26
|
+
export declare const raw = false;
|
|
27
|
+
/**
|
|
28
|
+
* Number of attempts of restarting a process, if it exits with non-0 code
|
|
29
|
+
*/
|
|
30
|
+
export declare const restartTries = 0;
|
|
31
|
+
/**
|
|
32
|
+
* How many milliseconds concurrently should wait before restarting a process.
|
|
33
|
+
*/
|
|
34
|
+
export declare const restartDelay = 0;
|
|
35
|
+
/**
|
|
36
|
+
* Condition of success for concurrently itself.
|
|
37
|
+
*/
|
|
38
|
+
export declare const success: SuccessCondition;
|
|
39
|
+
/**
|
|
40
|
+
* Date format used when logging date/time.
|
|
41
|
+
* @see https://date-fns.org/v2.0.1/docs/format
|
|
42
|
+
*/
|
|
43
|
+
export declare const timestampFormat = "yyyy-MM-dd HH:mm:ss.SSS";
|
|
44
|
+
/**
|
|
45
|
+
* Current working dir passed as option to spawn command.
|
|
46
|
+
* Defaults to process.cwd()
|
|
47
|
+
*/
|
|
48
|
+
export declare const cwd: string | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* Whether to show timing information for processes in console output
|
|
51
|
+
*/
|
|
52
|
+
export declare const timings = false;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// This file is meant to be a shared place for default configs.
|
|
3
|
+
// It's read by the flow controllers, the executable, etc.
|
|
4
|
+
// Refer to tests for the meaning of the different possible values.
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.timings = exports.cwd = exports.timestampFormat = exports.success = exports.restartDelay = exports.restartTries = exports.raw = exports.prefixLength = exports.prefixColors = exports.prefix = exports.nameSeparator = exports.hide = exports.maxProcesses = exports.handleInput = exports.defaultInputTarget = void 0;
|
|
7
|
+
exports.defaultInputTarget = 0;
|
|
8
|
+
/**
|
|
9
|
+
* Whether process.stdin should be forwarded to child processes
|
|
10
|
+
*/
|
|
11
|
+
exports.handleInput = false;
|
|
12
|
+
/**
|
|
13
|
+
* How many processes to run at once.
|
|
14
|
+
*/
|
|
15
|
+
exports.maxProcesses = 0;
|
|
16
|
+
// Indices and names of commands whose output are not to be logged
|
|
17
|
+
exports.hide = '';
|
|
18
|
+
exports.nameSeparator = ',';
|
|
19
|
+
/**
|
|
20
|
+
* Which prefix style to use when logging processes output.
|
|
21
|
+
*/
|
|
22
|
+
exports.prefix = '';
|
|
23
|
+
/**
|
|
24
|
+
* Default prefix color.
|
|
25
|
+
* @see https://www.npmjs.com/package/chalk
|
|
26
|
+
*/
|
|
27
|
+
exports.prefixColors = 'reset';
|
|
28
|
+
/**
|
|
29
|
+
* How many bytes we'll show on the command prefix
|
|
30
|
+
*/
|
|
31
|
+
exports.prefixLength = 10;
|
|
32
|
+
exports.raw = false;
|
|
33
|
+
/**
|
|
34
|
+
* Number of attempts of restarting a process, if it exits with non-0 code
|
|
35
|
+
*/
|
|
36
|
+
exports.restartTries = 0;
|
|
37
|
+
/**
|
|
38
|
+
* How many milliseconds concurrently should wait before restarting a process.
|
|
39
|
+
*/
|
|
40
|
+
exports.restartDelay = 0;
|
|
41
|
+
/**
|
|
42
|
+
* Condition of success for concurrently itself.
|
|
43
|
+
*/
|
|
44
|
+
exports.success = 'all';
|
|
45
|
+
/**
|
|
46
|
+
* Date format used when logging date/time.
|
|
47
|
+
* @see https://date-fns.org/v2.0.1/docs/format
|
|
48
|
+
*/
|
|
49
|
+
exports.timestampFormat = 'yyyy-MM-dd HH:mm:ss.SSS';
|
|
50
|
+
/**
|
|
51
|
+
* Current working dir passed as option to spawn command.
|
|
52
|
+
* Defaults to process.cwd()
|
|
53
|
+
*/
|
|
54
|
+
exports.cwd = undefined;
|
|
55
|
+
/**
|
|
56
|
+
* Whether to show timing information for processes in console output
|
|
57
|
+
*/
|
|
58
|
+
exports.timings = false;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Command } from '../command';
|
|
2
|
+
/**
|
|
3
|
+
* Interface for a class that controls and/or watches the behavior of commands.
|
|
4
|
+
*
|
|
5
|
+
* This may include logging their output, creating interactions between them, or changing when they
|
|
6
|
+
* actually finish.
|
|
7
|
+
*/
|
|
8
|
+
export interface FlowController {
|
|
9
|
+
handle(commands: Command[]): {
|
|
10
|
+
commands: Command[];
|
|
11
|
+
onFinish?: () => void;
|
|
12
|
+
};
|
|
13
|
+
}
|