concurrently 9.0.1 → 9.1.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.
@@ -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 NodeJS and Deno
6
+ * configuration 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,107 @@
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
+ const jsonc_1 = __importDefault(require("../jsonc"));
10
+ // Matches a negative filter surrounded by '(!' and ')'.
11
+ const OMISSION = /\(!([^)]+)\)/;
12
+ /**
13
+ * Finds wildcards in 'npm/yarn/pnpm/bun run', 'node --run' and 'deno task'
14
+ * commands and replaces them with all matching scripts in the NodeJS and Deno
15
+ * configuration files of the current directory.
16
+ */
17
+ class ExpandWildcard {
18
+ readDeno;
19
+ readPackage;
20
+ static readDeno() {
21
+ try {
22
+ let json = '{}';
23
+ if (fs_1.default.existsSync('deno.json')) {
24
+ json = fs_1.default.readFileSync('deno.json', { encoding: 'utf-8' });
25
+ }
26
+ else if (fs_1.default.existsSync('deno.jsonc')) {
27
+ json = fs_1.default.readFileSync('deno.jsonc', { encoding: 'utf-8' });
28
+ }
29
+ return jsonc_1.default.parse(json);
30
+ }
31
+ catch (e) {
32
+ return {};
33
+ }
34
+ }
35
+ static readPackage() {
36
+ try {
37
+ const json = fs_1.default.readFileSync('package.json', { encoding: 'utf-8' });
38
+ return JSON.parse(json);
39
+ }
40
+ catch (e) {
41
+ return {};
42
+ }
43
+ }
44
+ packageScripts;
45
+ denoTasks;
46
+ constructor(readDeno = ExpandWildcard.readDeno, readPackage = ExpandWildcard.readPackage) {
47
+ this.readDeno = readDeno;
48
+ this.readPackage = readPackage;
49
+ }
50
+ relevantScripts(command) {
51
+ if (!this.packageScripts) {
52
+ this.packageScripts = Object.keys(this.readPackage().scripts || {});
53
+ }
54
+ if (command === 'deno task') {
55
+ if (!this.denoTasks) {
56
+ // If Deno tries to run a task that doesn't exist,
57
+ // it can fall back to running a script with the same name.
58
+ // Therefore, the actual list of tasks is the union of the tasks and scripts.
59
+ this.denoTasks = [
60
+ ...Object.keys(this.readDeno().tasks || {}),
61
+ ...this.packageScripts,
62
+ ];
63
+ }
64
+ return this.denoTasks;
65
+ }
66
+ return this.packageScripts;
67
+ }
68
+ parse(commandInfo) {
69
+ // We expect one of the following patterns:
70
+ // - <npm|yarn|pnpm|bun> run <script> [args]
71
+ // - node --run <script> [args]
72
+ // - deno task <script> [args]
73
+ const [, command, scriptGlob, args] = /((?:npm|yarn|pnpm|bun) (?:run)|node --run|deno task) (\S+)([^&]*)/.exec(commandInfo.command) || [];
74
+ const wildcardPosition = (scriptGlob || '').indexOf('*');
75
+ // If the regex didn't match an npm script, or it has no wildcard,
76
+ // then we have nothing to do here
77
+ if (wildcardPosition === -1) {
78
+ return commandInfo;
79
+ }
80
+ const [, omission] = OMISSION.exec(scriptGlob) || [];
81
+ const scriptGlobSansOmission = scriptGlob.replace(OMISSION, '');
82
+ const preWildcard = lodash_1.default.escapeRegExp(scriptGlobSansOmission.slice(0, wildcardPosition));
83
+ const postWildcard = lodash_1.default.escapeRegExp(scriptGlobSansOmission.slice(wildcardPosition + 1));
84
+ const wildcardRegex = new RegExp(`^${preWildcard}(.*?)${postWildcard}$`);
85
+ // If 'commandInfo.name' doesn't match 'scriptGlob', this means a custom name
86
+ // has been specified and thus becomes the prefix (as described in the README).
87
+ const prefix = commandInfo.name !== scriptGlob ? commandInfo.name : '';
88
+ return this.relevantScripts(command)
89
+ .map((script) => {
90
+ if (omission && RegExp(omission).test(script)) {
91
+ return;
92
+ }
93
+ const [, match] = wildcardRegex.exec(script) || [];
94
+ if (match !== undefined) {
95
+ return {
96
+ ...commandInfo,
97
+ command: `${command} ${script}${args}`,
98
+ // Will use an empty command name if no prefix has been specified and
99
+ // the wildcard match is empty, e.g. if `npm:watch-*` matches `npm run watch-`.
100
+ name: prefix + match,
101
+ };
102
+ }
103
+ })
104
+ .filter((commandInfo) => !!commandInfo);
105
+ }
106
+ }
107
+ 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
  }
@@ -0,0 +1,8 @@
1
+ declare const JSONC: {
2
+ parse: (text: string) => any;
3
+ stringify: {
4
+ (value: any, replacer?: ((this: any, key: string, value: any) => any) | undefined, space?: string | number | undefined): string;
5
+ (value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined): string;
6
+ };
7
+ };
8
+ export default JSONC;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ /*
3
+ ORIGINAL https://www.npmjs.com/package/tiny-jsonc
4
+ BY Fabio Spampinato
5
+ MIT license
6
+
7
+ Copied due to the dependency not being compatible with CommonJS
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ /* HELPERS */
11
+ const stringOrCommentRe = /("(?:\\?[^])*?")|(\/\/.*)|(\/\*[^]*?\*\/)/g;
12
+ const stringOrTrailingCommaRe = /("(?:\\?[^])*?")|(,\s*)(?=]|})/g;
13
+ /* MAIN */
14
+ const JSONC = {
15
+ parse: (text) => {
16
+ text = String(text); // To be extra safe
17
+ try {
18
+ // Fast path for valid JSON
19
+ return JSON.parse(text);
20
+ }
21
+ catch {
22
+ // Slow path for JSONC and invalid inputs
23
+ return JSON.parse(text.replace(stringOrCommentRe, '$1').replace(stringOrTrailingCommaRe, '$1'));
24
+ }
25
+ },
26
+ stringify: JSON.stringify,
27
+ };
28
+ /* EXPORT */
29
+ exports.default = JSONC;
@@ -17,9 +17,9 @@ For example, imagine you have in your `package.json` file scripts like this:
17
17
  ```
18
18
 
19
19
  If you wanted to run only either `build:server` or `build:client` with an additional `--noEmit` flag,
20
- you can do so with `npm run build:server -- --watch`, for example.<br/>
21
- However, if you want to do that while using concurrently, as `npm run dev -- --noEmit` for example,
22
- you might find that concurrently actually parses `--watch` as its own flag, which does nothing,
20
+ you can do so with `npm run build:server -- --noEmit`, for example.<br/>
21
+ However, if you want to do that while using concurrently, as `npm run build -- --noEmit` for example,
22
+ you might find that concurrently actually parses `--noEmit` as its own flag, which does nothing,
23
23
  because it doesn't exist.
24
24
 
25
25
  To solve this, you can set the `--passthrough-arguments`/`-P` flag, which instructs concurrently to
@@ -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|jsonc)` 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.1",
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;