concurrently 9.2.1 → 10.0.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 +25 -14
- package/dist/bin/bin-options.d.ts +1 -0
- package/dist/bin/bin-options.js +1 -0
- package/dist/bin/{concurrently.js → index.js} +23 -62
- package/dist/bin/normalize-cli-command.d.ts +1 -0
- package/dist/bin/normalize-cli-command.js +15 -0
- package/dist/bin/read-package-json.d.ts +4 -0
- package/dist/bin/read-package-json.js +17 -0
- package/dist/lib/assert.d.ts +10 -0
- package/dist/lib/assert.js +24 -0
- package/dist/{src → lib}/command-parser/expand-arguments.d.ts +2 -2
- package/dist/{src → lib}/command-parser/expand-arguments.js +7 -12
- package/dist/{src → lib}/command-parser/expand-shortcut.d.ts +2 -2
- package/dist/{src → lib}/command-parser/expand-shortcut.js +1 -5
- package/dist/{src → lib}/command-parser/expand-wildcard.d.ts +2 -2
- package/dist/{src → lib}/command-parser/expand-wildcard.js +21 -28
- package/dist/{src → lib}/command.d.ts +5 -4
- package/dist/{src → lib}/command.js +3 -39
- package/dist/{src → lib}/completion-listener.d.ts +2 -2
- package/dist/{src → lib}/completion-listener.js +9 -46
- package/dist/{src → lib}/concurrently.d.ts +10 -10
- package/dist/{src → lib}/concurrently.js +29 -40
- package/dist/{src → lib}/date-format.d.ts +2 -2
- package/dist/{src → lib}/date-format.js +97 -76
- package/dist/{src → lib}/defaults.d.ts +2 -6
- package/dist/{src → lib}/defaults.js +16 -23
- package/dist/{src → lib}/flow-control/flow-controller.d.ts +1 -1
- package/dist/lib/flow-control/flow-controller.js +1 -0
- package/dist/{src → lib}/flow-control/input-handler.d.ts +4 -4
- package/dist/{src → lib}/flow-control/input-handler.js +8 -44
- package/dist/{src → lib}/flow-control/kill-on-signal.d.ts +3 -3
- package/dist/{src → lib}/flow-control/kill-on-signal.js +3 -7
- package/dist/{src → lib}/flow-control/kill-others.d.ts +3 -3
- package/dist/{src → lib}/flow-control/kill-others.js +8 -12
- package/dist/{src → lib}/flow-control/log-error.d.ts +3 -3
- package/dist/{src → lib}/flow-control/log-error.js +1 -5
- package/dist/{src → lib}/flow-control/log-exit.d.ts +3 -3
- package/dist/{src → lib}/flow-control/log-exit.js +1 -5
- package/dist/{src → lib}/flow-control/log-output.d.ts +3 -3
- package/dist/{src → lib}/flow-control/log-output.js +1 -5
- package/dist/{src → lib}/flow-control/log-timings.d.ts +3 -3
- package/dist/{src → lib}/flow-control/log-timings.js +8 -45
- package/dist/{src → lib}/flow-control/logger-padding.d.ts +3 -3
- package/dist/{src → lib}/flow-control/logger-padding.js +7 -7
- package/dist/{src → lib}/flow-control/output-error-handler.d.ts +4 -4
- package/dist/{src → lib}/flow-control/output-error-handler.js +3 -7
- package/dist/{src → lib}/flow-control/restart-process.d.ts +4 -4
- package/dist/lib/flow-control/restart-process.js +61 -0
- package/dist/{src → lib}/flow-control/teardown.d.ts +4 -5
- package/dist/lib/flow-control/teardown.js +45 -0
- package/dist/{src → lib}/index.d.ts +21 -19
- package/dist/lib/index.js +98 -0
- package/dist/{src → lib}/jsonc.js +3 -8
- package/dist/{src → lib}/logger.d.ts +3 -2
- package/dist/{src → lib}/logger.js +109 -65
- package/dist/{src → lib}/observables.d.ts +1 -1
- package/dist/{src → lib}/observables.js +3 -6
- package/dist/{src → lib}/output-writer.d.ts +3 -3
- package/dist/{src → lib}/output-writer.js +4 -41
- package/dist/lib/prefix-color-selector.d.ts +21 -0
- package/dist/{src → lib}/prefix-color-selector.js +14 -31
- package/dist/{src → lib}/spawn.d.ts +14 -5
- package/dist/lib/spawn.js +105 -0
- package/dist/lib/utils.d.ts +25 -0
- package/dist/lib/utils.js +52 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/docs/README.md +6 -0
- package/docs/cli/prefixing.md +44 -4
- package/docs/shell-resolution.md +48 -0
- package/package.json +48 -67
- package/dist/bin/read-package.d.ts +0 -6
- package/dist/bin/read-package.js +0 -56
- package/dist/src/assert.d.ts +0 -5
- package/dist/src/assert.js +0 -15
- package/dist/src/command-parser/command-parser.d.ts +0 -19
- package/dist/src/command-parser/command-parser.js +0 -2
- package/dist/src/command-parser/strip-quotes.d.ts +0 -16
- package/dist/src/command-parser/strip-quotes.js +0 -17
- package/dist/src/flow-control/flow-controller.js +0 -2
- package/dist/src/flow-control/restart-process.js +0 -98
- package/dist/src/flow-control/teardown.js +0 -82
- package/dist/src/index.js +0 -96
- package/dist/src/prefix-color-selector.d.ts +0 -11
- package/dist/src/spawn.js +0 -49
- package/dist/src/utils.d.ts +0 -10
- package/dist/src/utils.js +0 -16
- package/index.d.mts +0 -7
- package/index.d.ts +0 -11
- package/index.js +0 -14
- package/index.mjs +0 -9
- /package/dist/bin/{concurrently.d.ts → index.d.ts} +0 -0
- /package/dist/{src → lib}/jsonc.d.ts +0 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import assert from 'node:assert';
|
|
2
|
+
import { spawn as baseSpawn } from 'node:child_process';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import nodeProcess from 'node:process';
|
|
5
|
+
import supportsColor from 'supports-color';
|
|
6
|
+
import { UnreachableError } from './utils.js';
|
|
7
|
+
/**
|
|
8
|
+
* Creates a spawn function that uses the given shell executable.
|
|
9
|
+
*
|
|
10
|
+
* The shell is resolved in the following priority order:
|
|
11
|
+
* 1. explicit shell option
|
|
12
|
+
* 2. `npm_config_script_shell` env variable
|
|
13
|
+
* 3. platform default (`cmd.exe` on Windows, `/bin/sh` elsewhere)
|
|
14
|
+
*
|
|
15
|
+
* @see https://docs.npmjs.com/cli/v6/using-npm/config#script-shell
|
|
16
|
+
*/
|
|
17
|
+
export function createSpawn(shell,
|
|
18
|
+
// For testing
|
|
19
|
+
spawn = baseSpawn, process = nodeProcess) {
|
|
20
|
+
const resolved = resolveShell(shell, process);
|
|
21
|
+
return (command, spawnOpts) => {
|
|
22
|
+
const { file, args, shellOptions } = getShellSpawnArgs(resolved, command);
|
|
23
|
+
return spawn(file, args, { ...spawnOpts, ...shellOptions });
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
const NPM_SCRIPT_SHELL_ENV = 'npm_config_script_shell';
|
|
27
|
+
/**
|
|
28
|
+
* Resolves which shell executable to use when spawning commands.
|
|
29
|
+
* @see {@link createSpawn()}
|
|
30
|
+
*/
|
|
31
|
+
function resolveShell(shell, process = nodeProcess) {
|
|
32
|
+
if (shell) {
|
|
33
|
+
return shell;
|
|
34
|
+
}
|
|
35
|
+
const npmScriptShell = process.env[NPM_SCRIPT_SHELL_ENV];
|
|
36
|
+
if (npmScriptShell) {
|
|
37
|
+
return npmScriptShell;
|
|
38
|
+
}
|
|
39
|
+
return process.platform === 'win32' ? 'cmd.exe' : '/bin/sh';
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Builds spawn file/args for the given shell and command string.
|
|
43
|
+
*/
|
|
44
|
+
function getShellSpawnArgs(shellPath, command) {
|
|
45
|
+
const kind = detectShellKind(shellPath);
|
|
46
|
+
switch (kind) {
|
|
47
|
+
case 'cmd':
|
|
48
|
+
return {
|
|
49
|
+
file: shellPath,
|
|
50
|
+
args: ['/s', '/c', `"${command}"`],
|
|
51
|
+
shellOptions: { windowsVerbatimArguments: true },
|
|
52
|
+
};
|
|
53
|
+
case 'powershell':
|
|
54
|
+
return {
|
|
55
|
+
file: shellPath,
|
|
56
|
+
args: ['-NoProfile', '-Command', command],
|
|
57
|
+
};
|
|
58
|
+
case 'posix':
|
|
59
|
+
return {
|
|
60
|
+
file: shellPath,
|
|
61
|
+
args: ['-c', command],
|
|
62
|
+
};
|
|
63
|
+
default:
|
|
64
|
+
throw new UnreachableError(kind);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Detects which argument style to use when spawning the given shell executable.
|
|
69
|
+
*/
|
|
70
|
+
function detectShellKind(shellPath) {
|
|
71
|
+
const normalized = shellPath.replace(/\\/g, '/');
|
|
72
|
+
const base = path
|
|
73
|
+
.basename(normalized)
|
|
74
|
+
.toLowerCase()
|
|
75
|
+
.replace(/\.exe$/i, '');
|
|
76
|
+
if (base === 'cmd') {
|
|
77
|
+
return 'cmd';
|
|
78
|
+
}
|
|
79
|
+
if (base === 'powershell' || base === 'pwsh') {
|
|
80
|
+
return 'powershell';
|
|
81
|
+
}
|
|
82
|
+
return 'posix';
|
|
83
|
+
}
|
|
84
|
+
export const getSpawnOpts = ({ colorSupport = supportsColor.stdout, cwd, process = nodeProcess, ipc, stdio = 'normal', env = {}, }) => {
|
|
85
|
+
const stdioValues = stdio === 'normal'
|
|
86
|
+
? ['pipe', 'pipe', 'pipe']
|
|
87
|
+
: stdio === 'raw'
|
|
88
|
+
? ['inherit', 'inherit', 'inherit']
|
|
89
|
+
: ['pipe', 'ignore', 'ignore'];
|
|
90
|
+
if (ipc != null) {
|
|
91
|
+
// Avoid overriding the stdout/stderr/stdin
|
|
92
|
+
assert.ok(ipc > 2, '[concurrently] the IPC channel number should be > 2');
|
|
93
|
+
stdioValues[ipc] = 'ipc';
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
cwd: cwd || process.cwd(),
|
|
97
|
+
stdio: stdioValues,
|
|
98
|
+
...(process.platform.startsWith('win') && { detached: false }),
|
|
99
|
+
env: {
|
|
100
|
+
...(colorSupport ? { FORCE_COLOR: colorSupport.level.toString() } : {}),
|
|
101
|
+
...process.env,
|
|
102
|
+
...env,
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Escapes a string for use in a regular expression.
|
|
3
|
+
*/
|
|
4
|
+
export declare function escapeRegExp(str: string): string;
|
|
5
|
+
type CastArrayResult<T> = T extends undefined | null ? never[] : T extends unknown[] ? T : T[];
|
|
6
|
+
/**
|
|
7
|
+
* Casts a value to an array if it's not one.
|
|
8
|
+
*/
|
|
9
|
+
export declare function castArray<T = never[]>(value?: T): CastArrayResult<T>;
|
|
10
|
+
/**
|
|
11
|
+
* Splits a string on `delimiter`, ignoring delimiters inside parentheses.
|
|
12
|
+
* Trims each segment and discards empty ones.
|
|
13
|
+
*
|
|
14
|
+
* Examples:
|
|
15
|
+
* splitOutsideParens('red,rgb(255,0,0),blue', ',') → ['red', 'rgb(255,0,0)', 'blue']
|
|
16
|
+
* splitOutsideParens('black.bgHex(#533AFD).dim', '.') → ['black', 'bgHex(#533AFD)', 'dim']
|
|
17
|
+
*/
|
|
18
|
+
export declare function splitOutsideParens(input: string, delimiter: string): string[];
|
|
19
|
+
/**
|
|
20
|
+
* Error thrown when a condition is reached that should be impossible.
|
|
21
|
+
*/
|
|
22
|
+
export declare class UnreachableError extends Error {
|
|
23
|
+
constructor(value: never);
|
|
24
|
+
}
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Escapes a string for use in a regular expression.
|
|
3
|
+
*/
|
|
4
|
+
export function escapeRegExp(str) {
|
|
5
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Casts a value to an array if it's not one.
|
|
9
|
+
*/
|
|
10
|
+
export function castArray(value) {
|
|
11
|
+
return (Array.isArray(value) ? value : value != null ? [value] : []);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Splits a string on `delimiter`, ignoring delimiters inside parentheses.
|
|
15
|
+
* Trims each segment and discards empty ones.
|
|
16
|
+
*
|
|
17
|
+
* Examples:
|
|
18
|
+
* splitOutsideParens('red,rgb(255,0,0),blue', ',') → ['red', 'rgb(255,0,0)', 'blue']
|
|
19
|
+
* splitOutsideParens('black.bgHex(#533AFD).dim', '.') → ['black', 'bgHex(#533AFD)', 'dim']
|
|
20
|
+
*/
|
|
21
|
+
export function splitOutsideParens(input, delimiter) {
|
|
22
|
+
const segments = [];
|
|
23
|
+
let current = '';
|
|
24
|
+
let parenDepth = 0;
|
|
25
|
+
for (const char of input) {
|
|
26
|
+
if (char === '(')
|
|
27
|
+
parenDepth++;
|
|
28
|
+
else if (char === ')')
|
|
29
|
+
parenDepth--;
|
|
30
|
+
if (char === delimiter && parenDepth === 0) {
|
|
31
|
+
const trimmed = current.trim();
|
|
32
|
+
if (trimmed)
|
|
33
|
+
segments.push(trimmed);
|
|
34
|
+
current = '';
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
current += char;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const trimmed = current.trim();
|
|
41
|
+
if (trimmed)
|
|
42
|
+
segments.push(trimmed);
|
|
43
|
+
return segments;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Error thrown when a condition is reached that should be impossible.
|
|
47
|
+
*/
|
|
48
|
+
export class UnreachableError extends Error {
|
|
49
|
+
constructor(value) {
|
|
50
|
+
super(`Unreachable condition: ${value}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../bin/
|
|
1
|
+
{"root":["../bin/bin-options.ts","../bin/index.spec.ts","../bin/index.ts","../bin/normalize-cli-command.spec.ts","../bin/normalize-cli-command.ts","../bin/read-package-json.ts","../lib/assert.spec.ts","../lib/assert.ts","../lib/command.spec.ts","../lib/command.ts","../lib/completion-listener.spec.ts","../lib/completion-listener.ts","../lib/concurrently.spec.ts","../lib/concurrently.ts","../lib/date-format.spec.ts","../lib/date-format.ts","../lib/defaults.ts","../lib/index.ts","../lib/jsonc.spec.ts","../lib/jsonc.ts","../lib/logger.spec.ts","../lib/logger.ts","../lib/observables.spec.ts","../lib/observables.ts","../lib/output-writer.spec.ts","../lib/output-writer.ts","../lib/prefix-color-selector.spec.ts","../lib/prefix-color-selector.ts","../lib/spawn.spec.ts","../lib/spawn.ts","../lib/utils.spec.ts","../lib/utils.ts","../lib/__fixtures__/create-mock-instance.ts","../lib/__fixtures__/fake-command.ts","../lib/command-parser/command-parser.d.ts","../lib/command-parser/expand-arguments.spec.ts","../lib/command-parser/expand-arguments.ts","../lib/command-parser/expand-shortcut.spec.ts","../lib/command-parser/expand-shortcut.ts","../lib/command-parser/expand-wildcard.spec.ts","../lib/command-parser/expand-wildcard.ts","../lib/declarations/intl.d.ts","../lib/flow-control/flow-controller.ts","../lib/flow-control/input-handler.spec.ts","../lib/flow-control/input-handler.ts","../lib/flow-control/kill-on-signal.spec.ts","../lib/flow-control/kill-on-signal.ts","../lib/flow-control/kill-others.spec.ts","../lib/flow-control/kill-others.ts","../lib/flow-control/log-error.spec.ts","../lib/flow-control/log-error.ts","../lib/flow-control/log-exit.spec.ts","../lib/flow-control/log-exit.ts","../lib/flow-control/log-output.spec.ts","../lib/flow-control/log-output.ts","../lib/flow-control/log-timings.spec.ts","../lib/flow-control/log-timings.ts","../lib/flow-control/logger-padding.spec.ts","../lib/flow-control/logger-padding.ts","../lib/flow-control/output-error-handler.spec.ts","../lib/flow-control/output-error-handler.ts","../lib/flow-control/restart-process.spec.ts","../lib/flow-control/restart-process.ts","../lib/flow-control/teardown.spec.ts","../lib/flow-control/teardown.ts"],"version":"5.9.3"}
|
package/docs/README.md
CHANGED
package/docs/cli/prefixing.md
CHANGED
|
@@ -56,10 +56,10 @@ $ concurrently --prefix '{index}-{pid}' 'echo Hello there' 'echo General Kenobi!
|
|
|
56
56
|
|
|
57
57
|
## Prefix Colors
|
|
58
58
|
|
|
59
|
-
By default,
|
|
59
|
+
By default, concurrently automatically assigns colors to each command's prefix, cycling through `cyan`, `magenta`, `green`, `yellow`, and `blue` (the same palette and order used by turborepo).
|
|
60
60
|
|
|
61
61
|
This can be changed by using the `--prefix-colors`/`-c` flag, which takes a comma-separated list of colors to use.<br/>
|
|
62
|
-
The available values are color names (e.g. `green`, `magenta`, `gray`, etc), a hex value (such as `#23de43`),
|
|
62
|
+
The available values are color names (e.g. `green`, `magenta`, `gray`, etc), a hex value (such as `#23de43`), `auto` to automatically select a color, or `reset` to disable coloring.
|
|
63
63
|
|
|
64
64
|
```bash
|
|
65
65
|
$ concurrently -c red,blue 'echo Hello there' 'echo General Kenobi!'
|
|
@@ -79,10 +79,10 @@ $ concurrently -c red,blue 'echo Hello there' 'echo General Kenobi!'
|
|
|
79
79
|
- `yellow`
|
|
80
80
|
</details>
|
|
81
81
|
|
|
82
|
-
Colors can take modifiers too. Several can be applied at once by
|
|
82
|
+
Colors can take modifiers too. Several can be applied at once by appending `.<modifier 1>.<modifier 2>` and so on.
|
|
83
83
|
|
|
84
84
|
```bash
|
|
85
|
-
$ concurrently -c
|
|
85
|
+
$ concurrently -c '#23de43.inverse,bold.blue.dim' 'echo Hello there' 'echo General Kenobi!'
|
|
86
86
|
```
|
|
87
87
|
|
|
88
88
|
<details>
|
|
@@ -118,6 +118,46 @@ $ concurrently -c bgGray,red.bgBlack 'echo Hello there' 'echo General Kenobi!'
|
|
|
118
118
|
- `bgYellow`
|
|
119
119
|
</details>
|
|
120
120
|
|
|
121
|
+
### Advanced Color Functions
|
|
122
|
+
|
|
123
|
+
concurrently supports all [Chalk color functions](https://github.com/chalk/chalk#256-and-truecolor-color-support):
|
|
124
|
+
|
|
125
|
+
| Function | Description |
|
|
126
|
+
| ---------------- | --------------------------- |
|
|
127
|
+
| `#RRGGBB` | Foreground hex (shorthand) |
|
|
128
|
+
| `bg#RRGGBB` | Background hex (shorthand) |
|
|
129
|
+
| `hex(#RRGGBB)` | Foreground hex |
|
|
130
|
+
| `bgHex(#RRGGBB)` | Background hex |
|
|
131
|
+
| `rgb(R,G,B)` | Foreground RGB (0-255) |
|
|
132
|
+
| `bgRgb(R,G,B)` | Background RGB (0-255) |
|
|
133
|
+
| `ansi256(N)` | Foreground ANSI 256 (0-255) |
|
|
134
|
+
| `bgAnsi256(N)` | Background ANSI 256 (0-255) |
|
|
135
|
+
|
|
136
|
+
All functions can be chained with colors and modifiers:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
# Hex colors
|
|
140
|
+
$ concurrently -c 'bg#FF0000.bold,black.bgHex(#00FF00).dim' 'echo Red bg' 'echo Green bg'
|
|
141
|
+
|
|
142
|
+
# RGB colors
|
|
143
|
+
$ concurrently -c 'rgb(255,136,0).bold,black.bgRgb(100,100,255)' 'echo Orange' 'echo Blue bg'
|
|
144
|
+
|
|
145
|
+
# ANSI 256 colors
|
|
146
|
+
$ concurrently -c 'ansi256(199),ansi256(50).bgAnsi256(17)' 'echo Pink' 'echo Cyan on blue'
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Scoping the Color to Part of a Template
|
|
150
|
+
|
|
151
|
+
By default, the entire prefix is colored. When using a template, you can restrict coloring to a specific region by wrapping it with the `{color}` and `{/color}` markers — anything outside the markers is rendered without color.
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
$ concurrently -c red,blue --prefix '[{color}{name}{/color}] {pid}' --names one,two 'echo Hello there' 'echo General Kenobi!'
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
In the example above, only `one` and `two` are colored — the surrounding brackets and the PID stay in the terminal's default color.
|
|
158
|
+
|
|
159
|
+
If only one of the markers is present, the missing side is implicit: an `{color}` without a matching `{/color}` colors everything from the opener to the end of the prefix, and a `{/color}` without a preceding `{color}` colors everything from the start of the prefix up to the closer. A template with neither marker is colored in full, matching the previous behavior.
|
|
160
|
+
|
|
121
161
|
## Prefix Length
|
|
122
162
|
|
|
123
163
|
When using the `command` prefix style, it's possible that it'll be too long.<br/>
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Shell Resolution
|
|
2
|
+
|
|
3
|
+
Each command runs inside a shell, not as a bare executable.
|
|
4
|
+
By default, concurrently uses `cmd.exe` on Windows and `/bin/sh` elsewhere.
|
|
5
|
+
|
|
6
|
+
## Using a different shell
|
|
7
|
+
|
|
8
|
+
If the default shell isn't suitable, it's possible to instruct concurrently to use a specific shell in a few ways.
|
|
9
|
+
|
|
10
|
+
This is useful, for example, to use Unix-style syntax (for example `BROWSER=none npm start`) on Windows, if you set concurrently shell to e.g. Git Bash.
|
|
11
|
+
|
|
12
|
+
### Via explicit override
|
|
13
|
+
|
|
14
|
+
An explicit shell override takes precedence over every other configuration.
|
|
15
|
+
To do that, pass the `--shell` flag to the CLI:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
concurrently --shell "C:\Program Files\Git\bin\bash.exe" "echo Hello world | xargs -n 1 echo"
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Or via the API:
|
|
22
|
+
|
|
23
|
+
```js
|
|
24
|
+
concurrently(['echo Hello world | xargs -n 1 echo'], {
|
|
25
|
+
shell: 'C:\\Program Files\\Git\\bin\\bash.exe',
|
|
26
|
+
});
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Via npm/pnpm/yarn v1
|
|
30
|
+
|
|
31
|
+
When using npm, pnpm or yarn v1 to run concurrently via a `package.json` script, the
|
|
32
|
+
[`script-shell` configuration](https://docs.npmjs.com/cli/v6/using-npm/config#script-shell) is inherited and used to spawn commands.
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm config set script-shell /bin/bash
|
|
36
|
+
npm dev # Runs the dev script on bash. Concurrently will also run commands using bash.
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Supported shells
|
|
40
|
+
|
|
41
|
+
If you've specified a different shell, concurrently detects its kind and spawns commands
|
|
42
|
+
using the right syntax for that shell.
|
|
43
|
+
|
|
44
|
+
The following shell types are supported:
|
|
45
|
+
|
|
46
|
+
- Windows `cmd.exe`
|
|
47
|
+
- Powershell
|
|
48
|
+
- Any POSIX compliant shells (bash, zsh, dash, etc)
|
package/package.json
CHANGED
|
@@ -1,35 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "concurrently",
|
|
3
|
-
"
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "10.0.1",
|
|
4
5
|
"description": "Run commands concurrently",
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"bin": {
|
|
9
|
-
"concurrently": "./dist/bin/concurrently.js",
|
|
10
|
-
"conc": "./dist/bin/concurrently.js"
|
|
11
|
-
},
|
|
12
|
-
"engines": {
|
|
13
|
-
"node": ">=18"
|
|
14
|
-
},
|
|
15
|
-
"exports": {
|
|
16
|
-
".": {
|
|
17
|
-
"import": {
|
|
18
|
-
"types": "./index.d.mts",
|
|
19
|
-
"default": "./index.mjs"
|
|
20
|
-
},
|
|
21
|
-
"require": {
|
|
22
|
-
"types": "./index.d.ts",
|
|
23
|
-
"default": "./index.js"
|
|
24
|
-
}
|
|
25
|
-
},
|
|
26
|
-
"./package.json": "./package.json"
|
|
27
|
-
},
|
|
6
|
+
"author": "Kimmo Brunfeldt",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"funding": "https://github.com/open-cli-tools/concurrently?sponsor=1",
|
|
28
9
|
"repository": {
|
|
29
10
|
"type": "git",
|
|
30
11
|
"url": "https://github.com/open-cli-tools/concurrently.git"
|
|
31
12
|
},
|
|
32
|
-
"funding": "https://github.com/open-cli-tools/concurrently?sponsor=1",
|
|
33
13
|
"keywords": [
|
|
34
14
|
"bash",
|
|
35
15
|
"concurrent",
|
|
@@ -38,68 +18,69 @@
|
|
|
38
18
|
"command",
|
|
39
19
|
"sh"
|
|
40
20
|
],
|
|
41
|
-
"
|
|
42
|
-
|
|
21
|
+
"exports": {
|
|
22
|
+
".": "./dist/lib/index.js",
|
|
23
|
+
"./package.json": "./package.json"
|
|
24
|
+
},
|
|
25
|
+
"types": "./dist/lib/index.d.ts",
|
|
26
|
+
"bin": {
|
|
27
|
+
"concurrently": "./dist/bin/index.js",
|
|
28
|
+
"conc": "./dist/bin/index.js"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"!**/*.spec.d.ts",
|
|
32
|
+
"!**/*.spec.js",
|
|
33
|
+
"!**/__fixtures__",
|
|
34
|
+
"dist",
|
|
35
|
+
"dist/tsconfig.tsbuildinfo",
|
|
36
|
+
"docs"
|
|
37
|
+
],
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=22"
|
|
40
|
+
},
|
|
43
41
|
"dependencies": {
|
|
44
|
-
"chalk": "
|
|
42
|
+
"chalk": "5.6.2",
|
|
45
43
|
"rxjs": "7.8.2",
|
|
46
|
-
"shell-quote": "1.8.
|
|
47
|
-
"supports-color": "
|
|
44
|
+
"shell-quote": "1.8.4",
|
|
45
|
+
"supports-color": "10.2.2",
|
|
48
46
|
"tree-kill": "1.2.2",
|
|
49
|
-
"yargs": "
|
|
47
|
+
"yargs": "18.0.0"
|
|
50
48
|
},
|
|
51
49
|
"devDependencies": {
|
|
52
|
-
"@eslint/js": "^
|
|
50
|
+
"@eslint/js": "^10.0.1",
|
|
53
51
|
"@hirez_io/observer-spy": "^2.2.0",
|
|
54
|
-
"@types/node": "^
|
|
52
|
+
"@types/node": "^20.19.41",
|
|
55
53
|
"@types/shell-quote": "^1.7.5",
|
|
56
|
-
"@types/
|
|
57
|
-
"@
|
|
58
|
-
"@vitest/
|
|
59
|
-
"@vitest/eslint-plugin": "^1.3.4",
|
|
60
|
-
"coveralls-next": "^5.0.0",
|
|
54
|
+
"@types/yargs": "^17.0.35",
|
|
55
|
+
"@vitest/coverage-v8": "^4.1.6",
|
|
56
|
+
"@vitest/eslint-plugin": "^1.6.17",
|
|
61
57
|
"ctrlc-wrapper": "^0.0.5",
|
|
62
|
-
"
|
|
63
|
-
"eslint": "^
|
|
64
|
-
"eslint-config-flat-gitignore": "^2.1.0",
|
|
58
|
+
"eslint": "^10.4.0",
|
|
59
|
+
"eslint-config-flat-gitignore": "^2.3.0",
|
|
65
60
|
"eslint-config-prettier": "^10.1.8",
|
|
66
|
-
"eslint-plugin-import-lite": "^0.
|
|
67
|
-
"eslint-plugin-prettier": "^5.5.
|
|
68
|
-
"eslint-plugin-simple-import-sort": "^
|
|
69
|
-
"globals": "
|
|
61
|
+
"eslint-plugin-import-lite": "^0.6.0",
|
|
62
|
+
"eslint-plugin-prettier": "^5.5.5",
|
|
63
|
+
"eslint-plugin-simple-import-sort": "^13.0.0",
|
|
64
|
+
"globals": "^17.6.0",
|
|
70
65
|
"husky": "^9.1.7",
|
|
71
|
-
"lint-staged": "^
|
|
72
|
-
"prettier": "^3.
|
|
66
|
+
"lint-staged": "^17.0.5",
|
|
67
|
+
"prettier": "^3.8.3",
|
|
73
68
|
"safe-publish-latest": "^2.0.0",
|
|
74
69
|
"string-argv": "^0.3.2",
|
|
75
|
-
"typescript": "~5.9.
|
|
76
|
-
"typescript-eslint": "^8.
|
|
77
|
-
"vitest": "^
|
|
70
|
+
"typescript": "~5.9.3",
|
|
71
|
+
"typescript-eslint": "^8.59.3",
|
|
72
|
+
"vitest": "^4.1.6"
|
|
78
73
|
},
|
|
79
|
-
"files": [
|
|
80
|
-
"dist",
|
|
81
|
-
"index.js",
|
|
82
|
-
"index.d.ts",
|
|
83
|
-
"index.mjs",
|
|
84
|
-
"index.d.mts",
|
|
85
|
-
"!**/fixtures",
|
|
86
|
-
"!**/*.spec.js",
|
|
87
|
-
"!**/*.spec.d.ts",
|
|
88
|
-
"docs"
|
|
89
|
-
],
|
|
90
74
|
"lint-staged": {
|
|
91
|
-
"
|
|
75
|
+
"*.{js,ts}": "eslint --fix",
|
|
92
76
|
"*.{json,y?(a)ml,md}": "prettier --write"
|
|
93
77
|
},
|
|
94
78
|
"scripts": {
|
|
95
79
|
"build": "tsc --build",
|
|
96
|
-
"postbuild": "chmod +x dist/bin/
|
|
97
|
-
"
|
|
80
|
+
"postbuild": "chmod +x dist/bin/index.js",
|
|
81
|
+
"typecheck": "tsc --noEmit",
|
|
98
82
|
"format": "prettier --check '**/*.{json,y?(a)ml,md}'",
|
|
99
|
-
"format:fix": "pnpm run format --write",
|
|
100
83
|
"lint": "eslint",
|
|
101
|
-
"lint:fix": "pnpm run lint --fix",
|
|
102
|
-
"report-coverage": "cat coverage/lcov.info | coveralls",
|
|
103
84
|
"test": "vitest --project unit",
|
|
104
85
|
"test:smoke": "vitest run --project smoke"
|
|
105
86
|
}
|
package/dist/bin/read-package.js
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
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
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.readPackage = readPackage;
|
|
37
|
-
const fs = __importStar(require("fs"));
|
|
38
|
-
const path = __importStar(require("path"));
|
|
39
|
-
/**
|
|
40
|
-
* Traverses the directory tree until a package.json file is found.
|
|
41
|
-
*
|
|
42
|
-
* @throws if the root directory is reached, and no package.json is found.
|
|
43
|
-
*/
|
|
44
|
-
function readPackage() {
|
|
45
|
-
let dir = require.main?.path ?? process.cwd();
|
|
46
|
-
let oldDir = dir;
|
|
47
|
-
do {
|
|
48
|
-
const pkgPath = path.join(dir, 'package.json');
|
|
49
|
-
if (fs.existsSync(pkgPath)) {
|
|
50
|
-
return JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
51
|
-
}
|
|
52
|
-
oldDir = dir;
|
|
53
|
-
dir = path.dirname(dir);
|
|
54
|
-
} while (oldDir !== dir);
|
|
55
|
-
throw new Error('package.json not found');
|
|
56
|
-
}
|
package/dist/src/assert.d.ts
DELETED
package/dist/src/assert.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { CommandInfo } from '../command';
|
|
2
|
-
/**
|
|
3
|
-
* A command parser encapsulates a specific logic for mapping `CommandInfo` objects
|
|
4
|
-
* into another `CommandInfo`.
|
|
5
|
-
*
|
|
6
|
-
* A prime example is turning an abstract `npm:foo` into `npm run foo`, but it could also turn
|
|
7
|
-
* the prefix color of a command brighter, or maybe even prefixing each command with `time(1)`.
|
|
8
|
-
*/
|
|
9
|
-
export interface CommandParser {
|
|
10
|
-
/**
|
|
11
|
-
* Parses `commandInfo` and returns one or more `CommandInfo`s.
|
|
12
|
-
*
|
|
13
|
-
* Returning multiple `CommandInfo` is used when there are multiple possibilities of commands to
|
|
14
|
-
* run given the original input.
|
|
15
|
-
* An example of this is when the command contains a wildcard and it must be expanded into all
|
|
16
|
-
* viable options so that the consumer can decide which ones to run.
|
|
17
|
-
*/
|
|
18
|
-
parse(commandInfo: CommandInfo): CommandInfo | CommandInfo[];
|
|
19
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { CommandInfo } from '../command';
|
|
2
|
-
import { CommandParser } from './command-parser';
|
|
3
|
-
/**
|
|
4
|
-
* Strips quotes around commands so that they can run on the current shell.
|
|
5
|
-
*/
|
|
6
|
-
export declare class StripQuotes implements CommandParser {
|
|
7
|
-
parse(commandInfo: CommandInfo): {
|
|
8
|
-
command: string;
|
|
9
|
-
name: string;
|
|
10
|
-
env?: Record<string, unknown>;
|
|
11
|
-
cwd?: string;
|
|
12
|
-
prefixColor?: string;
|
|
13
|
-
ipc?: number;
|
|
14
|
-
raw?: boolean;
|
|
15
|
-
};
|
|
16
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.StripQuotes = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* Strips quotes around commands so that they can run on the current shell.
|
|
6
|
-
*/
|
|
7
|
-
class StripQuotes {
|
|
8
|
-
parse(commandInfo) {
|
|
9
|
-
let { command } = commandInfo;
|
|
10
|
-
// Removes the quotes surrounding a command.
|
|
11
|
-
if (/^"(.+?)"$/.test(command) || /^'(.+?)'$/.test(command)) {
|
|
12
|
-
command = command.slice(1, command.length - 1);
|
|
13
|
-
}
|
|
14
|
-
return { ...commandInfo, command };
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
exports.StripQuotes = StripQuotes;
|