concurrently 7.0.0 → 7.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +85 -34
  2. package/dist/.DS_Store +0 -0
  3. package/dist/bin/concurrently.js +66 -41
  4. package/dist/bin/epilogue.js +22 -6
  5. package/dist/src/command-parser/expand-arguments.d.ts +12 -0
  6. package/dist/src/command-parser/expand-arguments.js +40 -0
  7. package/dist/src/command-parser/expand-npm-shortcut.js +1 -1
  8. package/dist/src/command-parser/expand-npm-wildcard.js +11 -2
  9. package/dist/src/command-parser/strip-quotes.js +1 -1
  10. package/dist/src/command.d.ts +3 -0
  11. package/dist/src/command.js +1 -1
  12. package/dist/src/completion-listener.d.ts +3 -1
  13. package/dist/src/completion-listener.js +26 -11
  14. package/dist/src/concurrently.d.ts +13 -0
  15. package/dist/src/concurrently.js +6 -2
  16. package/dist/src/defaults.d.ts +14 -4
  17. package/dist/src/defaults.js +15 -6
  18. package/dist/src/flow-control/kill-on-signal.js +2 -2
  19. package/dist/src/flow-control/restart-process.js +2 -2
  20. package/dist/src/index.d.ts +5 -0
  21. package/dist/src/index.js +3 -2
  22. package/package.json +12 -8
  23. package/dist/bin/concurrently.spec.d.ts +0 -1
  24. package/dist/src/command-parser/expand-npm-shortcut.spec.d.ts +0 -1
  25. package/dist/src/command-parser/expand-npm-wildcard.spec.d.ts +0 -1
  26. package/dist/src/command-parser/strip-quotes.spec.d.ts +0 -1
  27. package/dist/src/command.spec.d.ts +0 -1
  28. package/dist/src/completion-listener.spec.d.ts +0 -1
  29. package/dist/src/concurrently.spec.d.ts +0 -1
  30. package/dist/src/flow-control/input-handler.spec.d.ts +0 -1
  31. package/dist/src/flow-control/kill-on-signal.spec.d.ts +0 -1
  32. package/dist/src/flow-control/kill-others.spec.d.ts +0 -1
  33. package/dist/src/flow-control/log-error.spec.d.ts +0 -1
  34. package/dist/src/flow-control/log-exit.spec.d.ts +0 -1
  35. package/dist/src/flow-control/log-output.spec.d.ts +0 -1
  36. package/dist/src/flow-control/log-timings.spec.d.ts +0 -1
  37. package/dist/src/flow-control/restart-process.spec.d.ts +0 -1
  38. package/dist/src/get-spawn-opts.spec.d.ts +0 -1
  39. package/dist/src/logger.spec.d.ts +0 -1
  40. package/dist/src/output-writer.spec.d.ts +0 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Concurrently
2
2
 
