concurrently 9.0.1 → 9.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.
@@ -36,7 +36,7 @@ const read_package_1 = require("./read-package");
36
36
  const version = String((0, read_package_1.readPackage)().version);
37
37
  const epilogue = `For documentation and more examples, visit:\nhttps://github.com/open-cli-tools/concurrently/tree/v${version}/docs`;
38
38
  // Clean-up arguments (yargs expects only the arguments after the program name)
39
- const args = (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
39
+ const program = (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
40
40
  .parserConfiguration({
41
41
  // Avoids options that can be specified multiple times from requiring a `--` to pass commands
42
42
  'greedy-arrays': false,
@@ -211,12 +211,16 @@ const args = (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
211
211
  .group(['i', 'default-input-target'], 'Input handling')
212
212
  .group(['k', 'kill-others-on-fail', 'kill-signal'], 'Killing other processes')
213
213
  .group(['restart-tries', 'restart-after'], 'Restarting')
214
- .epilogue(epilogue)
215
- .parseSync();
214
+ .epilogue(epilogue);
215
+ const args = program.parseSync();
216
216
  // Get names of commands by the specified separator
217
217
  const names = (args.names || '').split(args.nameSeparator);
218
218
  const additionalArguments = lodash_1.default.castArray(args['--'] ?? []).map(String);
219
219
  const commands = args.passthroughArguments ? args._ : args._.concat(additionalArguments);
220
+ if (!commands.length) {
221
+ program.showHelp();
222
+ process.exit();
223
+ }
220
224
  (0, index_1.concurrently)(commands.map((command, index) => ({
221
225
  command: String(command),
222
226
  name: names[index],
@@ -0,0 +1,17 @@
1
+ import { CommandInfo } from '../command';
2
+ import { CommandParser } from './command-parser';
3
+ /**
4
+ * Expands shortcuts according to the following table:
5
+ *
6
+ * | Syntax | Expands to |
7
+ * | --------------- | --------------------- |
8
+ * | `npm:<script>` | `npm run <script>` |
9
+ * | `pnpm:<script>` | `pnpm run <script>` |
10
+ * | `yarn:<script>` | `yarn run <script>` |
11
+ * | `bun:<script>` | `bun run <script>` |
12
+ * | `node:<script>` | `node --run <script>` |
13
+ * | `deno:<script>` | `deno task <script>` |
14
+ */
15
+ export declare class ExpandShortcut implements CommandParser {
16
+ parse(commandInfo: CommandInfo): CommandInfo;
17
+ }
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ExpandShortcut = void 0;
4
+ /**
5
+ * Expands shortcuts according to the following table:
6
+ *
7
+ * | Syntax | Expands to |
8
+ * | --------------- | --------------------- |
9
+ * | `npm:<script>` | `npm run <script>` |
10
+ * | `pnpm:<script>` | `pnpm run <script>` |
11
+ * | `yarn:<script>` | `yarn run <script>` |
12
+ * | `bun:<script>` | `bun run <script>` |
13
+ * | `node:<script>` | `node --run <script>` |
14
+ * | `deno:<script>` | `deno task <script>` |
15
+ */
16
+ class ExpandShortcut {
17
+ parse(commandInfo) {
18
+ const [, prefix, script, args] = /^(npm|yarn|pnpm|bun|node|deno):(\S+)(.*)/.exec(commandInfo.command) || [];
19
+ if (!script) {
20
+ return commandInfo;
21
+ }
22
+ let command;
23
+ if (prefix === 'node') {
24
+ command = 'node --run';
25
+ }
26
+ else if (prefix === 'deno') {
27
+ command = 'deno task';
28
+ }
29
+ else {
30
+ command = `${prefix} run`;
31
+ }
32
+ return {
33
+ ...commandInfo,
34
+ name: commandInfo.name || script,
35
+ command: `${command} ${script}${args}`,
36
+ };
37
+ }
38
+ }
39
+ exports.ExpandShortcut = ExpandShortcut;
@@ -0,0 +1,18 @@
1
+ import { CommandInfo } from '../command';
2
+ import { CommandParser } from './command-parser';
3
+ /**
4
+ * Finds wildcards in 'npm/yarn/pnpm/bun run', 'node --run' and 'deno task'
5
+ * commands and replaces them with all matching scripts in the `package.json`
6
+ * and `deno.json` files of the current directory.
7
+ */
8
+ export declare class ExpandWildcard implements CommandParser {
9
+ private readonly readDeno;
10
+ private readonly readPackage;
11
+ static readDeno(): any;
12
+ static readPackage(): any;
13
+ private packageScripts?;
14
+ private denoTasks?;
15
+ constructor(readDeno?: typeof ExpandWildcard.readDeno, readPackage?: typeof ExpandWildcard.readPackage);
16
+ private relevantScripts;
17
+ parse(commandInfo: CommandInfo): CommandInfo | CommandInfo[];
18
+ }
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ExpandWildcard = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const lodash_1 = __importDefault(require("lodash"));
9
+ // Matches a negative filter surrounded by '(!' and ')'.
10
+ const OMISSION = /\(!([^)]+)\)/;
11
+ /**
12
+ * Finds wildcards in 'npm/yarn/pnpm/bun run', 'node --run' and 'deno task'
13
+ * commands and replaces them with all matching scripts in the `package.json`
14
+ * and `deno.json` files of the current directory.
15
+ */
16
+ class ExpandWildcard {
17
+ readDeno;
18
+ readPackage;
19
+ static readDeno() {
20
+ try {
21
+ const json = fs_1.default.readFileSync('deno.json', { encoding: 'utf-8' });
22
+ return JSON.parse(json);
23
+ }
24
+ catch (e) {
25
+ return {};
26
+ }
27
+ }
28
+ static readPackage() {
29
+ try {
30
+ const json = fs_1.default.readFileSync('package.json', { encoding: 'utf-8' });
31
+ return JSON.parse(json);
32
+ }
33
+ catch (e) {
34
+ return {};
35
+ }
36
+ }
37
+ packageScripts;
38
+ denoTasks;
39
+ constructor(readDeno = ExpandWildcard.readDeno, readPackage = ExpandWildcard.readPackage) {
40
+ this.readDeno = readDeno;
41
+ this.readPackage = readPackage;
42
+ }
43
+ relevantScripts(command) {
44
+ if (!this.packageScripts) {
45
+ this.packageScripts = Object.keys(this.readPackage().scripts || {});
46
+ }
47
+ if (command === 'deno task') {
48
+ if (!this.denoTasks) {
49
+ // If Deno tries to run a task that doesn't exist,
50
+ // it can fall back to running a script with the same name.
51
+ // Therefore, the actual list of tasks is the union of the tasks and scripts.
52
+ this.denoTasks = [
53
+ ...Object.keys(this.readDeno().tasks || {}),
54
+ ...this.packageScripts,
55
+ ];
56
+ }
57
+ return this.denoTasks;
58
+ }
59
+ return this.packageScripts;
60
+ }
61
+ parse(commandInfo) {
62
+ // We expect one of the following patterns:
63
+ // - <npm|yarn|pnpm|bun> run <script> [args]
64
+ // - node --run <script> [args]
65
+ // - deno task <script> [args]
66
+ const [, command, scriptGlob, args] = /((?:npm|yarn|pnpm|bun) (?:run)|node --run|deno task) (\S+)([^&]*)/.exec(commandInfo.command) || [];
67
+ const wildcardPosition = (scriptGlob || '').indexOf('*');
68
+ // If the regex didn't match an npm script, or it has no wildcard,
69
+ // then we have nothing to do here
70
+ if (wildcardPosition === -1) {
71
+ return commandInfo;
72
+ }
73
+ const [, omission] = OMISSION.exec(scriptGlob) || [];
74
+ const scriptGlobSansOmission = scriptGlob.replace(OMISSION, '');
75
+ const preWildcard = lodash_1.default.escapeRegExp(scriptGlobSansOmission.slice(0, wildcardPosition));
76
+ const postWildcard = lodash_1.default.escapeRegExp(scriptGlobSansOmission.slice(wildcardPosition + 1));
77
+ const wildcardRegex = new RegExp(`^${preWildcard}(.*?)${postWildcard}$`);
78
+ // If 'commandInfo.name' doesn't match 'scriptGlob', this means a custom name
79
+ // has been specified and thus becomes the prefix (as described in the README).
80
+ const prefix = commandInfo.name !== scriptGlob ? commandInfo.name : '';
81
+ return this.relevantScripts(command)
82
+ .map((script) => {
83
+ if (omission && RegExp(omission).test(script)) {
84
+ return;
85
+ }
86
+ const [, match] = wildcardRegex.exec(script) || [];
87
+ if (match !== undefined) {
88
+ return {
89
+ ...commandInfo,
90
+ command: `${command} ${script}${args}`,
91
+ // Will use an empty command name if no prefix has been specified and
92
+ // the wildcard match is empty, e.g. if `npm:watch-*` matches `npm run watch-`.
93
+ name: prefix + match,
94
+ };
95
+ }
96
+ })
97
+ .filter((commandInfo) => !!commandInfo);
98
+ }
99
+ }
100
+ exports.ExpandWildcard = ExpandWildcard;
@@ -10,8 +10,8 @@ const os_1 = require("os");
10
10
  const tree_kill_1 = __importDefault(require("tree-kill"));
11
11
  const command_1 = require("./command");
12
12
  const expand_arguments_1 = require("./command-parser/expand-arguments");
13
- const expand_npm_shortcut_1 = require("./command-parser/expand-npm-shortcut");
14
- const expand_npm_wildcard_1 = require("./command-parser/expand-npm-wildcard");
13
+ const expand_shortcut_1 = require("./command-parser/expand-shortcut");
14
+ const expand_wildcard_1 = require("./command-parser/expand-wildcard");
15
15
  const strip_quotes_1 = require("./command-parser/strip-quotes");
16
16
  const completion_listener_1 = require("./completion-listener");
17
17
  const output_writer_1 = require("./output-writer");
@@ -37,8 +37,8 @@ function concurrently(baseCommands, baseOptions) {
37
37
  const prefixColorSelector = new prefix_color_selector_1.PrefixColorSelector(options.prefixColors || []);
38
38
  const commandParsers = [
39
39
  new strip_quotes_1.StripQuotes(),
40
- new expand_npm_shortcut_1.ExpandNpmShortcut(),
41
- new expand_npm_wildcard_1.ExpandNpmWildcard(),
40
+ new expand_shortcut_1.ExpandShortcut(),
41
+ new expand_wildcard_1.ExpandWildcard(),
42
42
  ];
43
43
  if (options.additionalArguments) {
44
44
  commandParsers.push(new expand_arguments_1.ExpandArguments(options.additionalArguments));
@@ -16,5 +16,6 @@ export declare class KillOnSignal implements FlowController {
16
16
  });
17
17
  handle(commands: Command[]): {
18
18
  commands: Command[];
19
+ onFinish: () => void;
19
20
  };
20
21
  }
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.KillOnSignal = void 0;
4
4
  const operators_1 = require("rxjs/operators");
5
+ const SIGNALS = ['SIGINT', 'SIGTERM', 'SIGHUP'];
5
6
  /**
6
7
  * Watches the main concurrently process for signals and sends the same signal down to each spawned
7
8
  * command.
@@ -15,13 +16,12 @@ class KillOnSignal {
15
16
  }
16
17
  handle(commands) {
17
18
  let caughtSignal;
18
- ['SIGINT', 'SIGTERM', 'SIGHUP'].forEach((signal) => {
19
- this.process.on(signal, () => {
20
- caughtSignal = signal;
21
- this.abortController?.abort();
22
- commands.forEach((command) => command.kill(signal));
23
- });
24
- });
19
+ const signalListener = (signal) => {
20
+ caughtSignal = signal;
21
+ this.abortController?.abort();
22
+ commands.forEach((command) => command.kill(signal));
23
+ };
24
+ SIGNALS.forEach((signal) => this.process.on(signal, signalListener));
25
25
  return {
26
26
  commands: commands.map((command) => {
27
27
  const closeStream = command.close.pipe((0, operators_1.map)((exitInfo) => {
@@ -37,6 +37,10 @@ class KillOnSignal {
37
37
  },
38
38
  });
39
39
  }),
40
+ onFinish: () => {
41
+ // Avoids MaxListenersExceededWarning when running programmatically
42
+ SIGNALS.forEach((signal) => this.process.off(signal, signalListener));
43
+ },
40
44
  };
41
45
  }
42
46
  }
@@ -1,6 +1,6 @@
1
1
  # Command Shortcuts
2
2
 
3
- Package managers that execute scripts from a `package.json` file can be shortened when in concurrently.<br/>
3
+ Package managers that execute scripts from a `package.json` or `deno.json` file can be shortened when in concurrently.<br/>
4
4
  The following are supported:
5
5
 
6
6
  | Syntax | Expands to |
@@ -10,6 +10,7 @@ The following are supported:
10
10
  | `yarn:<script>` | `yarn run <script>` |
11
11
  | `bun:<script>` | `bun run <script>` |
12
12
  | `node:<script>` | `node --run <script>` |
13
+ | `deno:<script>` | `deno task <script>` |
13
14
 
14
15
  > [!NOTE]
15
16
  >
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "concurrently",
3
- "version": "9.0.1",
3
+ "version": "9.1.0",
4
4
  "description": "Run commands concurrently",
5
5
  "packageManager": "pnpm@8.15.9+sha256.daa27a0b541bc635323ff96c2ded995467ff9fe6d69ff67021558aa9ad9dcc36",
6
6
  "main": "index.js",
@@ -1,8 +0,0 @@
1
- import { CommandInfo } from '../command';
2
- import { CommandParser } from './command-parser';
3
- /**
4
- * Expands commands prefixed with `node:`, `npm:`, `yarn:`, `pnpm:`, or `bun:` into the full version `npm run <command>` and so on.
5
- */
6
- export declare class ExpandNpmShortcut implements CommandParser {
7
- parse(commandInfo: CommandInfo): CommandInfo;
8
- }
@@ -1,21 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ExpandNpmShortcut = void 0;
4
- /**
5
- * Expands commands prefixed with `node:`, `npm:`, `yarn:`, `pnpm:`, or `bun:` into the full version `npm run <command>` and so on.
6
- */
7
- class ExpandNpmShortcut {
8
- parse(commandInfo) {
9
- const [, npmCmd, cmdName, args] = commandInfo.command.match(/^(node|npm|yarn|pnpm|bun):(\S+)(.*)/) || [];
10
- if (!cmdName) {
11
- return commandInfo;
12
- }
13
- const runCmd = npmCmd === 'node' ? '--run' : 'run';
14
- return {
15
- ...commandInfo,
16
- name: commandInfo.name || cmdName,
17
- command: `${npmCmd} ${runCmd} ${cmdName}${args}`,
18
- };
19
- }
20
- }
21
- exports.ExpandNpmShortcut = ExpandNpmShortcut;
@@ -1,13 +0,0 @@
1
- import { CommandInfo } from '../command';
2
- import { CommandParser } from './command-parser';
3
- /**
4
- * Finds wildcards in npm/yarn/pnpm/bun run commands and replaces them with all matching scripts in the
5
- * `package.json` file of the current directory.
6
- */
7
- export declare class ExpandNpmWildcard implements CommandParser {
8
- private readonly readPackage;
9
- static readPackage(): any;
10
- private scripts?;
11
- constructor(readPackage?: typeof ExpandNpmWildcard.readPackage);
12
- parse(commandInfo: CommandInfo): CommandInfo | CommandInfo[];
13
- }
@@ -1,70 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.ExpandNpmWildcard = void 0;
7
- const fs_1 = __importDefault(require("fs"));
8
- const lodash_1 = __importDefault(require("lodash"));
9
- const OMISSION = /\(!([^)]+)\)/;
10
- /**
11
- * Finds wildcards in npm/yarn/pnpm/bun run commands and replaces them with all matching scripts in the
12
- * `package.json` file of the current directory.
13
- */
14
- class ExpandNpmWildcard {
15
- readPackage;
16
- static readPackage() {
17
- try {
18
- const json = fs_1.default.readFileSync('package.json', { encoding: 'utf-8' });
19
- return JSON.parse(json);
20
- }
21
- catch (e) {
22
- return {};
23
- }
24
- }
25
- scripts;
26
- constructor(readPackage = ExpandNpmWildcard.readPackage) {
27
- this.readPackage = readPackage;
28
- }
29
- parse(commandInfo) {
30
- const [, npmCmd, runCmd, cmdName, args] = commandInfo.command.match(/(node|npm|yarn|pnpm|bun) ((?:--)?run) (\S+)([^&]*)/) || [];
31
- const wildcardPosition = (cmdName || '').indexOf('*');
32
- // If the regex didn't match an npm script, or it has no wildcard,
33
- // then we have nothing to do here
34
- if (!cmdName || wildcardPosition === -1) {
35
- return commandInfo;
36
- }
37
- if (!this.scripts) {
38
- this.scripts = Object.keys(this.readPackage().scripts || {});
39
- }
40
- const omissionRegex = cmdName.match(OMISSION);
41
- const cmdNameSansOmission = cmdName.replace(OMISSION, '');
42
- const preWildcard = lodash_1.default.escapeRegExp(cmdNameSansOmission.slice(0, wildcardPosition));
43
- const postWildcard = lodash_1.default.escapeRegExp(cmdNameSansOmission.slice(wildcardPosition + 1));
44
- const wildcardRegex = new RegExp(`^${preWildcard}(.*?)${postWildcard}$`);
45
- // If 'commandInfo.name' doesn't match 'cmdName', this means a custom name
46
- // has been specified and thus becomes the prefix (as described in the README).
47
- const prefix = commandInfo.name !== cmdName ? commandInfo.name : '';
48
- return this.scripts
49
- .map((script) => {
50
- const match = script.match(wildcardRegex);
51
- if (omissionRegex) {
52
- const toOmit = script.match(new RegExp(omissionRegex[1]));
53
- if (toOmit) {
54
- return;
55
- }
56
- }
57
- if (match) {
58
- return {
59
- ...commandInfo,
60
- command: `${npmCmd} ${runCmd} ${script}${args}`,
61
- // Will use an empty command name if no prefix has been specified and
62
- // the wildcard match is empty, e.g. if `npm:watch-*` matches `npm run watch-`.
63
- name: prefix + match[1],
64
- };
65
- }
66
- })
67
- .filter((commandInfo) => !!commandInfo);
68
- }
69
- }
70
- exports.ExpandNpmWildcard = ExpandNpmWildcard;