• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

open-cli-tools / concurrently / 7478293316

10 Jan 2024 05:02PM UTC coverage: 99.316% (+0.002%) from 99.314%
7478293316

Pull #461

github

web-flow
Merge b263492af into a2e5b1932
Pull Request #461: Don't override errored state on close event

332 of 337 branches covered (0.0%)

Branch coverage included in aggregate %.

539 of 540 relevant lines covered (99.81%)

297.82 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.77
/src/command-parser/expand-npm-wildcard.ts
1
import fs from 'fs';
18✔
2
import _ from 'lodash';
18✔
3

4
import { CommandInfo } from '../command';
5
import { CommandParser } from './command-parser';
6

7
const OMISSION = /\(!([^)]+)\)/;
18✔
8

9
/**
10
 * Finds wildcards in npm/yarn/pnpm/bun run commands and replaces them with all matching scripts in the
11
 * `package.json` file of the current directory.
12
 */
13
export class ExpandNpmWildcard implements CommandParser {
396✔
14
    static readPackage() {
15
        try {
27✔
16
            const json = fs.readFileSync('package.json', { encoding: 'utf-8' });
27✔
17
            return JSON.parse(json);
9✔
18
        } catch (e) {
19
            return {};
18✔
20
        }
21
    }
22

23
    private scripts?: string[];
123✔
24

25
    constructor(private readonly readPackage = ExpandNpmWildcard.readPackage) {}
369✔
26

27
    parse(commandInfo: CommandInfo) {
28
        const [, npmCmd, cmdName, args] =
29
            commandInfo.command.match(/(npm|yarn|pnpm|bun) run (\S+)([^&]*)/) || [];
603✔
30
        const wildcardPosition = (cmdName || '').indexOf('*');
603✔
31

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) {
603✔
35
            return commandInfo;
378✔
36
        }
37

38
        if (!this.scripts) {
225✔
39
            this.scripts = Object.keys(this.readPackage().scripts || {});
189✔
40
        }
41

42
        const omissionRegex = cmdName.match(OMISSION);
225✔
43
        const cmdNameSansOmission = cmdName.replace(OMISSION, '');
225✔
44
        const preWildcard = _.escapeRegExp(cmdNameSansOmission.slice(0, wildcardPosition));
225✔
45
        const postWildcard = _.escapeRegExp(cmdNameSansOmission.slice(wildcardPosition + 1));
225✔
46
        const wildcardRegex = new RegExp(`^${preWildcard}(.*?)${postWildcard}$`);
225✔
47
        // If 'commandInfo.name' doesn't match 'cmdName', this means a custom name
48
        // has been specified and thus becomes the prefix (as described in the README).
49
        const prefix = commandInfo.name !== cmdName ? commandInfo.name : '';
225!
50

51
        return this.scripts
225✔
52
            .map((script) => {
53
                const match = script.match(wildcardRegex);
360✔
54

55
                if (omissionRegex) {
360✔
56
                    const toOmit = script.match(new RegExp(omissionRegex[1]));
144✔
57

58
                    if (toOmit) {
144✔
59
                        return;
72✔
60
                    }
61
                }
62

63
                if (match) {
288✔
64
                    return {
288✔
65
                        ...commandInfo,
66
                        command: `${npmCmd} run ${script}${args}`,
67
                        // Will use an empty command name if no prefix has been specified and
68
                        // the wildcard match is empty, e.g. if `npm:watch-*` matches `npm run watch-`.
69
                        name: prefix + match[1],
70
                    };
71
                }
72
            })
73
            .filter((commandInfo): commandInfo is CommandInfo => !!commandInfo);
360✔
74
    }
75
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc