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

andrzej-woof / stuntman / 8908908344

01 May 2024 11:45AM UTC coverage: 81.27%. Remained the same
8908908344

push

github

andrzej-woof
fix module resolution

611 of 668 branches covered (91.47%)

Branch coverage included in aggregate %.

2218 of 2813 relevant lines covered (78.85%)

13.32 hits per line

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

85.95
/packages/server/src/ipUtils.ts
1
import { networkInterfaces } from 'os';
1✔
2
import dns, { Resolver as DNSResolver } from 'node:dns';
1✔
3
import { getDnsResolutionCache } from './storage';
1✔
4
import { errorToLog, logger } from '@stuntman/shared';
1✔
5

1✔
6
const localhostIPs: string[] = ['127.0.0.1', '::1'];
1✔
7
const IP_WITH_OPTIONAL_PORT_REGEX = /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}(:[0-9]+)?$/i;
1✔
8

1✔
9
for (const nets of Object.values(networkInterfaces())) {
1✔
10
    if (!nets) {
4!
11
        continue;
×
12
    }
×
13
    for (const net of nets) {
4✔
14
        const familyV4Value = typeof net.family === 'string' ? 'IPv4' : 4;
8!
15
        if (net.family === familyV4Value && !localhostIPs.includes(net.address)) {
8✔
16
            localhostIPs.push(net.address);
2✔
17
        }
2✔
18
    }
8✔
19
}
4✔
20

1✔
21
export class IPUtils {
1✔
22
    protected dnsResolutionCache;
20✔
23
    protected mockUuid: string;
20✔
24
    externalDns: dns.Resolver | null = null;
20✔
25

20✔
26
    constructor(options: { mockUuid: string; externalDns?: string[] }) {
20✔
27
        this.mockUuid = options.mockUuid;
20✔
28
        if (options.externalDns?.length) {
20✔
29
            this.externalDns = new DNSResolver();
16✔
30
            this.externalDns.setServers(options.externalDns);
16✔
31
        }
16✔
32
        this.dnsResolutionCache = getDnsResolutionCache(this.mockUuid);
20✔
33
    }
20✔
34

20✔
35
    isLocalhostIP(ip: string): boolean {
20✔
36
        return localhostIPs.includes(ip);
3✔
37
    }
3✔
38

20✔
39
    private async resolveIPs(hostname: string, options?: { useExternalDns?: true }): Promise<string[]> {
20✔
40
        return new Promise<string[]>((resolve, reject) => {
8✔
41
            const callback = (error: NodeJS.ErrnoException | null, addresses: string | string[]) => {
8✔
42
                if (error) {
6✔
43
                    logger.debug({ error: errorToLog(error), hostname }, 'error resolving hostname');
3✔
44
                    reject(error);
3✔
45
                    return;
3✔
46
                }
3✔
47
                if (typeof addresses === 'string') {
6!
48
                    logger.debug({ ip: [addresses], hostname }, 'resolved hostname');
×
49
                    resolve([addresses]);
×
50
                    return;
×
51
                }
×
52
                if (!addresses || addresses.length === 0) {
6!
53
                    logger.debug({ hostname }, 'no addresses found');
×
54
                    resolve([]);
×
55
                    return;
×
56
                }
×
57
                logger.debug({ ip: addresses, hostname }, 'resolved hostname');
3✔
58
                resolve(addresses);
3✔
59
            };
8✔
60
            if (options?.useExternalDns) {
8✔
61
                if (!this.externalDns) {
4✔
62
                    reject(new Error('external dns servers not set'));
1✔
63
                    return;
1✔
64
                }
1✔
65
                this.externalDns.resolve(hostname, callback);
3✔
66
                return;
3✔
67
            }
3✔
68
            // TODO general handling of IPv6
4✔
69
            dns.resolve4(hostname, callback);
4✔
70
        });
8✔
71
    }
8✔
72

20✔
73
    async resolveIP(hostname: string, options?: { useExternalDns?: true }): Promise<string> {
20✔
74
        const cachedIP = this.dnsResolutionCache.get(hostname);
9✔
75
        if (cachedIP) {
9✔
76
            return cachedIP;
1✔
77
        }
1✔
78
        const resolved = await this.resolveIPs(hostname, options);
8✔
79
        if (!resolved || resolved.length < 1) {
9!
80
            throw new Error('unable to resolve IP');
×
81
        }
×
82
        const ip = resolved[0]!;
3✔
83
        this.dnsResolutionCache.set(hostname, ip);
3✔
84
        return ip;
3✔
85
    }
3✔
86

20✔
87
    isIP(hostname: string): boolean {
20✔
88
        return IP_WITH_OPTIONAL_PORT_REGEX.test(hostname);
5✔
89
    }
5✔
90
}
20✔
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