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.
Files changed (92) hide show
  1. package/README.md +25 -14
  2. package/dist/bin/bin-options.d.ts +1 -0
  3. package/dist/bin/bin-options.js +1 -0
  4. package/dist/bin/{concurrently.js → index.js} +23 -62
  5. package/dist/bin/normalize-cli-command.d.ts +1 -0
  6. package/dist/bin/normalize-cli-command.js +15 -0
  7. package/dist/bin/read-package-json.d.ts +4 -0
  8. package/dist/bin/read-package-json.js +17 -0
  9. package/dist/lib/assert.d.ts +10 -0
  10. package/dist/lib/assert.js +24 -0
  11. package/dist/{src → lib}/command-parser/expand-arguments.d.ts +2 -2
  12. package/dist/{src → lib}/command-parser/expand-arguments.js +7 -12
  13. package/dist/{src → lib}/command-parser/expand-shortcut.d.ts +2 -2
  14. package/dist/{src → lib}/command-parser/expand-shortcut.js +1 -5
  15. package/dist/{src → lib}/command-parser/expand-wildcard.d.ts +2 -2
  16. package/dist/{src → lib}/command-parser/expand-wildcard.js +21 -28
  17. package/dist/{src → lib}/command.d.ts +5 -4
  18. package/dist/{src → lib}/command.js +3 -39
  19. package/dist/{src → lib}/completion-listener.d.ts +2 -2
  20. package/dist/{src → lib}/completion-listener.js +9 -46
  21. package/dist/{src → lib}/concurrently.d.ts +10 -10
  22. package/dist/{src → lib}/concurrently.js +29 -40
  23. package/dist/{src → lib}/date-format.d.ts +2 -2
  24. package/dist/{src → lib}/date-format.js +97 -76
  25. package/dist/{src → lib}/defaults.d.ts +2 -6
  26. package/dist/{src → lib}/defaults.js +16 -23
  27. package/dist/{src → lib}/flow-control/flow-controller.d.ts +1 -1
  28. package/dist/lib/flow-control/flow-controller.js +1 -0
  29. package/dist/{src → lib}/flow-control/input-handler.d.ts +4 -4
  30. package/dist/{src → lib}/flow-control/input-handler.js +8 -44
  31. package/dist/{src → lib}/flow-control/kill-on-signal.d.ts +3 -3
  32. package/dist/{src → lib}/flow-control/kill-on-signal.js +3 -7
  33. package/dist/{src → lib}/flow-control/kill-others.d.ts +3 -3
  34. package/dist/{src → lib}/flow-control/kill-others.js +8 -12
  35. package/dist/{src → lib}/flow-control/log-error.d.ts +3 -3
  36. package/dist/{src → lib}/flow-control/log-error.js +1 -5
  37. package/dist/{src → lib}/flow-control/log-exit.d.ts +3 -3
  38. package/dist/{src → lib}/flow-control/log-exit.js +1 -5
  39. package/dist/{src → lib}/flow-control/log-output.d.ts +3 -3
  40. package/dist/{src → lib}/flow-control/log-output.js +1 -5
  41. package/dist/{src → lib}/flow-control/log-timings.d.ts +3 -3
  42. package/dist/{src → lib}/flow-control/log-timings.js +8 -45
  43. package/dist/{src → lib}/flow-control/logger-padding.d.ts +3 -3
  44. package/dist/{src → lib}/flow-control/logger-padding.js +7 -7
  45. package/dist/{src → lib}/flow-control/output-error-handler.d.ts +4 -4
  46. package/dist/{src → lib}/flow-control/output-error-handler.js +3 -7
  47. package/dist/{src → lib}/flow-control/restart-process.d.ts +4 -4
  48. package/dist/lib/flow-control/restart-process.js +61 -0
  49. package/dist/{src → lib}/flow-control/teardown.d.ts +4 -5
  50. package/dist/lib/flow-control/teardown.js +45 -0
  51. package/dist/{src → lib}/index.d.ts +21 -19
  52. package/dist/lib/index.js +98 -0
  53. package/dist/{src → lib}/jsonc.js +3 -8
  54. package/dist/{src → lib}/logger.d.ts +3 -2
  55. package/dist/{src → lib}/logger.js +109 -65
  56. package/dist/{src → lib}/observables.d.ts +1 -1
  57. package/dist/{src → lib}/observables.js +3 -6
  58. package/dist/{src → lib}/output-writer.d.ts +3 -3
  59. package/dist/{src → lib}/output-writer.js +4 -41
  60. package/dist/lib/prefix-color-selector.d.ts +21 -0
  61. package/dist/{src → lib}/prefix-color-selector.js +14 -31
  62. package/dist/{src → lib}/spawn.d.ts +14 -5
  63. package/dist/lib/spawn.js +105 -0
  64. package/dist/lib/utils.d.ts +25 -0
  65. package/dist/lib/utils.js +52 -0
  66. package/dist/tsconfig.tsbuildinfo +1 -1
  67. package/docs/README.md +6 -0
  68. package/docs/cli/prefixing.md +44 -4
  69. package/docs/shell-resolution.md +48 -0
  70. package/package.json +48 -67
  71. package/dist/bin/read-package.d.ts +0 -6
  72. package/dist/bin/read-package.js +0 -56
  73. package/dist/src/assert.d.ts +0 -5
  74. package/dist/src/assert.js +0 -15
  75. package/dist/src/command-parser/command-parser.d.ts +0 -19
  76. package/dist/src/command-parser/command-parser.js +0 -2
  77. package/dist/src/command-parser/strip-quotes.d.ts +0 -16
  78. package/dist/src/command-parser/strip-quotes.js +0 -17
  79. package/dist/src/flow-control/flow-controller.js +0 -2
  80. package/dist/src/flow-control/restart-process.js +0 -98
  81. package/dist/src/flow-control/teardown.js +0 -82
  82. package/dist/src/index.js +0 -96
  83. package/dist/src/prefix-color-selector.d.ts +0 -11
  84. package/dist/src/spawn.js +0 -49
  85. package/dist/src/utils.d.ts +0 -10
  86. package/dist/src/utils.js +0 -16
  87. package/index.d.mts +0 -7
  88. package/index.d.ts +0 -11
  89. package/index.js +0 -14
  90. package/index.mjs +0 -9
  91. /package/dist/bin/{concurrently.d.ts → index.d.ts} +0 -0
  92. /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/concurrently.spec.ts","../bin/concurrently.ts","../bin/read-package.ts","../declarations/intl.d.ts","../src/assert.spec.ts","../src/assert.ts","../src/command.spec.ts","../src/command.ts","../src/completion-listener.spec.ts","../src/completion-listener.ts","../src/concurrently.spec.ts","../src/concurrently.ts","../src/date-format.spec.ts","../src/date-format.ts","../src/defaults.ts","../src/index.ts","../src/jsonc.spec.ts","../src/jsonc.ts","../src/logger.spec.ts","../src/logger.ts","../src/observables.spec.ts","../src/observables.ts","../src/output-writer.spec.ts","../src/output-writer.ts","../src/prefix-color-selector.spec.ts","../src/prefix-color-selector.ts","../src/spawn.spec.ts","../src/spawn.ts","../src/utils.spec.ts","../src/utils.ts","../src/command-parser/command-parser.ts","../src/command-parser/expand-arguments.spec.ts","../src/command-parser/expand-arguments.ts","../src/command-parser/expand-shortcut.spec.ts","../src/command-parser/expand-shortcut.ts","../src/command-parser/expand-wildcard.spec.ts","../src/command-parser/expand-wildcard.ts","../src/command-parser/strip-quotes.spec.ts","../src/command-parser/strip-quotes.ts","../src/fixtures/create-mock-instance.ts","../src/fixtures/fake-command.ts","../src/flow-control/flow-controller.ts","../src/flow-control/input-handler.spec.ts","../src/flow-control/input-handler.ts","../src/flow-control/kill-on-signal.spec.ts","../src/flow-control/kill-on-signal.ts","../src/flow-control/kill-others.spec.ts","../src/flow-control/kill-others.ts","../src/flow-control/log-error.spec.ts","../src/flow-control/log-error.ts","../src/flow-control/log-exit.spec.ts","../src/flow-control/log-exit.ts","../src/flow-control/log-output.spec.ts","../src/flow-control/log-output.ts","../src/flow-control/log-timings.spec.ts","../src/flow-control/log-timings.ts","../src/flow-control/logger-padding.spec.ts","../src/flow-control/logger-padding.ts","../src/flow-control/output-error-handler.spec.ts","../src/flow-control/output-error-handler.ts","../src/flow-control/restart-process.spec.ts","../src/flow-control/restart-process.ts","../src/flow-control/teardown.spec.ts","../src/flow-control/teardown.ts"],"version":"5.9.2"}
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
@@ -1,5 +1,11 @@
1
1
  # Concurrently Documentation