3
- [![Build Status](https://github.com/open-cli-tools/concurrently/workflows/Tests/badge.svg)](https://github.com/open-cli-tools/concurrently/actions?workflow=Tests)
3
+ [![Build Status](https://github.com/open-cli-tools/concurrently/workflows/Tests/badge.svg)](https://github.com/open-cli-tools/concurrently/actions?workflow=Tests)
4
4
  [![Coverage Status](https://coveralls.io/repos/github/open-cli-tools/concurrently/badge.svg?branch=master)](https://coveralls.io/github/open-cli-tools/concurrently?branch=master)
5
5
 
6
6
  [![NPM Badge](https://nodei.co/npm/concurrently.png?downloads=true)](https://www.npmjs.com/package/concurrently)
@@ -109,38 +109,68 @@ concurrently -n w: npm:watch-*
109
109
  concurrently -n w:js,w:css,w:node "npm run watch-js" "npm run watch-css" "npm run watch-node"
110
110
  ```
111
111
 
112
+ Exclusion is also supported. Given the following scripts in package.json:
113
+ ```javascript
114
+ {
115
+ // ...
116
+ "scripts": {
117
+ "lint:js": "...",
118
+ "lint:ts": "...",
119
+ "lint:fix:js": "...",
120
+ "lint:fix:ts": "...",
121
+ // ...
122
+ }
123
+ // ...
124
+ }
125
+ ```
126
+ ```bash
127
+ # Running only lint:js and lint:ts
128
+ # with lint:fix:js and lint:fix:ts excluded
129
+ concurrently "npm:lint:*(!fix)"
130
+ ```
131
+
112
132
  Good frontend one-liner example [here](https://github.com/kimmobrunfeldt/dont-copy-paste-this-frontend-template/blob/5cd2bde719654941bdfc0a42c6f1b8e69ae79980/package.json#L9).
113
133
 
114
134
  Help:
115
135
 
116
136
  ```
117
-
118
137
  concurrently [options] <command ...>
119
138
 
120
139
  General
121
- -m, --max-processes How many processes should run at once.
122
- New processes only spawn after all restart tries of a
123
- process. [number]
124
- -n, --names List of custom names to be used in prefix template.
125
- Example names: "main,browser,server" [string]
126
- --name-separator The character to split <names> on. Example usage:
127
- concurrently -n "styles|scripts|server" --name-separator
128
- "|" [default: ","]
129
- -r, --raw Output only raw output of processes, disables
130
- prettifying and concurrently coloring. [boolean]
131
- -s, --success Return exit code of zero or one based on the success or
132
- failure of the "first" child to terminate, the "last
133
- child", or succeed only if "all" child processes
134
- succeed.
135
- [choices: "first", "last", "all"] [default: "all"]
136
- --no-color Disables colors from logging [boolean]
137
- --hide Comma-separated list of processes to hide the output.
138
- The processes can be identified by their name or index.
139
- [string] [default: ""]
140
- -g, --group Order the output as if the commands were run
141
- sequentially. [boolean]
142
- --timings Show timing information for all processes
140
+ -m, --max-processes How many processes should run at once.
141
+ New processes only spawn after all restart tries
142
+ of a process. [number]
143
+ -n, --names List of custom names to be used in prefix
144
+ template.
145
+ Example names: "main,browser,server" [string]
146
+ --name-separator The character to split <names> on. Example usage:
147
+ concurrently -n "styles|scripts|server"
148
+ --name-separator "|" [default: ","]
149
+ -s, --success Which command(s) must exit with code 0 in order
150
+ for concurrently exit with code 0 too. Options
151
+ are:
152
+ - "first" for the first command to exit;
153
+ - "last" for the last command to exit;
154
+ - "all" for all commands;
155
+ - "command-{name}"/"command-{index}" for the
156
+ commands with that name or index;
157
+ - "!command-{name}"/"!command-{index}" for all
158
+ commands but the ones with that name or index.
159
+ [default: "all"]
160
+ -r, --raw Output only raw output of processes, disables
161
+ prettifying and concurrently coloring. [boolean]
162
+ --no-color Disables colors from logging [boolean]
163
+ --hide Comma-separated list of processes to hide the
164
+ output.
165
+ The processes can be identified by their name or
166
+ index. [string] [default: ""]
167
+ -g, --group Order the output as if the commands were run
168
+ sequentially. [boolean]
169
+ --timings Show timing information for all processes.
143
170
  [boolean] [default: false]
171
+ -P, --passthrough-arguments Passthrough additional arguments to commands
172
+ (accessible via placeholders) instead of treating
173
+ them as commands. [boolean] [default: false]
144
174
 
145
175
  Prefix styling
146
176
  -p, --prefix Prefix used in logging for each process.
@@ -177,9 +207,9 @@ Input handling
177
207
  process. [default: 0]
178
208
 
179
209
  Killing other processes
180
- -k, --kill-others kill other processes if one exits or dies [boolean]
181
- --kill-others-on-fail kill other processes if one exits with non zero
182
- status code [boolean]
210
+ -k, --kill-others Kill other processes if one exits or dies.[boolean]
211
+ --kill-others-on-fail Kill other processes if one exits with non zero
212
+ status code. [boolean]
183
213
 
184
214
  Restarting
185
215
  --restart-tries How many times a process that died should restart.
@@ -192,6 +222,7 @@ Options:
192
222
  -h, --help Show help [boolean]
193
223
  -v, -V, --version Show version number [boolean]
194
224
 
225
+
195
226
  Examples:
196
227
 
197
228
  - Output nothing more than stdout+stderr of child processes
@@ -213,7 +244,8 @@ Examples:
213
244
 
214
245
  - Configuring via environment variables with CONCURRENTLY_ prefix
215
246
 
216
- $ CONCURRENTLY_RAW=true CONCURRENTLY_KILL_OTHERS=true concurrently "echo hello" "echo world"
247
+ $ CONCURRENTLY_RAW=true CONCURRENTLY_KILL_OTHERS=true concurrently "echo
248
+ hello" "echo world"
217
249
 
218
250
  - Send input to default
219
251
 
@@ -238,6 +270,23 @@ Examples:
238
270
 
239
271
  $ concurrently "npm:watch-*"
240
272
 
273
+ - Exclude patterns so that between "lint:js" and "lint:fix:js", only "lint:js"
274
+ is ran
275
+
276
+ $ concurrently "npm:*(!fix)"
277
+
278
+ - Passthrough some additional arguments via '{<number>}' placeholder
279
+
280
+ $ concurrently -P "echo {1}" -- foo
281
+
282
+ - Passthrough all additional arguments via '{@}' placeholder
283
+
284
+ $ concurrently -P "npm:dev-* -- {@}" -- --watch --noEmit
285
+
286
+ - Passthrough all additional arguments combined via '{*}' placeholder
287
+
288
+ $ concurrently -P "npm:dev-* -- {*}" -- --watch --noEmit
289
+
241
290
  For more details, visit https://github.com/open-cli-tools/concurrently
242
291
  ```
243
292
 
@@ -279,8 +328,9 @@ concurrently can be used programmatically by using the API documented below:
279
328
  - `restartDelay`: how many milliseconds to wait between process restarts. Default: `0`.
280
329
  - `timestampFormat`: a [date-fns format](https://date-fns.org/v2.0.1/docs/format)
281
330
  to use when prefixing with `time`. Default: `yyyy-MM-dd HH:mm:ss.ZZZ`
331
+ - `additionalArguments`: list of additional arguments passed that will get replaced in each command. If not defined, no argument replacing will happen.
282
332
 
283
- > **Returns:** an object in the shape `{ commands, result }`.
333
+ > **Returns:** an object in the shape `{ result, commands }`.
284
334
  > - `result`: a `Promise` that resolves if the run was successful (according to `successCondition` option),
285
335
  > or rejects, containing an array of [`CloseEvent`](#CloseEvent), in the order that the commands terminated.
286
336
  > - `commands`: an array of all spawned [`Command`s](#Command).
@@ -289,7 +339,7 @@ Example:
289
339
 
290
340
  ```js
291
341
  const concurrently = require('concurrently');
292
- concurrently([
342
+ const { result } = concurrently([
293
343
  'npm:watch-*',
294
344
  { command: 'nodemon', name: 'server' },
295
345
  { command: 'deploy', name: 'deploy', env: { PUBLIC_KEY: '...' } },
@@ -299,11 +349,12 @@ concurrently([
299
349
  killOthers: ['failure', 'success'],
300
350
  restartTries: 3,
301
351
  cwd: path.resolve(__dirname, 'scripts'),
302
- }).then(success, failure);
352
+ });
353
+ result.then(success, failure);
303
354
  ```
304
355
 
305
356
  ### `Command`
306
- An object that contains all information about a spawned command, and ways to interact with it.
357
+ An object that contains all information about a spawned command, and ways to interact with it.<br>
307
358
  It has the following properties:
308
359
 
309
360
  - `index`: the index of the command among all commands spawned.
@@ -321,11 +372,11 @@ It has the following properties:
321
372
  - `timer`: an RxJS observable to the command's timing events (e.g. starting, stopping).
322
373
  - `close`: an RxJS observable to the command's close events.
323
374
  See [`CloseEvent`](#CloseEvent) for more information.
324
- - `start()`: starts the command, setting up all
375
+ - `start()`: starts the command, setting up all
325
376
  - `kill([signal])`: kills the command, optionally specifying a signal (e.g. `SIGTERM`, `SIGKILL`, etc).
326
377
 
327
378
  ### `CloseEvent`
328
- An object with information about a command's closing event.
379
+ An object with information about a command's closing event.<br>
329
380
  It contains the following properties:
330
381
 
331
382
  - `command`: a stripped down version of [`Command`](#command), including only `name`, `command`, `env` and `cwd` properties.
package/dist/.DS_Store ADDED
Binary file
@@ -24,10 +24,19 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
26
  const yargs_1 = __importDefault(require("yargs"));
27
+ const helpers_1 = require("yargs/helpers");
27
28
  const defaults = __importStar(require("../src/defaults"));
28
29
  const index_1 = __importDefault(require("../src/index"));
29
30
  const epilogue_1 = require("./epilogue");
30
- const args = yargs_1.default
31
+ // Clean-up arguments (yargs expects only the arguments after the program name)
32
+ const cleanArgs = (0, helpers_1.hideBin)(process.argv);
33
+ // Find argument separator (double dash)
34
+ const argsSepIdx = cleanArgs.findIndex((arg) => arg === '--');
35
+ // Arguments before separator
36
+ const argsBeforeSep = argsSepIdx >= 0 ? cleanArgs.slice(0, argsSepIdx) : cleanArgs;
37
+ // Arguments after separator
38
+ const argsAfterSep = argsSepIdx >= 0 ? cleanArgs.slice(argsSepIdx + 1) : [];
39
+ const args = (0, yargs_1.default)(argsBeforeSep)
31
40
  .usage('$0 [options] <command ...>')
32
41
  .help('h')
33
42
  .alias('h', 'help')
@@ -42,13 +51,13 @@ const args = yargs_1.default
42
51
  alias: 'm',
43
52
  describe: 'How many processes should run at once.\n' +
44
53
  'New processes only spawn after all restart tries of a process.',
45
- type: 'number'
54
+ type: 'number',
46
55
  },
47
56
  'names': {
48
57
  alias: 'n',
49
58
  describe: 'List of custom names to be used in prefix template.\n' +
50
59
  'Example names: "main,browser,server"',
51
- type: 'string'
60
+ type: 'string',
52
61
  },
53
62
  'name-separator': {
54
63
  describe: 'The character to split <names> on. Example usage:\n' +
@@ -57,49 +66,61 @@ const args = yargs_1.default
57
66
  },
58
67
  'success': {
59
68
  alias: 's',
60
- describe: 'Return exit code of zero or one based on the success or failure ' +
61
- 'of the "first" child to terminate, the "last child", or succeed ' +
62
- 'only if "all" child processes succeed.',
63
- choices: ['first', 'last', 'all'],
64
- default: defaults.success
69
+ describe: 'Which command(s) must exit with code 0 in order for concurrently exit with ' +
70
+ 'code 0 too. Options are:\n' +
71
+ '- "first" for the first command to exit;\n' +
72
+ '- "last" for the last command to exit;\n' +
73
+ '- "all" for all commands;\n' +
74
+ // Note: not a typo. Multiple commands can have the same name.
75
+ '- "command-{name}"/"command-{index}" for the commands with that name or index;\n' +
76
+ '- "!command-{name}"/"!command-{index}" for all commands but the ones with that ' +
77
+ 'name or index.\n',
78
+ default: defaults.success,
65
79
  },
66
80
  'raw': {
67
81
  alias: 'r',
68
82
  describe: 'Output only raw output of processes, disables prettifying ' +
69
83
  'and concurrently coloring.',
70
- type: 'boolean'
84
+ type: 'boolean',
71
85
  },
72
86
  // This one is provided for free. Chalk reads this itself and removes colours.
73
87
  // https://www.npmjs.com/package/chalk#chalksupportscolor
74
88
  'no-color': {
75
89
  describe: 'Disables colors from logging',
76
- type: 'boolean'
90
+ type: 'boolean',
77
91
  },
78
92
  'hide': {
79
93
  describe: 'Comma-separated list of processes to hide the output.\n' +
80
94
  'The processes can be identified by their name or index.',
81
95
  default: defaults.hide,
82
- type: 'string'
96
+ type: 'string',
83
97
  },
84
98
  'group': {
85
99
  alias: 'g',
86
100
  describe: 'Order the output as if the commands were run sequentially.',
87
- type: 'boolean'
101
+ type: 'boolean',
88
102
  },
89
103
  'timings': {
90
- describe: 'Show timing information for all processes',
104
+ describe: 'Show timing information for all processes.',
105
+ type: 'boolean',
106
+ default: defaults.timings,
107
+ },
108
+ 'passthrough-arguments': {
109
+ alias: 'P',
110
+ describe: 'Passthrough additional arguments to commands (accessible via placeholders) ' +
111
+ 'instead of treating them as commands.',
91
112
  type: 'boolean',
92
- default: defaults.timings
113
+ default: defaults.passthroughArguments,
93
114
  },
94
115
  // Kill others
95
116
  'kill-others': {
96
117
  alias: 'k',
97
- describe: 'kill other processes if one exits or dies',
98
- type: 'boolean'
118
+ describe: 'Kill other processes if one exits or dies.',
119
+ type: 'boolean',
99
120
  },
100
121
  'kill-others-on-fail': {
101
- describe: 'kill other processes if one exits with non zero status code',
102
- type: 'boolean'
122
+ describe: 'Kill other processes if one exits with non zero status code.',
123
+ type: 'boolean',
103
124
  },
104
125
  // Prefix
105
126
  'prefix': {
@@ -108,7 +129,7 @@ const args = yargs_1.default
108
129
  'Possible values: index, pid, time, command, name, none, or a template. ' +
109
130
  'Example template: "{time}-{pid}"',
110
131
  defaultDescription: 'index or name (when --names is set)',
111
- type: 'string'
132
+ type: 'string',
112
133
  },
113
134
  'prefix-colors': {
114
135
  alias: 'c',
@@ -120,74 +141,78 @@ const args = yargs_1.default
120
141
  '- Available background colors: bgBlack, bgRed, bgGreen, bgYellow, bgBlue, bgMagenta, bgCyan, bgWhite\n' +
121
142
  'See https://www.npmjs.com/package/chalk for more information.',
122
143
  default: defaults.prefixColors,
123
- type: 'string'
144
+ type: 'string',
124
145
  },
125
146
  'prefix-length': {
126
147
  alias: 'l',
127
148
  describe: 'Limit how many characters of the command is displayed in prefix. ' +
128
149
  'The option can be used to shorten the prefix when it is set to "command"',
129
150
  default: defaults.prefixLength,
130
- type: 'number'
151
+ type: 'number',
131
152
  },
132
153
  'timestamp-format': {
133
154
  alias: 't',
134
155
  describe: 'Specify the timestamp in moment/date-fns format.',
135
156
  default: defaults.timestampFormat,
136
- type: 'string'
157
+ type: 'string',
137
158
  },
138
159
  // Restarting
139
160
  'restart-tries': {
140
161
  describe: 'How many times a process that died should restart.\n' +
141
162
  'Negative numbers will make the process restart forever.',
142
163
  default: defaults.restartTries,
143
- type: 'number'
164
+ type: 'number',
144
165
  },
145
166
  'restart-after': {
146
167
  describe: 'Delay time to respawn the process, in milliseconds.',
147
168
  default: defaults.restartDelay,
148
- type: 'number'
169
+ type: 'number',
149
170
  },
150
171
  // Input
151
172
  'handle-input': {
152
173
  alias: 'i',
153
174
  describe: 'Whether input should be forwarded to the child processes. ' +
154
175
  'See examples for more information.',
155
- type: 'boolean'
176
+ type: 'boolean',
156
177
  },
157
178
  'default-input-target': {
158
179
  default: defaults.defaultInputTarget,
159
180
  describe: 'Identifier for child process to which input on stdin ' +
160
181
  'should be sent if not specified at start of input.\n' +
161
- 'Can be either the index or the name of the process.'
162
- }
182
+ 'Can be either the index or the name of the process.',
183
+ },
163
184
  })
164
- .group(['m', 'n', 'name-separator', 'raw', 's', 'no-color', 'hide', 'group', 'timings'], 'General')
185
+ .group(['m', 'n', 'name-separator', 's', 'r', 'no-color', 'hide', 'g', 'timings', 'P'], 'General')
165
186
  .group(['p', 'c', 'l', 't'], 'Prefix styling')
166
187
  .group(['i', 'default-input-target'], 'Input handling')
167
188
  .group(['k', 'kill-others-on-fail'], 'Killing other processes')
168
189
  .group(['restart-tries', 'restart-after'], 'Restarting')
169
190
  .epilogue(epilogue_1.epilogue)
170
- .argv;
171
- const names = (args.names || '').split(args['name-separator']);
172
- (0, index_1.default)(args._.map((command, index) => ({
191
+ .parseSync();
192
+ // Get names of commands by the specified separator
193
+ const names = (args.names || '').split(args.nameSeparator);
194
+ // If "passthrough-arguments" is disabled, treat additional arguments as commands
195
+ const commands = args.passthroughArguments ? args._ : [...args._, ...argsAfterSep];
196
+ (0, index_1.default)(commands.map((command, index) => ({
173
197
  command: String(command),
174
- name: names[index]
198
+ name: names[index],
175
199
  })), {
176
- handleInput: args['handle-input'],
177
- defaultInputTarget: args['default-input-target'],
200
+ handleInput: args.handleInput,
201
+ defaultInputTarget: args.defaultInputTarget,
178
202
  killOthers: args.killOthers
179
203
  ? ['success', 'failure']
180
204
  : (args.killOthersOnFail ? ['failure'] : []),
181
- maxProcesses: args['max-processes'],
205
+ maxProcesses: args.maxProcesses,
182
206
  raw: args.raw,
183
207
  hide: args.hide.split(','),
184
208
  group: args.group,
185
209
  prefix: args.prefix,
186
- prefixColors: args['prefix-colors'].split(','),
187
- prefixLength: args['prefix-length'],
188
- restartDelay: args['restart-after'],
189
- restartTries: args['restart-tries'],
210
+ prefixColors: args.prefixColors.split(','),
211
+ prefixLength: args.prefixLength,
212
+ restartDelay: args.restartAfter,
213
+ restartTries: args.restartTries,
190
214
  successCondition: args.success,
191
- timestampFormat: args['timestamp-format'],
192
- timings: args.timings
215
+ timestampFormat: args.timestampFormat,
216
+ timings: args.timings,
217
+ additionalArguments: args.passthroughArguments ? argsAfterSep : undefined,
193
218
  }).result.then(() => process.exit(0), () => process.exit(1));
@@ -6,11 +6,11 @@ exports.epilogue = void 0;
6
6
  const examples = [
7
7
  {
8
8
  description: 'Output nothing more than stdout+stderr of child processes',
9
- example: '$ $0 --raw "npm run watch-less" "npm run watch-js"'
9
+ example: '$ $0 --raw "npm run watch-less" "npm run watch-js"',
10
10
  },
11
11
  {
12
12
  description: 'Normal output but without colors e.g. when logging to file',
13
- example: '$ $0 --no-color "grunt watch" "http-server" > log'
13
+ example: '$ $0 --no-color "grunt watch" "http-server" > log',
14
14
  },
15
15
  {
16
16
  description: 'Custom prefix',
@@ -28,21 +28,21 @@ const examples = [
28
28
  description: 'Send input to default',
29
29
  example: [
30
30
  '$ $0 --handle-input "nodemon" "npm run watch-js"',
31
- 'rs # Sends rs command to nodemon process'
31
+ 'rs # Sends rs command to nodemon process',
32
32
  ].join('\n'),
33
33
  },
34
34
  {
35
35
  description: 'Send input to specific child identified by index',
36
36
  example: [
37
37
  '$ $0 --handle-input "npm run watch-js" nodemon',
38
- '1:rs'
38
+ '1:rs',
39
39
  ].join('\n'),
40
40
  },
41
41
  {
42
42
  description: 'Send input to specific child identified by name',
43
43
  example: [
44
44
  '$ $0 --handle-input -n js,srv "npm run watch-js" nodemon',
45
- 'srv:rs'
45
+ 'srv:rs',
46
46
  ].join('\n'),
47
47
  },
48
48
  {
@@ -52,7 +52,23 @@ const examples = [
52
52
  {
53
53
  description: 'Shortened NPM run command with wildcard (make sure to wrap it in quotes!)',
54
54
  example: '$ $0 "npm:watch-*"',
55
- }
55
+ },
56
+ {
57
+ description: 'Exclude patterns so that between "lint:js" and "lint:fix:js", only "lint:js" is ran',
58
+ example: '$ $0 "npm:*(!fix)"',
59
+ },
60
+ {
61
+ description: 'Passthrough some additional arguments via \'{<number>}\' placeholder',
62
+ example: '$ $0 -P "echo {1}" -- foo',
63
+ },
64
+ {
65
+ description: 'Passthrough all additional arguments via \'{@}\' placeholder',
66
+ example: '$ $0 -P "npm:dev-* -- {@}" -- --watch --noEmit',
67
+ },
68
+ {
69
+ description: 'Passthrough all additional arguments combined via \'{*}\' placeholder',
70
+ example: '$ $0 -P "npm:dev-* -- {*}" -- --watch --noEmit',
71
+ },
56
72
  ];
57
73
  exports.epilogue = `
58
74
  Examples:
@@ -0,0 +1,12 @@
1
+ import { CommandInfo } from '../command';
2
+ import { CommandParser } from './command-parser';
3
+ /**
4
+ * Replace placeholders with additional arguments.
5
+ */
6
+ export declare class ExpandArguments implements CommandParser {
7
+ private readonly additionalArguments;
8
+ constructor(additionalArguments: string[]);
9
+ parse(commandInfo: CommandInfo): CommandInfo & {
10
+ command: string;
11
+ };
12
+ }
@@ -0,0 +1,40 @@
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
+ constructor(additionalArguments) {
10
+ this.additionalArguments = additionalArguments;
11
+ }
12
+ parse(commandInfo) {
13
+ const command = commandInfo.command.replace(/\\?\{([@\*]|[1-9][0-9]*)\}/g, (match, placeholderTarget) => {
14
+ // Don't replace the placeholder if it is escaped by a backslash.
15
+ if (match.startsWith('\\')) {
16
+ return match.substring(1);
17
+ }
18
+ // Replace numeric placeholder if value exists in additional arguments.
19
+ if (!isNaN(placeholderTarget) &&
20
+ placeholderTarget <= this.additionalArguments.length) {
21
+ return (0, shell_quote_1.quote)([this.additionalArguments[placeholderTarget - 1]]);
22
+ }
23
+ // Replace all arguments placeholder.
24
+ if (placeholderTarget === '@') {
25
+ return (0, shell_quote_1.quote)(this.additionalArguments);
26
+ }
27
+ // Replace combined arguments placeholder.
28
+ if (placeholderTarget === '*') {
29
+ return (0, shell_quote_1.quote)([this.additionalArguments.join(' ')]);
30
+ }
31
+ // Replace placeholder with empty string
32
+ // if value doesn't exist in additional arguments.
33
+ return '';
34
+ });
35
+ return Object.assign({}, commandInfo, {
36
+ command,
37
+ });
38
+ }
39
+ }
40
+ exports.ExpandArguments = ExpandArguments;
@@ -12,7 +12,7 @@ class ExpandNpmShortcut {
12
12
  }
13
13
  return Object.assign({}, commandInfo, {
14
14
  name: commandInfo.name || cmdName,
15
- command: `${npmCmd} run ${cmdName}${args}`
15
+ command: `${npmCmd} run ${cmdName}${args}`,
16
16
  });
17
17
  }
18
18
  }
@@ -22,6 +22,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
22
22
  exports.ExpandNpmWildcard = void 0;
23
23
  const fs = __importStar(require("fs"));
24
24
  const _ = __importStar(require("lodash"));
25
+ const OMISSION = /\(!([^\)]+)\)/;
25
26
  /**
26
27
  * Finds wildcards in npm/yarn/pnpm run commands and replaces them with all matching scripts in the
27
28
  * `package.json` file of the current directory.
@@ -50,13 +51,21 @@ class ExpandNpmWildcard {
50
51
  if (!this.scripts) {
51
52
  this.scripts = Object.keys(this.readPackage().scripts || {});
52
53
  }
53
- const preWildcard = _.escapeRegExp(cmdName.substr(0, wildcardPosition));
54
- const postWildcard = _.escapeRegExp(cmdName.substr(wildcardPosition + 1));
54
+ const omissionRegex = cmdName.match(OMISSION);
55
+ const cmdNameSansOmission = cmdName.replace(OMISSION, '');
56
+ const preWildcard = _.escapeRegExp(cmdNameSansOmission.substr(0, wildcardPosition));
57
+ const postWildcard = _.escapeRegExp(cmdNameSansOmission.substr(wildcardPosition + 1));
55
58
  const wildcardRegex = new RegExp(`^${preWildcard}(.*?)${postWildcard}$`);
56
59
  const currentName = commandInfo.name || '';
57
60
  return this.scripts
58
61
  .map(script => {
59
62
  const match = script.match(wildcardRegex);
63
+ if (omissionRegex) {
64
+ const toOmit = script.match(new RegExp(omissionRegex[1]));
65
+ if (toOmit) {
66
+ return;
67
+ }
68
+ }
60
69
  if (match) {
61
70
  return Object.assign({}, commandInfo, {
62
71
  command: `${npmCmd} run ${script}${args}`,
@@ -9,7 +9,7 @@ class StripQuotes {
9
9
  let { command } = commandInfo;
10
10
  // Removes the quotes surrounding a command.
11
11
  if (/^"(.+?)"$/.test(command) || /^'(.+?)'$/.test(command)) {
12
- command = command.substr(1, command.length - 2);
12
+ command = command.substring(1, command.length - 1);
13
13
  }
14
14
  return Object.assign({}, commandInfo, { command });
15
15
  }
@@ -23,6 +23,9 @@ export interface CommandInfo {
23
23
  * The current working directory of the process when spawned.
24
24
  */
25
25
  cwd?: string;
26
+ /**
27
+ * Color to use on prefix of command.
28
+ */
26
29
  prefixColor?: string;
27
30
  }
28
31
  export interface CloseEvent {
@@ -74,7 +74,7 @@ class Command {
74
74
  startDate,
75
75
  endDate,
76
76
  durationSeconds: durationSeconds + (durationNanoSeconds / 1e9),
77
- }
77
+ },
78
78
  });
79
79
  });
80
80
  child.stdout && pipeTo(Rx.fromEvent(child.stdout, 'data'), this.stdout);
@@ -6,8 +6,10 @@ import { CloseEvent, Command } from './command';
6
6
  * - `first`: only the first specified command;
7
7
  * - `last`: only the last specified command;
8
8
  * - `all`: all commands.
9
+ * - `command-{name|index}`: only the commands with the specified names or index.
10
+ * - `!command-{name|index}`: all commands but the ones with the specified names or index.
9
11
  */
10
- export declare type SuccessCondition = 'first' | 'last' | 'all';
12
+ export declare type SuccessCondition = 'first' | 'last' | 'all' | `command-${string | number}` | `!command-${string | number}`;
11
13
  /**
12
14
  * Provides logic to determine whether lists of commands ran successfully.
13
15
  */
@@ -30,17 +30,32 @@ class CompletionListener {
30
30
  this.successCondition = successCondition;
31
31
  this.scheduler = scheduler;
32
32
  }
33
- isSuccess(exitCodes) {
34
- switch (this.successCondition) {
35
- /* eslint-disable indent */
36
- case 'first':
37
- return exitCodes[0] === 0;
38
- case 'last':
39
- return exitCodes[exitCodes.length - 1] === 0;
40
- default:
41
- return exitCodes.every(exitCode => exitCode === 0);
42
- /* eslint-enable indent */
33
+ isSuccess(events) {
34
+ if (this.successCondition === 'first') {
35
+ return events[0].exitCode === 0;
43
36
  }
37
+ else if (this.successCondition === 'last') {
38
+ return events[events.length - 1].exitCode === 0;
39
+ }
40
+ const commandSyntaxMatch = this.successCondition.match(/^!?command-(.+)$/);
41
+ if (commandSyntaxMatch == null) {
42
+ // If not a `command-` syntax, then it's an 'all' condition or it's treated as such.
43
+ return events.every(({ exitCode }) => exitCode === 0);
44
+ }
45
+ // Check `command-` syntax condition.
46
+ // Note that a command's `name` is not necessarily unique,
47
+ // in which case all of them must meet the success condition.
48
+ const nameOrIndex = commandSyntaxMatch[1];
49
+ const targetCommandsEvents = events.filter(({ command, index }) => (command.name === nameOrIndex
50
+ || index === Number(nameOrIndex)));
51
+ if (this.successCondition.startsWith('!')) {
52
+ // All commands except the specified ones must exit succesfully
53
+ return events.every((event) => (targetCommandsEvents.includes(event)
54
+ || event.exitCode === 0));
55
+ }
56
+ // Only the specified commands must exit succesfully
57
+ return targetCommandsEvents.length > 0
58
+ && targetCommandsEvents.every(event => event.exitCode === 0);
44
59
  }
45
60
  /**
46
61
  * Given a list of commands, wait for all of them to exit and then evaluate their exit codes.
@@ -50,7 +65,7 @@ class CompletionListener {
50
65
  listen(commands) {
51
66
  const closeStreams = commands.map(command => command.close);
52
67
  return Rx.merge(...closeStreams)
53
- .pipe((0, operators_1.bufferCount)(closeStreams.length), (0, operators_1.switchMap)(exitInfos => this.isSuccess(exitInfos.map(({ exitCode }) => exitCode))
68
+ .pipe((0, operators_1.bufferCount)(closeStreams.length), (0, operators_1.switchMap)(exitInfos => this.isSuccess(exitInfos)
54
69
  ? Rx.of(exitInfos, this.scheduler)
55
70
  : Rx.throwError(exitInfos, this.scheduler)), (0, operators_1.take)(1))
56
71
  .toPromise();
@@ -29,7 +29,13 @@ export declare type ConcurrentlyOptions = {
29
29
  * Which stream should the commands output be written to.
30
30
  */
31
31
  outputStream?: Writable;
32
+ /**
33
+ * Whether the output should be ordered as if the commands were run sequentially.
34
+ */
32
35
  group?: boolean;
36
+ /**
37
+ * Comma-separated list of chalk colors to use on prefixes.
38
+ */
33
39
  prefixColors?: string[];
34
40
  /**
35
41
  * Maximum number of commands to run at once.
@@ -67,6 +73,13 @@ export declare type ConcurrentlyOptions = {
67
73
  * Defaults to the `tree-kill` module.
68
74
  */
69
75
  kill: KillProcess;
76
+ /**
77
+ * List of additional arguments passed that will get replaced in each command.
78
+ * If not defined, no argument replacing will happen.
79
+ *
80
+ * @see ExpandArguments
81
+ */
82
+ additionalArguments?: string[];
70
83
  };
71
84
  /**
72
85
  * Core concurrently functionality -- spawns the given commands concurrently and
@@ -9,6 +9,7 @@ const lodash_1 = __importDefault(require("lodash"));
9
9
  const spawn_command_1 = __importDefault(require("spawn-command"));
10
10
  const tree_kill_1 = __importDefault(require("tree-kill"));
11
11
  const command_1 = require("./command");
12
+ const expand_arguments_1 = require("./command-parser/expand-arguments");
12
13
  const expand_npm_shortcut_1 = require("./command-parser/expand-npm-shortcut");
13
14
  const expand_npm_wildcard_1 = require("./command-parser/expand-npm-wildcard");
14
15
  const strip_quotes_1 = require("./command-parser/strip-quotes");
@@ -35,8 +36,11 @@ function concurrently(baseCommands, baseOptions) {
35
36
  const commandParsers = [
36
37
  new strip_quotes_1.StripQuotes(),
37
38
  new expand_npm_shortcut_1.ExpandNpmShortcut(),
38
- new expand_npm_wildcard_1.ExpandNpmWildcard()
39
+ new expand_npm_wildcard_1.ExpandNpmWildcard(),
39
40
  ];
41
+ if (options.additionalArguments) {
42
+ commandParsers.push(new expand_arguments_1.ExpandArguments(options.additionalArguments));
43
+ }
40
44
  let lastColor = '';
41
45
  let commands = (0, lodash_1.default)(baseCommands)
42
46
  .map(mapToCommandInfo)
@@ -58,7 +62,7 @@ function concurrently(baseCommands, baseOptions) {
58
62
  const { commands, onFinish } = controller.handle(prevCommands);
59
63
  return {
60
64
  commands,
61
- onFinishCallbacks: lodash_1.default.concat(onFinishCallbacks, onFinish ? [onFinish] : [])
65
+ onFinishCallbacks: lodash_1.default.concat(onFinishCallbacks, onFinish ? [onFinish] : []),
62
66
  };
63
67
  }, { commands, onFinishCallbacks: [] });
64
68
  commands = handleResult.commands;
@@ -1,14 +1,20 @@
1
1
  import { SuccessCondition } from './completion-listener';
2
2
  export declare const defaultInputTarget = 0;
3
3
  /**
4
- * Whether process.stdin should be forwarded to child processes
4
+ * Whether process.stdin should be forwarded to child processes.
5
5
  */
6
6
  export declare const handleInput = false;
7
7
  /**
8
8
  * How many processes to run at once.
9
9
  */
10
10
  export declare const maxProcesses = 0;
11
+ /**
12
+ * Indices and names of commands whose output are not to be logged.
13
+ */
11
14
  export declare const hide = "";
15
+ /**
16
+ * The character to split <names> on.
17
+ */
12
18
  export declare const nameSeparator = ",";
13
19
  /**
14
20
  * Which prefix style to use when logging processes output.
@@ -20,12 +26,12 @@ export declare const prefix = "";
20
26
  */
21
27
  export declare const prefixColors = "reset";
22
28
  /**
23
- * How many bytes we'll show on the command prefix
29
+ * How many bytes we'll show on the command prefix.
24
30
  */
25
31
  export declare const prefixLength = 10;
26
32
  export declare const raw = false;
27
33
  /**
28
- * Number of attempts of restarting a process, if it exits with non-0 code
34
+ * Number of attempts of restarting a process, if it exits with non-0 code.
29
35
  */
30
36
  export declare const restartTries = 0;
31
37
  /**
@@ -47,6 +53,10 @@ export declare const timestampFormat = "yyyy-MM-dd HH:mm:ss.SSS";
47
53
  */
48
54
  export declare const cwd: string | undefined;
49
55
  /**
50
- * Whether to show timing information for processes in console output
56
+ * Whether to show timing information for processes in console output.
51
57
  */
52
58
  export declare const timings = false;
59
+ /**
60
+ * Passthrough additional arguments to commands (accessible via placeholders) instead of treating them as commands.
61
+ */
62
+ export declare const passthroughArguments = false;
@@ -3,18 +3,23 @@
3
3
  // It's read by the flow controllers, the executable, etc.
4
4
  // Refer to tests for the meaning of the different possible values.
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.timings = exports.cwd = exports.timestampFormat = exports.success = exports.restartDelay = exports.restartTries = exports.raw = exports.prefixLength = exports.prefixColors = exports.prefix = exports.nameSeparator = exports.hide = exports.maxProcesses = exports.handleInput = exports.defaultInputTarget = void 0;
6
+ exports.passthroughArguments = exports.timings = exports.cwd = exports.timestampFormat = exports.success = exports.restartDelay = exports.restartTries = exports.raw = exports.prefixLength = exports.prefixColors = exports.prefix = exports.nameSeparator = exports.hide = exports.maxProcesses = exports.handleInput = exports.defaultInputTarget = void 0;
7
7
  exports.defaultInputTarget = 0;
8
8
  /**
9
- * Whether process.stdin should be forwarded to child processes
9
+ * Whether process.stdin should be forwarded to child processes.
10
10
  */
11
11
  exports.handleInput = false;
12
12
  /**
13
13
  * How many processes to run at once.
14
14
  */
15
15
  exports.maxProcesses = 0;
16
- // Indices and names of commands whose output are not to be logged
16
+ /**
17
+ * Indices and names of commands whose output are not to be logged.
18
+ */
17
19
  exports.hide = '';
20
+ /**
21
+ * The character to split <names> on.
22
+ */
18
23
  exports.nameSeparator = ',';
19
24
  /**
20
25
  * Which prefix style to use when logging processes output.
@@ -26,12 +31,12 @@ exports.prefix = '';
26
31
  */
27
32
  exports.prefixColors = 'reset';
28
33
  /**
29
- * How many bytes we'll show on the command prefix
34
+ * How many bytes we'll show on the command prefix.
30
35
  */
31
36
  exports.prefixLength = 10;
32
37
  exports.raw = false;
33
38
  /**
34
- * Number of attempts of restarting a process, if it exits with non-0 code
39
+ * Number of attempts of restarting a process, if it exits with non-0 code.
35
40
  */
36
41
  exports.restartTries = 0;
37
42
  /**
@@ -53,6 +58,10 @@ exports.timestampFormat = 'yyyy-MM-dd HH:mm:ss.SSS';
53
58
  */
54
59
  exports.cwd = undefined;
55
60
  /**
56
- * Whether to show timing information for processes in console output
61
+ * Whether to show timing information for processes in console output.
57
62
  */
58
63
  exports.timings = false;
64
+ /**
65
+ * Passthrough additional arguments to commands (accessible via placeholders) instead of treating them as commands.
66
+ */
67
+ exports.passthroughArguments = false;
@@ -27,9 +27,9 @@ class KillOnSignal {
27
27
  return new Proxy(command, {
28
28
  get(target, prop) {
29
29
  return prop === 'close' ? closeStream : target[prop];
30
- }
30
+ },
31
31
  });
32
- })
32
+ }),
33
33
  };
34
34
  }
35
35
  }
@@ -61,9 +61,9 @@ class RestartProcess {
61
61
  return new Proxy(command, {
62
62
  get(target, prop) {
63
63
  return prop === 'close' ? closeStream : target[prop];
64
- }
64
+ },
65
65
  });
66
- })
66
+ }),
67
67
  };
68
68
  }
69
69
  }
@@ -63,6 +63,11 @@ export declare type ConcurrentlyOptions = BaseConcurrentlyOptions & {
63
63
  * @see LogTimings
64
64
  */
65
65
  timings?: boolean;
66
+ /**
67
+ * List of additional arguments passed that will get replaced in each command.
68
+ * If not defined, no argument replacing will happen.
69
+ */
70
+ additionalArguments?: string[];
66
71
  };
67
72
  declare const _default: (commands: ConcurrentlyCommandInput[], options?: Partial<ConcurrentlyOptions>) => ConcurrentlyResult;
68
73
  export default _default;
package/dist/src/index.js CHANGED
@@ -57,13 +57,14 @@ exports.default = (commands, options = {}) => {
57
57
  }),
58
58
  new kill_others_1.KillOthers({
59
59
  logger,
60
- conditions: options.killOthers
60
+ conditions: options.killOthers,
61
61
  }),
62
62
  new log_timings_1.LogTimings({
63
63
  logger: options.timings ? logger : null,
64
64
  timestampFormat: options.timestampFormat,
65
- })
65
+ }),
66
66
  ],
67
67
  prefixColors: options.prefixColors || [],
68
+ additionalArguments: options.additionalArguments,
68
69
  });
69
70
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "concurrently",
3
- "version": "7.0.0",
3
+ "version": "7.2.1",
4
4
  "description": "Run commands concurrently",
5
5
  "main": "index.js",
6
6
  "types": "dist/src/index.d.ts",
@@ -44,23 +44,26 @@
44
44
  "date-fns": "^2.16.1",
45
45
  "lodash": "^4.17.21",
46
46
  "rxjs": "^6.6.3",
47
+ "shell-quote": "^1.7.3",
47
48
  "spawn-command": "^0.0.2-1",
48
49
  "supports-color": "^8.1.0",
49
50
  "tree-kill": "^1.2.2",
50
- "yargs": "^16.2.0"
51
+ "yargs": "^17.3.1"
51
52
  },
52
53
  "devDependencies": {
53
54
  "@types/jest": "^27.0.3",
54
55
  "@types/lodash": "^4.14.178",
55
56
  "@types/node": "^17.0.0",
57
+ "@types/shell-quote": "^1.7.1",
56
58
  "@types/supports-color": "^8.1.1",
59
+ "@types/yargs": "^17.0.8",
57
60
  "@typescript-eslint/eslint-plugin": "^5.8.1",
58
61
  "@typescript-eslint/parser": "^5.8.1",
59
- "coveralls": "^3.1.0",
60
- "eslint": "^7.17.0",
61
- "jest": "^26.6.3",
62
- "jest-create-mock-instance": "^1.1.0",
63
- "ts-jest": "^26.5.6",
62
+ "coveralls-next": "^4.1.2",
63
+ "eslint": "^8.15.0",
64
+ "jest": "^27.5.1",
65
+ "jest-create-mock-instance": "^2.0.0",
66
+ "ts-jest": "^27.1.4",
64
67
  "ts-node": "^10.4.0",
65
68
  "typescript": "^4.5.4"
66
69
  },
@@ -69,7 +72,8 @@
69
72
  "index.js",
70
73
  "index.mjs",
71
74
  "!**/fixtures",
72
- "!**/*.spec.js"
75
+ "!**/*.spec.js",
76
+ "!**/*.spec.d.ts"
73
77
  ],
74
78
  "jest": {
75
79
  "preset": "ts-jest",
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};