concurrently 9.2.0 → 10.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.
Files changed (149) hide show
  1. package/README.md +25 -15
  2. package/dist/bin/{concurrently.js → index.js} +23 -52
  3. package/dist/bin/index.spec.d.ts +1 -0
  4. package/dist/bin/index.spec.js +368 -0
  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/normalize-cli-command.spec.d.ts +1 -0
  8. package/dist/bin/normalize-cli-command.spec.js +36 -0
  9. package/dist/bin/read-package-json.d.ts +4 -0
  10. package/dist/bin/read-package-json.js +17 -0
  11. package/dist/lib/__fixtures__/create-mock-instance.d.ts +2 -0
  12. package/dist/lib/__fixtures__/create-mock-instance.js +5 -0
  13. package/dist/lib/__fixtures__/fake-command.d.ts +6 -0
  14. package/dist/lib/__fixtures__/fake-command.js +37 -0
  15. package/dist/lib/assert.d.ts +10 -0
  16. package/dist/lib/assert.js +24 -0
  17. package/dist/lib/assert.spec.d.ts +1 -0
  18. package/dist/lib/assert.spec.js +41 -0
  19. package/dist/{src → lib}/command-parser/expand-arguments.d.ts +7 -7
  20. package/dist/lib/command-parser/expand-arguments.js +36 -0
  21. package/dist/lib/command-parser/expand-arguments.spec.d.ts +1 -0
  22. package/dist/lib/command-parser/expand-arguments.spec.js +57 -0
  23. package/dist/{src → lib}/command-parser/expand-shortcut.d.ts +2 -2
  24. package/dist/{src → lib}/command-parser/expand-shortcut.js +1 -5
  25. package/dist/lib/command-parser/expand-shortcut.spec.d.ts +1 -0
  26. package/dist/lib/command-parser/expand-shortcut.spec.js +36 -0
  27. package/dist/{src → lib}/command-parser/expand-wildcard.d.ts +2 -2
  28. package/dist/{src → lib}/command-parser/expand-wildcard.js +25 -31
  29. package/dist/lib/command-parser/expand-wildcard.spec.d.ts +1 -0
  30. package/dist/lib/command-parser/expand-wildcard.spec.js +288 -0
  31. package/dist/{src → lib}/command.d.ts +7 -10
  32. package/dist/{src → lib}/command.js +13 -32
  33. package/dist/lib/command.spec.d.ts +1 -0
  34. package/dist/lib/command.spec.js +369 -0
  35. package/dist/{src → lib}/completion-listener.d.ts +2 -3
  36. package/dist/{src → lib}/completion-listener.js +9 -36
  37. package/dist/lib/completion-listener.spec.d.ts +1 -0
  38. package/dist/lib/completion-listener.spec.js +229 -0
  39. package/dist/{src → lib}/concurrently.d.ts +10 -12
  40. package/dist/{src → lib}/concurrently.js +34 -47
  41. package/dist/lib/concurrently.spec.d.ts +1 -0
  42. package/dist/lib/concurrently.spec.js +320 -0
  43. package/dist/{src → lib}/date-format.d.ts +2 -2
  44. package/dist/{src → lib}/date-format.js +101 -77
  45. package/dist/lib/date-format.spec.d.ts +1 -0
  46. package/dist/lib/date-format.spec.js +480 -0
  47. package/dist/{src → lib}/defaults.d.ts +2 -6
  48. package/dist/{src → lib}/defaults.js +16 -23
  49. package/dist/{src → lib}/flow-control/input-handler.d.ts +4 -5
  50. package/dist/{src → lib}/flow-control/input-handler.js +8 -34
  51. package/dist/lib/flow-control/input-handler.spec.d.ts +1 -0
  52. package/dist/lib/flow-control/input-handler.spec.js +116 -0
  53. package/dist/{src → lib}/flow-control/kill-on-signal.d.ts +3 -5
  54. package/dist/{src → lib}/flow-control/kill-on-signal.js +3 -7
  55. package/dist/lib/flow-control/kill-on-signal.spec.d.ts +1 -0
  56. package/dist/lib/flow-control/kill-on-signal.spec.js +63 -0
  57. package/dist/{src → lib}/flow-control/kill-others.d.ts +3 -4
  58. package/dist/{src → lib}/flow-control/kill-others.js +8 -15
  59. package/dist/lib/flow-control/kill-others.spec.d.ts +1 -0
  60. package/dist/lib/flow-control/kill-others.spec.js +98 -0
  61. package/dist/{src → lib}/flow-control/log-error.d.ts +3 -3
  62. package/dist/{src → lib}/flow-control/log-error.js +1 -5
  63. package/dist/lib/flow-control/log-error.spec.d.ts +1 -0
  64. package/dist/lib/flow-control/log-error.spec.js +33 -0
  65. package/dist/{src → lib}/flow-control/log-exit.d.ts +3 -3
  66. package/dist/{src → lib}/flow-control/log-exit.js +1 -5
  67. package/dist/lib/flow-control/log-exit.spec.d.ts +1 -0
  68. package/dist/lib/flow-control/log-exit.spec.js +24 -0
  69. package/dist/{src → lib}/flow-control/log-output.d.ts +3 -3
  70. package/dist/{src → lib}/flow-control/log-output.js +1 -5
  71. package/dist/lib/flow-control/log-output.spec.d.ts +1 -0
  72. package/dist/lib/flow-control/log-output.spec.js +33 -0
  73. package/dist/{src → lib}/flow-control/log-timings.d.ts +3 -3
  74. package/dist/{src → lib}/flow-control/log-timings.js +11 -44
  75. package/dist/lib/flow-control/log-timings.spec.d.ts +1 -0
  76. package/dist/lib/flow-control/log-timings.spec.js +89 -0
  77. package/dist/{src → lib}/flow-control/logger-padding.d.ts +3 -3
  78. package/dist/{src → lib}/flow-control/logger-padding.js +7 -7
  79. package/dist/lib/flow-control/logger-padding.spec.d.ts +1 -0
  80. package/dist/lib/flow-control/logger-padding.spec.js +60 -0
  81. package/dist/{src → lib}/flow-control/output-error-handler.d.ts +4 -6
  82. package/dist/{src → lib}/flow-control/output-error-handler.js +3 -7
  83. package/dist/lib/flow-control/output-error-handler.spec.d.ts +1 -0
  84. package/dist/lib/flow-control/output-error-handler.spec.js +41 -0
  85. package/dist/{src → lib}/flow-control/restart-process.d.ts +4 -4
  86. package/dist/{src → lib}/flow-control/restart-process.js +10 -37
  87. package/dist/lib/flow-control/restart-process.spec.d.ts +1 -0
  88. package/dist/lib/flow-control/restart-process.spec.js +127 -0
  89. package/dist/{src → lib}/flow-control/teardown.d.ts +4 -5
  90. package/dist/{src → lib}/flow-control/teardown.js +6 -33
  91. package/dist/lib/flow-control/teardown.spec.d.ts +1 -0
  92. package/dist/lib/flow-control/teardown.spec.js +93 -0
  93. package/dist/{src → lib}/index.d.ts +21 -20
  94. package/dist/lib/index.js +98 -0
  95. package/dist/lib/jsonc.d.ts +8 -0
  96. package/dist/{src → lib}/jsonc.js +3 -8
  97. package/dist/lib/jsonc.spec.d.ts +1 -0
  98. package/dist/lib/jsonc.spec.js +73 -0
  99. package/dist/{src → lib}/logger.d.ts +3 -2
  100. package/dist/{src → lib}/logger.js +112 -53
  101. package/dist/lib/logger.spec.d.ts +1 -0
  102. package/dist/lib/logger.spec.js +507 -0
  103. package/dist/{src → lib}/observables.d.ts +1 -2
  104. package/dist/{src → lib}/observables.js +3 -7
  105. package/dist/lib/observables.spec.d.ts +1 -0
  106. package/dist/lib/observables.spec.js +29 -0
  107. package/dist/{src → lib}/output-writer.d.ts +3 -4
  108. package/dist/{src → lib}/output-writer.js +4 -31
  109. package/dist/lib/output-writer.spec.d.ts +1 -0
  110. package/dist/lib/output-writer.spec.js +96 -0
  111. package/dist/lib/prefix-color-selector.d.ts +21 -0
  112. package/dist/{src → lib}/prefix-color-selector.js +14 -31
  113. package/dist/lib/prefix-color-selector.spec.d.ts +1 -0
  114. package/dist/lib/prefix-color-selector.spec.js +159 -0
  115. package/dist/{src → lib}/spawn.d.ts +19 -16
  116. package/dist/lib/spawn.js +105 -0
  117. package/dist/lib/spawn.spec.d.ts +1 -0
  118. package/dist/lib/spawn.spec.js +100 -0
  119. package/dist/lib/utils.d.ts +25 -0
  120. package/dist/lib/utils.js +52 -0
  121. package/dist/lib/utils.spec.d.ts +1 -0
  122. package/dist/lib/utils.spec.js +58 -0
  123. package/dist/tsconfig.tsbuildinfo +1 -0
  124. package/docs/README.md +6 -0
  125. package/docs/cli/passthrough-arguments.md +8 -8
  126. package/docs/cli/prefixing.md +44 -4
  127. package/docs/cli/shortcuts.md +2 -2
  128. package/docs/shell-resolution.md +48 -0
  129. package/package.json +64 -85
  130. package/dist/bin/read-package.d.ts +0 -6
  131. package/dist/bin/read-package.js +0 -47
  132. package/dist/src/assert.d.ts +0 -5
  133. package/dist/src/assert.js +0 -16
  134. package/dist/src/command-parser/command-parser.d.ts +0 -19
  135. package/dist/src/command-parser/command-parser.js +0 -2
  136. package/dist/src/command-parser/expand-arguments.js +0 -39
  137. package/dist/src/command-parser/strip-quotes.d.ts +0 -16
  138. package/dist/src/command-parser/strip-quotes.js +0 -17
  139. package/dist/src/flow-control/flow-controller.d.ts +0 -13
  140. package/dist/src/flow-control/flow-controller.js +0 -2
  141. package/dist/src/index.js +0 -99
  142. package/dist/src/jsonc.d.ts +0 -8
  143. package/dist/src/prefix-color-selector.d.ts +0 -11
  144. package/dist/src/spawn.js +0 -49
  145. package/index.d.mts +0 -7
  146. package/index.d.ts +0 -11
  147. package/index.js +0 -14
  148. package/index.mjs +0 -10
  149. /package/dist/bin/{concurrently.d.ts → index.d.ts} +0 -0
@@ -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
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,58 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { castArray, escapeRegExp, splitOutsideParens } from './utils.js';
3
+ describe('#escapeRegExp()', () => {
4
+ it('escapes all RegExp chars', () => {
5
+ // eslint-disable-next-line no-useless-escape
6
+ const result = escapeRegExp('\*?{}.(?<test>.)|[]');
7
+ expect(result).toBe('\\*\\?\\{\\}\\.\\(\\?<test>\\.\\)\\|\\[\\]');
8
+ });
9
+ });
10
+ describe('#castArray()', () => {
11
+ it('returns empty array for nullish input values', () => {
12
+ const result1 = castArray();
13
+ const result2 = castArray(undefined);
14
+ const result3 = castArray(null);
15
+ expect(result1).toStrictEqual([]);
16
+ expect(result2).toStrictEqual([]);
17
+ expect(result3).toStrictEqual([]);
18
+ });
19
+ it('directly returns value if it is already of type array', () => {
20
+ const value = ['example'];
21
+ const result = castArray(value);
22
+ expect(result).toBe(value);
23
+ });
24
+ describe('casts primitives to an array', () => {
25
+ it.each([1, 'example', {}])('%s', (value) => {
26
+ const result = castArray(value);
27
+ expect(result).toStrictEqual([value]);
28
+ });
29
+ });
30
+ });
31
+ describe('#splitOutsideParens()', () => {
32
+ it('splits on the given delimiter', () => {
33
+ expect(splitOutsideParens('red,blue', ',')).toEqual(['red', 'blue']);
34
+ });
35
+ it('preserves delimiters inside parentheses', () => {
36
+ expect(splitOutsideParens('red,rgb(255,0,0),blue', ',')).toEqual([
37
+ 'red',
38
+ 'rgb(255,0,0)',
39
+ 'blue',
40
+ ]);
41
+ });
42
+ it('splits chalk-style dotted color paths, preserving function calls', () => {
43
+ expect(splitOutsideParens('black.bgHex(#533AFD).dim', '.')).toEqual([
44
+ 'black',
45
+ 'bgHex(#533AFD)',
46
+ 'dim',
47
+ ]);
48
+ });
49
+ it('trims whitespace around each segment', () => {
50
+ expect(splitOutsideParens(' red , blue ', ',')).toEqual(['red', 'blue']);
51
+ });
52
+ it('drops empty segments', () => {
53
+ expect(splitOutsideParens(',,red,,', ',')).toEqual(['red']);
54
+ });
55
+ it('returns an empty array for an empty input', () => {
56
+ expect(splitOutsideParens('', ',')).toEqual([]);
57
+ });
58
+ });
@@ -0,0 +1 @@
1
+ {"root":["../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.d.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:
@@ -11,8 +11,8 @@ For example, imagine you have in your `package.json` file scripts like this:
11
11
  "scripts": {
12
12
  "build:client": "tsc -p client",
13
13
  "build:server": "tsc -p server",
14
- "build": "concurrently npm:build:client npm:build:server"
15
- }
14
+ "build": "concurrently npm:build:client npm:build:server",
15
+ },
16
16
  }
17
17
  ```
18
18
 
@@ -37,8 +37,8 @@ a 1-indexed `{number}` placeholder to the command you want it to apply to:
37
37
  "scripts": {
38
38
  // ...
39
39
  "build": "concurrently -P 'npm:build:client -- {1}' npm:build:server --",
40
- "typecheck": "npm run build -- --noEmit"
41
- }
40
+ "typecheck": "npm run build -- --noEmit",
41
+ },
42
42
  }
43
43
  ```
44
44
 
@@ -55,8 +55,8 @@ to your commands. This can be done with the `{@}` placeholder.
55
55
  "scripts": {
56
56
  // ...
57
57
  "build": "concurrently -P 'npm:build:client -- {@}' 'npm:build:server -- {@}' --",
58
- "typecheck": "npm run build -- --watch --noEmit"
59
- }
58
+ "typecheck": "npm run build -- --watch --noEmit",
59
+ },
60
60
  }
61
61
  ```
62
62
 
@@ -72,8 +72,8 @@ which wraps the arguments in quotes.
72
72
  // ...
73
73
  "scripts": {
74
74
  // ...
75
- "build": "concurrently -P 'npm:build:client -- --outDir {*}/client' 'npm:build:server -- --outDir {*}/server' -- $(date)"
76
- }
75
+ "build": "concurrently -P 'npm:build:client -- --outDir {*}/client' 'npm:build:server -- --outDir {*}/server' -- $(date)",
76
+ },
77
77
  }
78
78
  ```
79
79
 
@@ -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/>
@@ -25,9 +25,9 @@ For example, given the following `package.json` contents:
25
25
  "lint:js": "...",
26
26
  "lint:ts": "...",
27
27
  "lint:fix:js": "...",
28
- "lint:fix:ts": "..."
28
+ "lint:fix:ts": "...",
29
29
  // ...
30
- }
30
+ },
31
31
  // ...
32
32
  }
33
33
  ```
@@ -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,36 +1,16 @@
1
1
  {
2
2
  "name": "concurrently",
3
- "version": "9.2.0",
3
+ "type": "module",
4
+ "version": "10.0.0",
5
+ "packageManager": "pnpm@10.18.2+sha512.9fb969fa749b3ade6035e0f109f0b8a60b5d08a1a87fdf72e337da90dcc93336e2280ca4e44f2358a649b83c17959e9993e777c2080879f3801e6f0d999ad3dd",
4
6
  "description": "Run commands concurrently",
5
- "packageManager": "pnpm@8.15.9+sha256.daa27a0b541bc635323ff96c2ded995467ff9fe6d69ff67021558aa9ad9dcc36",
6
- "main": "index.js",
7
- "types": "index.d.ts",
8
- "type": "commonjs",
9
- "bin": {
10
- "concurrently": "./dist/bin/concurrently.js",
11
- "conc": "./dist/bin/concurrently.js"
12
- },
13
- "engines": {
14
- "node": ">=18"
15
- },
16
- "exports": {
17
- ".": {
18
- "import": {
19
- "types": "./index.d.mts",
20
- "default": "./index.mjs"
21
- },
22
- "require": {
23
- "types": "./index.d.ts",
24
- "default": "./index.js"
25
- }
26
- },
27
- "./package.json": "./package.json"
28
- },
7
+ "author": "Kimmo Brunfeldt",
8
+ "license": "MIT",
9
+ "funding": "https://github.com/open-cli-tools/concurrently?sponsor=1",
29
10
  "repository": {
30
11
  "type": "git",
31
12
  "url": "https://github.com/open-cli-tools/concurrently.git"
32
13
  },
33
- "funding": "https://github.com/open-cli-tools/concurrently?sponsor=1",
34
14
  "keywords": [
35
15
  "bash",
36
16
  "concurrent",
@@ -39,73 +19,72 @@
39
19
  "command",
40
20
  "sh"
41
21
  ],
42
- "author": "Kimmo Brunfeldt",
43
- "license": "MIT",
44
- "dependencies": {
45
- "chalk": "^4.1.2",
46
- "lodash": "^4.17.21",
47
- "rxjs": "^7.8.1",
48
- "shell-quote": "^1.8.1",
49
- "supports-color": "^8.1.1",
50
- "tree-kill": "^1.2.2",
51
- "yargs": "^17.7.2"
22
+ "exports": {
23
+ ".": "./dist/lib/index.js",
24
+ "./package.json": "./package.json"
52
25
  },
53
- "devDependencies": {
54
- "@hirez_io/observer-spy": "^2.2.0",
55
- "@jest/types": "^30.0.0",
56
- "@swc/core": "^1.7.23",
57
- "@swc/jest": "^0.2.36",
58
- "@types/jest": "^30.0.0",
59
- "@types/lodash": "^4.17.7",
60
- "@types/node": "^18.19.50",
61
- "@types/shell-quote": "^1.7.5",
62
- "@types/supports-color": "^8.1.3",
63
- "@types/yargs": "^17.0.33",
64
- "@typescript-eslint/eslint-plugin": "^7.18.0",
65
- "@typescript-eslint/parser": "^7.18.0",
66
- "coveralls-next": "^4.2.1",
67
- "ctrlc-wrapper": "^0.0.4",
68
- "esbuild": "~0.25.0",
69
- "eslint": "^8.57.0",
70
- "eslint-config-prettier": "^9.1.0",
71
- "eslint-plugin-import": "^2.30.0",
72
- "eslint-plugin-jest": "^27.9.0",
73
- "eslint-plugin-prettier": "^5.2.1",
74
- "eslint-plugin-simple-import-sort": "^10.0.0",
75
- "husky": "^9.1.5",
76
- "jest": "^30.0.0",
77
- "jest-create-mock-instance": "^2.0.0",
78
- "lint-staged": "^15.2.10",
79
- "prettier": "^3.0.3",
80
- "safe-publish-latest": "^2.0.0",
81
- "string-argv": "^0.3.2",
82
- "typescript": "~5.2.2"
26
+ "types": "./dist/lib/index.d.ts",
27
+ "bin": {
28
+ "concurrently": "./dist/bin/index.js",
29
+ "conc": "./dist/bin/index.js"
83
30
  },
84
31
  "files": [
85
- "dist",
86
- "index.js",
87
- "index.d.ts",
88
- "index.mjs",
89
- "index.d.mts",
90
- "!**/fixtures",
91
- "!**/*.spec.js",
92
32
  "!**/*.spec.d.ts",
33
+ "!**/*.spec.js",
34
+ "!**/__fixtures__",
35
+ "dist",
36
+ "dist/tsconfig.tsbuildinfo",
93
37
  "docs"
94
38
  ],
95
- "lint-staged": {
96
- "*.?(m){js,ts}": "eslint --fix",
97
- "*.{json,y?(a)ml,md}": "prettier --write"
39
+ "engines": {
40
+ "node": ">=22"
98
41
  },
99
42
  "scripts": {
100
43
  "build": "tsc --build",
101
- "postbuild": "chmod +x dist/bin/concurrently.js",
102
- "clean": "tsc --build --clean",
44
+ "postbuild": "chmod +x dist/bin/index.js",
45
+ "typecheck": "tsc --noEmit",
103
46
  "format": "prettier --check '**/*.{json,y?(a)ml,md}'",
104
- "format:fix": "pnpm run format --write",
105
- "lint": "eslint --ignore-path .gitignore --ext mjs,js,ts .",
106
- "lint:fix": "pnpm run lint --fix",
107
- "report-coverage": "cat coverage/lcov.info | coveralls",
108
- "test": "jest --selectProjects unit",
109
- "test:smoke": "jest --selectProjects smoke"
47
+ "lint": "eslint",
48
+ "prepublishOnly": "safe-publish-latest && pnpm run build",
49
+ "test": "vitest --project unit",
50
+ "test:smoke": "vitest run --project smoke",
51
+ "prepare": "husky"
52
+ },
53
+ "dependencies": {
54
+ "chalk": "5.6.2",
55
+ "rxjs": "7.8.2",
56
+ "shell-quote": "1.8.4",
57
+ "supports-color": "10.2.2",
58
+ "tree-kill": "1.2.2",
59
+ "yargs": "18.0.0"
60
+ },
61
+ "devDependencies": {
62
+ "@eslint/js": "^10.0.1",
63
+ "@hirez_io/observer-spy": "^2.2.0",
64
+ "@types/node": "^20.19.41",
65
+ "@types/shell-quote": "^1.7.5",
66
+ "@types/yargs": "^17.0.35",
67
+ "@vitest/coverage-v8": "^4.1.6",
68
+ "@vitest/eslint-plugin": "^1.6.17",
69
+ "ctrlc-wrapper": "^0.0.5",
70
+ "eslint": "^10.4.0",
71
+ "eslint-config-flat-gitignore": "^2.3.0",
72
+ "eslint-config-prettier": "^10.1.8",
73
+ "eslint-plugin-import-lite": "^0.6.0",
74
+ "eslint-plugin-prettier": "^5.5.5",
75
+ "eslint-plugin-simple-import-sort": "^13.0.0",
76
+ "globals": "^17.6.0",
77
+ "husky": "^9.1.7",
78
+ "lint-staged": "^17.0.5",
79
+ "prettier": "^3.8.3",
80
+ "safe-publish-latest": "^2.0.0",
81
+ "string-argv": "^0.3.2",
82
+ "typescript": "~5.9.3",
83
+ "typescript-eslint": "^8.59.3",
84
+ "vitest": "^4.1.6"
85
+ },
86
+ "lint-staged": {
87
+ "*.{js,ts}": "eslint --fix",
88
+ "*.{json,y?(a)ml,md}": "prettier --write"
110
89
  }
111
- }
90
+ }
@@ -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,47 +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 (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.readPackage = void 0;
27
- const fs = __importStar(require("fs"));
28
- const path = __importStar(require("path"));
29
- /**
30
- * Traverses the directory tree until a package.json file is found.
31
- *
32
- * @throws if the root directory is reached, and no package.json is found.
33
- */
34
- function readPackage() {
35
- let dir = require.main?.path ?? process.cwd();
36
- let oldDir = dir;
37
- do {
38
- const pkgPath = path.join(dir, 'package.json');
39
- if (fs.existsSync(pkgPath)) {
40
- return JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
41
- }
42
- oldDir = dir;
43
- dir = path.dirname(dir);
44
- } while (oldDir !== dir);
45
- throw new Error('package.json not found');
46
- }
47
- exports.readPackage = readPackage;
@@ -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,16 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.assertDeprecated = void 0;
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) {
11
- // eslint-disable-next-line no-console
12
- console.warn(`[concurrently] ${name} is deprecated. ${message}`);
13
- deprecations.add(name);
14
- }
15
- }
16
- exports.assertDeprecated = assertDeprecated;
@@ -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,39 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ExpandArguments = void 0;
4
- const shell_quote_1 = require("shell-quote");
5
- /**
6
- * Replace placeholders with additional arguments.
7
- */
8
- class ExpandArguments {
9
- additionalArguments;
10
- constructor(additionalArguments) {
11
- this.additionalArguments = additionalArguments;
12
- }
13
- parse(commandInfo) {
14
- const command = commandInfo.command.replace(/\\?\{([@*]|[1-9][0-9]*)\}/g, (match, placeholderTarget) => {
15
- // Don't replace the placeholder if it is escaped by a backslash.
16
- if (match.startsWith('\\')) {
17
- return match.slice(1);
18
- }
19
- // Replace numeric placeholder if value exists in additional arguments.
20
- if (!isNaN(placeholderTarget) &&
21
- placeholderTarget <= this.additionalArguments.length) {
22
- return (0, shell_quote_1.quote)([this.additionalArguments[placeholderTarget - 1]]);
23
- }
24
- // Replace all arguments placeholder.
25
- if (placeholderTarget === '@') {
26
- return (0, shell_quote_1.quote)(this.additionalArguments);
27
- }
28
- // Replace combined arguments placeholder.
29
- if (placeholderTarget === '*') {
30
- return (0, shell_quote_1.quote)([this.additionalArguments.join(' ')]);
31
- }
32
- // Replace placeholder with empty string
33
- // if value doesn't exist in additional arguments.
34
- return '';
35
- });
36
- return { ...commandInfo, command };
37
- }
38
- }
39
- exports.ExpandArguments = ExpandArguments;
@@ -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> | undefined;
11
- cwd?: string | undefined;
12
- prefixColor?: string | undefined;
13
- ipc?: number | undefined;
14
- raw?: boolean | undefined;
15
- };
16
- }