2
2
 
3
+ ## General
4
+
5
+ These articles apply when using either concurrently's CLI or API:
6
+
7
+ - [Shell Resolution](./shell-resolution.md)
8
+
3
9
  ## CLI
4
10
 
5
11
  These articles cover using concurrently through CLI:
@@ -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, there are no colors applied to concurrently prefixes, and they just use whatever the terminal's defaults are.
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`), or `auto`, to automatically select a color.
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 prepending `.<modifier 1>.<modifier 2>` and so on.
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 red,bold.blue.dim 'echo Hello there' 'echo General Kenobi!'
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
- "version": "9.2.1",
3
+ "type": "module",
4
+ "version": "10.0.1",
4
5
  "description": "Run commands concurrently",
5
- "main": "index.js",
6
- "types": "index.d.ts",
7
- "type": "commonjs",
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
- "author": "Kimmo Brunfeldt",
42
- "license": "MIT",
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": "4.1.2",
42
+ "chalk": "5.6.2",
45
43
  "rxjs": "7.8.2",
46
- "shell-quote": "1.8.3",
47
- "supports-color": "8.1.1",
44
+ "shell-quote": "1.8.4",
45
+ "supports-color": "10.2.2",
48
46
  "tree-kill": "1.2.2",
49
- "yargs": "17.7.2"
47
+ "yargs": "18.0.0"
50
48
  },
51
49
  "devDependencies": {
52
- "@eslint/js": "^9.33.0",
50
+ "@eslint/js": "^10.0.1",
53
51
  "@hirez_io/observer-spy": "^2.2.0",
54
- "@types/node": "^18.19.123",
52
+ "@types/node": "^20.19.41",
55
53
  "@types/shell-quote": "^1.7.5",
56
- "@types/supports-color": "^8.1.3",
57
- "@types/yargs": "^17.0.33",
58
- "@vitest/coverage-v8": "^3.2.4",
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
- "esbuild": "~0.25.9",
63
- "eslint": "^9.33.0",
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.3.0",
67
- "eslint-plugin-prettier": "^5.5.4",
68
- "eslint-plugin-simple-import-sort": "^12.1.1",
69
- "globals": "16.3.0",
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": "^15.5.2",
72
- "prettier": "^3.6.2",
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.2",
76
- "typescript-eslint": "^8.40.0",
77
- "vitest": "^3.2.4"
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
- "*.?(m){js,ts}": "eslint --fix",
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/concurrently.js",
97
- "clean": "tsc --build --clean",
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
  }
@@ -1,6 +0,0 @@
1
- /**
2
- * Traverses the directory tree until a package.json file is found.
3
- *
4
- * @throws if the root directory is reached, and no package.json is found.
5
- */
6
- export declare function readPackage(): Record<string, unknown>;
@@ -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
- }
@@ -1,5 +0,0 @@
1
- /**
2
- * Asserts that some condition is true, and if not, prints a warning about it being deprecated.
3
- * The message is printed only once.
4
- */
5
- export declare function assertDeprecated(check: boolean, name: string, message: string): void;
@@ -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,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -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;
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });