concurrently 4.0.1 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.travis.yml CHANGED
@@ -6,3 +6,5 @@ node_js:
6
6
  script:
7
7
  - npm test
8
8
  - npm run lint
9
+ after_success:
10
+ - npm run report-coverage
package/CONTRIBUTING.md CHANGED
@@ -6,7 +6,6 @@ updated.
6
6
 
7
7
  **Pull requests:** You don't need to bump version numbers or modify anything related to releasing. That stuff is fully automated, just write the functionality.
8
8
 
9
-
10
9
  # Maintaining
11
10
 
12
11
  ## Test
@@ -14,11 +13,9 @@ updated.
14
13
  Tests can be run with command:
15
14
 
16
15
  ```bash
17
- mocha
16
+ npm run test
18
17
  ```
19
18
 
20
- You need to have *mocha* installed globally with `npm install -g mocha`.
21
-
22
19
  ## Release
23
20
 
24
21
  * Commit all changes
package/README.md CHANGED
@@ -225,25 +225,25 @@ For more details, visit https://github.com/kimmobrunfeldt/concurrently
225
225
  concurrently can be used programmatically by using the API documented below:
226
226
 
227
227
  ### `concurrently(commands[, options])`
228
- - `commands`: an array of either strings (containing the commands to run) or objects
228
+ - `commands`: an array of either strings (containing the commands to run) or objects
229
229
  with the shape `{ command, name, prefixColor }`.
230
230
  - `options` (optional): an object containing any of the below:
231
- - `defaultInputTarget`: the default input target when reading from `inputStream`.
231
+ - `defaultInputTarget`: the default input target when reading from `inputStream`.
232
232
  Default: `0`.
233
- - `inputStream`: a [`Readable` stream](https://nodejs.org/dist/latest-v10.x/docs/api/stream.html#stream_readable_streams)
233
+ - `inputStream`: a [`Readable` stream](https://nodejs.org/dist/latest-v10.x/docs/api/stream.html#stream_readable_streams)
234
234
  to read the input from, eg `process.stdin`.
235
- - `killOthers`: an array of exitting conditions that will cause a process to kill others.
235
+ - `killOthers`: an array of exitting conditions that will cause a process to kill others.
236
236
  Can contain any of `success` or `failure`.
237
237
  - `outputStream`: a [`Writable` stream](https://nodejs.org/dist/latest-v10.x/docs/api/stream.html#stream_writable_streams)
238
238
  to write logs to. Default: `process.stdout`.
239
- - `prefix`: the prefix type to use when logging processes output.
240
- Possible values: `index`, `pid`, `time`, `command`, `name`, `none`, or a template (eg `[{time} process: {pid}]`).
239
+ - `prefix`: the prefix type to use when logging processes output.
240
+ Possible values: `index`, `pid`, `time`, `command`, `name`, `none`, or a template (eg `[{time} process: {pid}]`).
241
241
  Default: the name of the process, or its index if no name is set.
242
242
  - `prefixLength`: how many characters to show when prefixing with `command`. Default: `10`
243
243
  - `raw`: whether raw mode should be used, meaning strictly process output will
244
244
  be logged, without any prefixes, colouring or extra stuff.
245
245
  - `successCondition`: the condition to consider the run was successful.
246
- If `first`, only the first process will make up the success of the run; if `last`, the last.
246
+ If `first`, only the first process to exit will make up the success of the run; if `last`, the last process that exits will determine whether the run succeeds.
247
247
  Anything else means all processes should exit successfully.
248
248
  - `restartTries`: how many attempts to restart a process that dies will be made. Default: `0`.
249
249
  - `restartDelay`: how many milliseconds to wait between process restarts. Default: `0`.
@@ -258,7 +258,7 @@ Example:
258
258
  ```js
259
259
  const concurrently = require('concurrently');
260
260
  concurrently([
261
- 'npm:watch-*',
261
+ 'npm:watch-*',
262
262
  { command: 'nodemon', name: 'server' }
263
263
  ], {
264
264
  prefix: 'name',
@@ -282,3 +282,6 @@ concurrently([
282
282
  So *null* means the process didn't terminate normally. This will make **concurrent**
283
283
  to return non-zero exit code too.
284
284
 
285
+ * Does this work with the npm-replacement [yarn](https://github.com/yarnpkg/yarn)?
286
+
287
+ Yes! In all examples above, you may replace "`npm`" with "`yarn`".
@@ -8,7 +8,7 @@ const args = yargs
8
8
  .usage('$0 [options] <command ...>')
9
9
  .help('h')
10
10
  .alias('h', 'help')
11
- .version('v')
11
+ .version('v', require('../package.json').version)
12
12
  .alias('v', 'V')
13
13
  .alias('v', 'version')
14
14
  .options({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "concurrently",
3
- "version": "4.0.1",
3
+ "version": "4.1.0",
4
4
  "description": "Run commands concurrently",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -11,6 +11,7 @@
11
11
  },
12
12
  "scripts": {
13
13
  "lint": "eslint . --ignore-path .gitignore",
14
+ "report-coverage": "cat coverage/lcov.info | coveralls",
14
15
  "test": "jest"
15
16
  },
16
17
  "repository": {
@@ -32,13 +33,14 @@
32
33
  "date-fns": "^1.23.0",
33
34
  "lodash": "^4.17.10",
34
35
  "read-pkg": "^4.0.1",
35
- "rxjs": "6.2.2",
36
+ "rxjs": "^6.3.3",
36
37
  "spawn-command": "^0.0.2-1",
37
38
  "supports-color": "^4.5.0",
38
39
  "tree-kill": "^1.1.0",
39
40
  "yargs": "^12.0.1"
40
41
  },
41
42
  "devDependencies": {
43
+ "coveralls": "^3.0.2",
42
44
  "eslint": "^5.4.0",
43
45
  "jest": "^23.5.0",
44
46
  "jest-create-mock-instance": "^1.1.0"
@@ -1,13 +1,13 @@
1
1
  module.exports = class ExpandNpmShortcut {
2
2
  parse(commandInfo) {
3
- const [, cmdName, args] = commandInfo.command.match(/^npm:(\S+)(.*)/) || [];
3
+ const [, npmCmd, cmdName, args] = commandInfo.command.match(/^(npm|yarn):(\S+)(.*)/) || [];
4
4
  if (!cmdName) {
5
5
  return commandInfo;
6
6
  }
7
7
 
8
8
  return Object.assign({}, commandInfo, {
9
9
  name: commandInfo.name || cmdName,
10
- command: `npm run ${cmdName}${args}`
10
+ command: `${npmCmd} run ${cmdName}${args}`
11
11
  });
12
12
  }
13
13
  };
@@ -9,25 +9,28 @@ it('returns same command if no npm: prefix is present', () => {
9
9
  expect(parser.parse(commandInfo)).toBe(commandInfo);
10
10
  });
11
11
 
12
- describe('with npm: prefix', () => {
13
- it('expands to "npm run <script> <args>"', () => {
14
- const commandInfo = {
15
- name: 'echo',
16
- command: 'npm:foo -- bar'
17
- };
18
- expect(parser.parse(commandInfo)).toEqual({
19
- name: 'echo',
20
- command: 'npm run foo -- bar'
12
+ for (const npmCmd of ['npm', 'yarn']) {
13
+ describe(`with ${npmCmd}: prefix`, () => {
14
+ it(`expands to "${npmCmd} run <script> <args>"`, () => {
15
+ const commandInfo = {
16
+ name: 'echo',
17
+ command: `${npmCmd}:foo -- bar`
18
+ };
19
+ expect(parser.parse(commandInfo)).toEqual({
20
+ name: 'echo',
21
+ command: `${npmCmd} run foo -- bar`
22
+ });
21
23
  });
22
- });
23
24
 
24
- it('sets name to script name if none', () => {
25
- const commandInfo = {
26
- command: 'npm:foo -- bar'
27
- };
28
- expect(parser.parse(commandInfo)).toEqual({
29
- name: 'foo',
30
- command: 'npm run foo -- bar'
25
+ it('sets name to script name if none', () => {
26
+ const commandInfo = {
27
+ command: `${npmCmd}:foo -- bar`
28
+ };
29
+ expect(parser.parse(commandInfo)).toEqual({
30
+ name: 'foo',
31
+ command: `${npmCmd} run foo -- bar`
32
+ });
31
33
  });
32
34
  });
33
- });
35
+
36
+ }
@@ -7,7 +7,7 @@ module.exports = class ExpandNpmWildcard {
7
7
  }
8
8
 
9
9
  parse(commandInfo) {
10
- const [, cmdName, args] = commandInfo.command.match(/npm run (\S+)([^&]*)/) || [];
10
+ const [, npmCmd, cmdName, args] = commandInfo.command.match(/(npm|yarn) run (\S+)([^&]*)/) || [];
11
11
  const wildcardPosition = (cmdName || '').indexOf('*');
12
12
 
13
13
  // If the regex didn't match an npm script, or it has no wildcard,
@@ -27,7 +27,7 @@ module.exports = class ExpandNpmWildcard {
27
27
  return this.scripts
28
28
  .filter(script => wildcardRegex.test(script))
29
29
  .map(script => Object.assign({}, commandInfo, {
30
- command: `npm run ${script}${args}`,
30
+ command: `${npmCmd} run ${script}${args}`,
31
31
  name: script
32
32
  }));
33
33
  }
@@ -31,24 +31,28 @@ it('expands to nothing if no scripts exist in package.json', () => {
31
31
  expect(parser.parse({ command: 'npm run foo-*-baz qux' })).toEqual([]);
32
32
  });
33
33
 
34
- it('expands to all scripts matching pattern', () => {
35
- readPkg.mockReturnValue({
36
- scripts: {
37
- 'foo-bar-baz': '',
38
- 'foo--baz': '',
39
- }
34
+ for (const npmCmd of ['npm', 'yarn']) {
35
+ describe(`with an ${npmCmd}: prefix`, () => {
36
+ it('expands to all scripts matching pattern', () => {
37
+ readPkg.mockReturnValue({
38
+ scripts: {
39
+ 'foo-bar-baz': '',
40
+ 'foo--baz': '',
41
+ }
42
+ });
43
+
44
+ expect(parser.parse({ command: `${npmCmd} run foo-*-baz qux` })).toEqual([
45
+ { name: 'foo-bar-baz', command: `${npmCmd} run foo-bar-baz qux` },
46
+ { name: 'foo--baz', command: `${npmCmd} run foo--baz qux` },
47
+ ]);
48
+ });
49
+
50
+ it('caches scripts upon calls', () => {
51
+ readPkg.mockReturnValue({});
52
+ parser.parse({ command: `${npmCmd} run foo-*-baz qux` });
53
+ parser.parse({ command: `${npmCmd} run foo-*-baz qux` });
54
+
55
+ expect(readPkg).toHaveBeenCalledTimes(1);
56
+ });
40
57
  });
41
-
42
- expect(parser.parse({ command: 'npm run foo-*-baz qux' })).toEqual([
43
- { name: 'foo-bar-baz', command: 'npm run foo-bar-baz qux' },
44
- { name: 'foo--baz', command: 'npm run foo--baz qux' },
45
- ]);
46
- });
47
-
48
- it('caches scripts upon calls', () => {
49
- readPkg.mockReturnValue({});
50
- parser.parse({ command: 'npm run foo-*-baz qux' });
51
- parser.parse({ command: 'npm run foo-*-baz qux' });
52
-
53
- expect(readPkg).toHaveBeenCalledTimes(1);
54
- });
58
+ }
@@ -13,6 +13,16 @@ beforeEach(() => {
13
13
  controller = new KillOnSignal({ process });
14
14
  });
15
15
 
16
+ it('returns commands that keep non-close streams from original commands', () => {
17
+ const newCommands = controller.handle(commands);
18
+ newCommands.forEach((newCommand, i) => {
19
+ expect(newCommand.close).not.toBe(commands[i].close);
20
+ expect(newCommand.error).toBe(commands[i].error);
21
+ expect(newCommand.stdout).toBe(commands[i].stdout);
22
+ expect(newCommand.stderr).toBe(commands[i].stderr);
23
+ });
24
+ });
25
+
16
26
  it('returns commands that map SIGINT to exit code 0', () => {
17
27
  const newCommands = controller.handle(commands);
18
28
  expect(newCommands).not.toBe(commands);
@@ -29,6 +39,18 @@ it('returns commands that map SIGINT to exit code 0', () => {
29
39
  expect(callback).toHaveBeenCalledWith(0);
30
40
  });
31
41
 
42
+ it('returns commands that keep non-SIGINT exit codes', () => {
43
+ const newCommands = controller.handle(commands);
44
+ expect(newCommands).not.toBe(commands);
45
+ expect(newCommands).toHaveLength(commands.length);
46
+
47
+ const callback = jest.fn();
48
+ newCommands[0].close.subscribe(callback);
49
+ commands[0].close.next(1);
50
+
51
+ expect(callback).toHaveBeenCalledWith(1);
52
+ });
53
+
32
54
  it('kills all commands on SIGINT', () => {
33
55
  controller.handle(commands);
34
56
  process.emit('SIGINT');
@@ -116,4 +116,14 @@ describe('returned commands', () => {
116
116
  // 1 failure from commands[0], 1 success from commands[1]
117
117
  expect(callback).toHaveBeenCalledTimes(2);
118
118
  });
119
+
120
+ it('keep non-close streams from original commands', () => {
121
+ const newCommands = controller.handle(commands);
122
+ newCommands.forEach((newCommand, i) => {
123
+ expect(newCommand.close).not.toBe(commands[i].close);
124
+ expect(newCommand.error).toBe(commands[i].error);
125
+ expect(newCommand.stdout).toBe(commands[i].stdout);
126
+ expect(newCommand.stderr).toBe(commands[i].stderr);
127
+ });
128
+ });
119
129
  });