@push.rocks/smartnetwork 4.1.1 → 4.2.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/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/index.d.ts +1 -0
- package/dist_ts/index.js +2 -1
- package/dist_ts/smartnetwork.classes.publicip.d.ts +39 -0
- package/dist_ts/smartnetwork.classes.publicip.js +136 -0
- package/dist_ts/smartnetwork.classes.smartnetwork.js +6 -5
- package/dist_ts/smartnetwork.plugins.d.ts +1 -2
- package/dist_ts/smartnetwork.plugins.js +2 -4
- package/package.json +8 -9
- package/readme.md +165 -95
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/index.ts +1 -0
- package/ts/smartnetwork.classes.publicip.ts +163 -0
- package/ts/smartnetwork.classes.smartnetwork.ts +5 -4
- package/ts/smartnetwork.plugins.ts +1 -3
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@push.rocks/smartnetwork',
|
|
6
|
-
version: '4.0
|
|
6
|
+
version: '4.2.0',
|
|
7
7
|
description: 'A toolkit for network diagnostics including speed tests, port availability checks, and more.'
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSwwQkFBMEI7SUFDaEMsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLDhGQUE4RjtDQUM1RyxDQUFBIn0=
|
package/dist_ts/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from './smartnetwork.classes.smartnetwork.js';
|
|
2
2
|
export type { SmartNetworkOptions, Hop } from './smartnetwork.classes.smartnetwork.js';
|
|
3
|
+
export { PublicIp } from './smartnetwork.classes.publicip.js';
|
|
3
4
|
export { setLogger, getLogger } from './logging.js';
|
|
4
5
|
export { NetworkError, TimeoutError } from './errors.js';
|
package/dist_ts/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from './smartnetwork.classes.smartnetwork.js';
|
|
2
|
+
export { PublicIp } from './smartnetwork.classes.publicip.js';
|
|
2
3
|
export { setLogger, getLogger } from './logging.js';
|
|
3
4
|
export { NetworkError, TimeoutError } from './errors.js';
|
|
4
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
5
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLHdDQUF3QyxDQUFDO0FBRXZELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQztBQUM5RCxPQUFPLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUNwRCxPQUFPLEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxNQUFNLGFBQWEsQ0FBQyJ9
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PublicIp class for detecting public IPv4 and IPv6 addresses
|
|
3
|
+
* Uses multiple fallback services for reliability
|
|
4
|
+
*/
|
|
5
|
+
export declare class PublicIp {
|
|
6
|
+
private readonly services;
|
|
7
|
+
private readonly timeout;
|
|
8
|
+
private readonly logger;
|
|
9
|
+
constructor(options?: {
|
|
10
|
+
timeout?: number;
|
|
11
|
+
});
|
|
12
|
+
/**
|
|
13
|
+
* Get public IPv4 address
|
|
14
|
+
*/
|
|
15
|
+
getPublicIpv4(): Promise<string | null>;
|
|
16
|
+
/**
|
|
17
|
+
* Get public IPv6 address
|
|
18
|
+
*/
|
|
19
|
+
getPublicIpv6(): Promise<string | null>;
|
|
20
|
+
/**
|
|
21
|
+
* Get both IPv4 and IPv6 addresses
|
|
22
|
+
*/
|
|
23
|
+
getPublicIps(): Promise<{
|
|
24
|
+
v4: string | null;
|
|
25
|
+
v6: string | null;
|
|
26
|
+
}>;
|
|
27
|
+
/**
|
|
28
|
+
* Fetch IP from a service URL
|
|
29
|
+
*/
|
|
30
|
+
private fetchIpFromService;
|
|
31
|
+
/**
|
|
32
|
+
* Validate IPv4 address format
|
|
33
|
+
*/
|
|
34
|
+
private isValidIpv4;
|
|
35
|
+
/**
|
|
36
|
+
* Validate IPv6 address format
|
|
37
|
+
*/
|
|
38
|
+
private isValidIpv6;
|
|
39
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { getLogger } from './logging.js';
|
|
2
|
+
/**
|
|
3
|
+
* PublicIp class for detecting public IPv4 and IPv6 addresses
|
|
4
|
+
* Uses multiple fallback services for reliability
|
|
5
|
+
*/
|
|
6
|
+
export class PublicIp {
|
|
7
|
+
constructor(options) {
|
|
8
|
+
this.services = [
|
|
9
|
+
{
|
|
10
|
+
name: 'ipify',
|
|
11
|
+
v4Url: 'https://api.ipify.org?format=text',
|
|
12
|
+
v6Url: 'https://api6.ipify.org?format=text',
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
name: 'ident.me',
|
|
16
|
+
v4Url: 'https://v4.ident.me',
|
|
17
|
+
v6Url: 'https://v6.ident.me',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: 'seeip',
|
|
21
|
+
v4Url: 'https://ipv4.seeip.org',
|
|
22
|
+
v6Url: 'https://ipv6.seeip.org',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
name: 'icanhazip',
|
|
26
|
+
v4Url: 'https://ipv4.icanhazip.com',
|
|
27
|
+
v6Url: 'https://ipv6.icanhazip.com',
|
|
28
|
+
},
|
|
29
|
+
];
|
|
30
|
+
this.logger = getLogger();
|
|
31
|
+
this.timeout = options?.timeout ?? 2000;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Get public IPv4 address
|
|
35
|
+
*/
|
|
36
|
+
async getPublicIpv4() {
|
|
37
|
+
for (const service of this.services) {
|
|
38
|
+
if (!service.v4Url)
|
|
39
|
+
continue;
|
|
40
|
+
try {
|
|
41
|
+
const ip = await this.fetchIpFromService(service.v4Url, service.parseResponse);
|
|
42
|
+
if (this.isValidIpv4(ip)) {
|
|
43
|
+
this.logger.info?.(`Got IPv4 from ${service.name}: ${ip}`);
|
|
44
|
+
return ip;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
this.logger.debug?.(`Failed to get IPv4 from ${service.name}: ${error.message}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
this.logger.warn?.('Could not determine public IPv4 address from any service');
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Get public IPv6 address
|
|
56
|
+
*/
|
|
57
|
+
async getPublicIpv6() {
|
|
58
|
+
for (const service of this.services) {
|
|
59
|
+
if (!service.v6Url)
|
|
60
|
+
continue;
|
|
61
|
+
try {
|
|
62
|
+
const ip = await this.fetchIpFromService(service.v6Url, service.parseResponse);
|
|
63
|
+
if (this.isValidIpv6(ip)) {
|
|
64
|
+
this.logger.info?.(`Got IPv6 from ${service.name}: ${ip}`);
|
|
65
|
+
return ip;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
this.logger.debug?.(`Failed to get IPv6 from ${service.name}: ${error.message}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
this.logger.warn?.('Could not determine public IPv6 address from any service');
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Get both IPv4 and IPv6 addresses
|
|
77
|
+
*/
|
|
78
|
+
async getPublicIps() {
|
|
79
|
+
const [v4, v6] = await Promise.all([
|
|
80
|
+
this.getPublicIpv4(),
|
|
81
|
+
this.getPublicIpv6(),
|
|
82
|
+
]);
|
|
83
|
+
return { v4, v6 };
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Fetch IP from a service URL
|
|
87
|
+
*/
|
|
88
|
+
async fetchIpFromService(url, parseResponse) {
|
|
89
|
+
const controller = new AbortController();
|
|
90
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
91
|
+
try {
|
|
92
|
+
const response = await fetch(url, {
|
|
93
|
+
signal: controller.signal,
|
|
94
|
+
headers: {
|
|
95
|
+
'User-Agent': '@push.rocks/smartnetwork',
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
if (!response.ok) {
|
|
99
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
100
|
+
}
|
|
101
|
+
const text = await response.text();
|
|
102
|
+
const ip = parseResponse ? parseResponse(text) : text.trim();
|
|
103
|
+
return ip;
|
|
104
|
+
}
|
|
105
|
+
finally {
|
|
106
|
+
clearTimeout(timeoutId);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Validate IPv4 address format
|
|
111
|
+
*/
|
|
112
|
+
isValidIpv4(ip) {
|
|
113
|
+
if (!ip)
|
|
114
|
+
return false;
|
|
115
|
+
const ipv4Regex = /^(\d{1,3}\.){3}\d{1,3}$/;
|
|
116
|
+
if (!ipv4Regex.test(ip))
|
|
117
|
+
return false;
|
|
118
|
+
const parts = ip.split('.');
|
|
119
|
+
return parts.every(part => {
|
|
120
|
+
const num = parseInt(part, 10);
|
|
121
|
+
return num >= 0 && num <= 255;
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Validate IPv6 address format
|
|
126
|
+
*/
|
|
127
|
+
isValidIpv6(ip) {
|
|
128
|
+
if (!ip)
|
|
129
|
+
return false;
|
|
130
|
+
// Simplified IPv6 validation - checks for colon-separated hex values
|
|
131
|
+
const ipv6Regex = /^([0-9a-fA-F]{0,4}:){2,7}[0-9a-fA-F]{0,4}$/;
|
|
132
|
+
const ipv6CompressedRegex = /^::([0-9a-fA-F]{0,4}:){0,6}[0-9a-fA-F]{0,4}$|^([0-9a-fA-F]{0,4}:){1,7}:$/;
|
|
133
|
+
return ipv6Regex.test(ip) || ipv6CompressedRegex.test(ip);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRuZXR3b3JrLmNsYXNzZXMucHVibGljaXAuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydG5ldHdvcmsuY2xhc3Nlcy5wdWJsaWNpcC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBWXpDOzs7R0FHRztBQUNILE1BQU0sT0FBTyxRQUFRO0lBMkJuQixZQUFZLE9BQThCO1FBMUJ6QixhQUFRLEdBQWdCO1lBQ3ZDO2dCQUNFLElBQUksRUFBRSxPQUFPO2dCQUNiLEtBQUssRUFBRSxtQ0FBbUM7Z0JBQzFDLEtBQUssRUFBRSxvQ0FBb0M7YUFDNUM7WUFDRDtnQkFDRSxJQUFJLEVBQUUsVUFBVTtnQkFDaEIsS0FBSyxFQUFFLHFCQUFxQjtnQkFDNUIsS0FBSyxFQUFFLHFCQUFxQjthQUM3QjtZQUNEO2dCQUNFLElBQUksRUFBRSxPQUFPO2dCQUNiLEtBQUssRUFBRSx3QkFBd0I7Z0JBQy9CLEtBQUssRUFBRSx3QkFBd0I7YUFDaEM7WUFDRDtnQkFDRSxJQUFJLEVBQUUsV0FBVztnQkFDakIsS0FBSyxFQUFFLDRCQUE0QjtnQkFDbkMsS0FBSyxFQUFFLDRCQUE0QjthQUNwQztTQUNGLENBQUM7UUFHZSxXQUFNLEdBQUcsU0FBUyxFQUFFLENBQUM7UUFHcEMsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLEVBQUUsT0FBTyxJQUFJLElBQUksQ0FBQztJQUMxQyxDQUFDO0lBRUQ7O09BRUc7SUFDSSxLQUFLLENBQUMsYUFBYTtRQUN4QixLQUFLLE1BQU0sT0FBTyxJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUNwQyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUs7Z0JBQUUsU0FBUztZQUU3QixJQUFJLENBQUM7Z0JBQ0gsTUFBTSxFQUFFLEdBQUcsTUFBTSxJQUFJLENBQUMsa0JBQWtCLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxPQUFPLENBQUMs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
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as plugins from './smartnetwork.plugins.js';
|
|
2
2
|
import { CloudflareSpeed } from './smartnetwork.classes.cloudflarespeed.js';
|
|
3
|
+
import { PublicIp } from './smartnetwork.classes.publicip.js';
|
|
3
4
|
import { getLogger } from './logging.js';
|
|
4
5
|
import { NetworkError } from './errors.js';
|
|
5
6
|
import * as stats from './helpers/stats.js';
|
|
@@ -220,10 +221,10 @@ export class SmartNetwork {
|
|
|
220
221
|
* Lookup public IPv4 and IPv6
|
|
221
222
|
*/
|
|
222
223
|
async getPublicIps() {
|
|
223
|
-
const fetcher = async () =>
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
}
|
|
224
|
+
const fetcher = async () => {
|
|
225
|
+
const publicIp = new PublicIp({ timeout: 1000 });
|
|
226
|
+
return publicIp.getPublicIps();
|
|
227
|
+
};
|
|
227
228
|
if (this.options.cacheTtl && this.options.cacheTtl > 0) {
|
|
228
229
|
return this.getCached('publicIps', fetcher);
|
|
229
230
|
}
|
|
@@ -337,4 +338,4 @@ export class SmartNetwork {
|
|
|
337
338
|
return value;
|
|
338
339
|
}
|
|
339
340
|
}
|
|
340
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRuZXR3b3JrLmNsYXNzZXMuc21hcnRuZXR3b3JrLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvc21hcnRuZXR3b3JrLmNsYXNzZXMuc21hcnRuZXR3b3JrLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sMkJBQTJCLENBQUM7QUFDckQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDJDQUEyQyxDQUFDO0FBQzVFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDekMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUMzQyxPQUFPLEtBQUssS0FBSyxNQUFNLG9CQUFvQixDQUFDO0FBcUI1QyxNQUFNLE9BQU8sWUFBWTtJQUN2QiwyQ0FBMkM7YUFDN0Isb0JBQWUsR0FBcUIsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUM1RCxnQ0FBZ0M7SUFDekIsTUFBTSxDQUFDLGNBQWMsQ0FBQyxJQUFZLEVBQUUsSUFBUztRQUNsRCxZQUFZLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDL0MsQ0FBQztJQUNELGtDQUFrQztJQUMzQixNQUFNLENBQUMsZ0JBQWdCLENBQUMsSUFBWTtRQUN6QyxZQUFZLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUM1QyxDQUFDO0lBR0QsWUFBWSxPQUE2QjtRQUN2QyxJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sSUFBSSxFQUFFLENBQUM7UUFDN0IsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLEdBQUcsRUFBRSxDQUFDO0lBQ3pCLENBQUM7SUFDRDs7O09BR0c7SUFDSSxLQUFLLENBQUMsUUFBUSxDQUFDLElBQXNEO1FBQzFFLE1BQU0sdUJBQXVCLEdBQUcsSUFBSSxlQUFlLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDMUQsT0FBTyx1QkFBdUIsQ0FBQyxT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
|
|
341
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRuZXR3b3JrLmNsYXNzZXMuc21hcnRuZXR3b3JrLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvc21hcnRuZXR3b3JrLmNsYXNzZXMuc21hcnRuZXR3b3JrLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sMkJBQTJCLENBQUM7QUFDckQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDJDQUEyQyxDQUFDO0FBQzVFLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQztBQUM5RCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ3pDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDM0MsT0FBTyxLQUFLLEtBQUssTUFBTSxvQkFBb0IsQ0FBQztBQXFCNUMsTUFBTSxPQUFPLFlBQVk7SUFDdkIsMkNBQTJDO2FBQzdCLG9CQUFlLEdBQXFCLElBQUksR0FBRyxFQUFFLENBQUM7SUFDNUQsZ0NBQWdDO0lBQ3pCLE1BQU0sQ0FBQyxjQUFjLENBQUMsSUFBWSxFQUFFLElBQVM7UUFDbEQsWUFBWSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQy9DLENBQUM7SUFDRCxrQ0FBa0M7SUFDM0IsTUFBTSxDQUFDLGdCQUFnQixDQUFDLElBQVk7UUFDekMsWUFBWSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDNUMsQ0FBQztJQUdELFlBQVksT0FBNkI7UUFDdkMsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLElBQUksRUFBRSxDQUFDO1FBQzdCLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUN6QixDQUFDO0lBQ0Q7OztPQUdHO0lBQ0ksS0FBSyxDQUFDLFFBQVEsQ0FBQyxJQUFzRDtRQUMxRSxNQUFNLHVCQUF1QixHQUFHLElBQUksZUFBZSxD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
|
|
@@ -7,6 +7,5 @@ import * as smartpromise from '@push.rocks/smartpromise';
|
|
|
7
7
|
import * as smartstring from '@push.rocks/smartstring';
|
|
8
8
|
export { smartpromise, smartping, smartstring };
|
|
9
9
|
import isopen from 'isopen';
|
|
10
|
-
import * as publicIp from 'public-ip';
|
|
11
10
|
import * as systeminformation from 'systeminformation';
|
|
12
|
-
export { isopen,
|
|
11
|
+
export { isopen, systeminformation };
|
|
@@ -11,8 +11,6 @@ export { smartpromise, smartping, smartstring };
|
|
|
11
11
|
// @third party scope
|
|
12
12
|
// @ts-ignore
|
|
13
13
|
import isopen from 'isopen';
|
|
14
|
-
// @ts-ignore
|
|
15
|
-
import * as publicIp from 'public-ip';
|
|
16
14
|
import * as systeminformation from 'systeminformation';
|
|
17
|
-
export { isopen,
|
|
18
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
15
|
+
export { isopen, systeminformation };
|
|
16
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRuZXR3b3JrLnBsdWdpbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydG5ldHdvcmsucGx1Z2lucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxlQUFlO0FBQ2YsT0FBTyxLQUFLLEVBQUUsTUFBTSxJQUFJLENBQUM7QUFDekIsT0FBTyxLQUFLLEtBQUssTUFBTSxPQUFPLENBQUM7QUFDL0IsT0FBTyxLQUFLLFNBQVMsTUFBTSxZQUFZLENBQUM7QUFFeEMsT0FBTyxFQUFFLEVBQUUsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLENBQUM7QUFFaEMsbUJBQW1CO0FBQ25CLE9BQU8sS0FBSyxTQUFTLE1BQU0sdUJBQXVCLENBQUM7QUFDbkQsT0FBTyxLQUFLLFlBQVksTUFBTSwwQkFBMEIsQ0FBQztBQUN6RCxPQUFPLEtBQUssV0FBVyxNQUFNLHlCQUF5QixDQUFDO0FBRXZELE9BQU8sRUFBRSxZQUFZLEVBQUUsU0FBUyxFQUFFLFdBQVcsRUFBRSxDQUFDO0FBRWhELHFCQUFxQjtBQUNyQixhQUFhO0FBQ2IsT0FBTyxNQUFNLE1BQU0sUUFBUSxDQUFDO0FBQzVCLE9BQU8sS0FBSyxpQkFBaUIsTUFBTSxtQkFBbUIsQ0FBQztBQUV2RCxPQUFPLEVBQUUsTUFBTSxFQUFFLGlCQUFpQixFQUFFLENBQUMifQ==
|
package/package.json
CHANGED
|
@@ -1,28 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@push.rocks/smartnetwork",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.2.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "A toolkit for network diagnostics including speed tests, port availability checks, and more.",
|
|
6
|
-
"
|
|
7
|
-
|
|
6
|
+
"exports": {
|
|
7
|
+
".": "./dist_ts/index.js"
|
|
8
|
+
},
|
|
8
9
|
"type": "module",
|
|
9
10
|
"author": "Lossless GmbH",
|
|
10
11
|
"license": "MIT",
|
|
11
12
|
"devDependencies": {
|
|
12
|
-
"@git.zone/tsbuild": "^2.
|
|
13
|
+
"@git.zone/tsbuild": "^2.6.8",
|
|
13
14
|
"@git.zone/tsrun": "^1.2.39",
|
|
14
|
-
"@git.zone/tstest": "^
|
|
15
|
-
"@push.rocks/smartenv": "^5.0.
|
|
15
|
+
"@git.zone/tstest": "^2.3.6",
|
|
16
|
+
"@push.rocks/smartenv": "^5.0.13",
|
|
16
17
|
"@types/node": "^22.15.19"
|
|
17
18
|
},
|
|
18
19
|
"dependencies": {
|
|
19
20
|
"@push.rocks/smartping": "^1.0.7",
|
|
20
21
|
"@push.rocks/smartpromise": "^4.2.3",
|
|
21
22
|
"@push.rocks/smartstring": "^4.0.2",
|
|
22
|
-
"@types/default-gateway": "^7.2.2",
|
|
23
23
|
"isopen": "^1.3.0",
|
|
24
|
-
"
|
|
25
|
-
"systeminformation": "^5.11.9"
|
|
24
|
+
"systeminformation": "^5.27.8"
|
|
26
25
|
},
|
|
27
26
|
"files": [
|
|
28
27
|
"ts/**/*",
|
package/readme.md
CHANGED
|
@@ -1,49 +1,59 @@
|
|
|
1
|
-
# @push.rocks/smartnetwork
|
|
1
|
+
# @push.rocks/smartnetwork 🌐
|
|
2
2
|
|
|
3
3
|
Comprehensive network diagnostics and utilities for Node.js applications
|
|
4
4
|
|
|
5
|
-
## Install
|
|
5
|
+
## 🚀 Install
|
|
6
6
|
|
|
7
7
|
To install `@push.rocks/smartnetwork`, run the following command in your terminal:
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
|
|
10
|
+
pnpm install @push.rocks/smartnetwork --save
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
##
|
|
13
|
+
## 🎯 Overview
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
**@push.rocks/smartnetwork** is your Swiss Army knife for network diagnostics in Node.js. Whether you're building network monitoring tools, implementing health checks, or just need to debug connectivity issues, this library has you covered with a clean, promise-based API.
|
|
16
|
+
|
|
17
|
+
### ✨ Key Features
|
|
18
|
+
|
|
19
|
+
- **🏎️ Speed Testing** - Measure download/upload speeds using Cloudflare's infrastructure
|
|
20
|
+
- **🔌 Port Management** - Check local/remote port availability, find free ports
|
|
21
|
+
- **📡 Connectivity Testing** - Ping hosts, trace routes, check endpoints
|
|
22
|
+
- **🌍 DNS Operations** - Resolve A, AAAA, and MX records
|
|
23
|
+
- **🔍 Network Discovery** - Get network interfaces, gateways, public IPs
|
|
24
|
+
- **⚡ Performance Caching** - Built-in caching for expensive operations
|
|
25
|
+
- **🔧 Plugin Architecture** - Extend functionality with custom plugins
|
|
26
|
+
- **📝 Full TypeScript Support** - Complete type definitions included
|
|
27
|
+
|
|
28
|
+
## 💻 Usage
|
|
16
29
|
|
|
17
30
|
### Basic Setup
|
|
18
31
|
|
|
19
|
-
First, import
|
|
32
|
+
First, import and initialize SmartNetwork:
|
|
20
33
|
|
|
21
34
|
```typescript
|
|
22
35
|
import { SmartNetwork } from '@push.rocks/smartnetwork';
|
|
23
|
-
```
|
|
24
36
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
```typescript
|
|
28
|
-
const myNetwork = new SmartNetwork();
|
|
37
|
+
// Basic instance
|
|
38
|
+
const network = new SmartNetwork();
|
|
29
39
|
|
|
30
|
-
//
|
|
31
|
-
const
|
|
40
|
+
// With caching enabled (60 seconds TTL)
|
|
41
|
+
const cachedNetwork = new SmartNetwork({ cacheTtl: 60000 });
|
|
32
42
|
```
|
|
33
43
|
|
|
34
|
-
### Network Speed Testing
|
|
44
|
+
### 🏎️ Network Speed Testing
|
|
35
45
|
|
|
36
|
-
Measure network
|
|
46
|
+
Measure your network performance using Cloudflare's global infrastructure:
|
|
37
47
|
|
|
38
48
|
```typescript
|
|
39
49
|
const speedTest = async () => {
|
|
40
|
-
//
|
|
41
|
-
const result = await
|
|
50
|
+
// Quick speed test
|
|
51
|
+
const result = await network.getSpeed();
|
|
42
52
|
console.log(`Download: ${result.downloadSpeed} Mbps`);
|
|
43
53
|
console.log(`Upload: ${result.uploadSpeed} Mbps`);
|
|
44
54
|
|
|
45
|
-
// Advanced
|
|
46
|
-
const advancedResult = await
|
|
55
|
+
// Advanced configuration
|
|
56
|
+
const advancedResult = await network.getSpeed({
|
|
47
57
|
parallelStreams: 3, // Number of concurrent connections
|
|
48
58
|
duration: 5 // Test duration in seconds
|
|
49
59
|
});
|
|
@@ -52,19 +62,19 @@ const speedTest = async () => {
|
|
|
52
62
|
};
|
|
53
63
|
```
|
|
54
64
|
|
|
55
|
-
### Port Management
|
|
65
|
+
### 🔌 Port Management
|
|
56
66
|
|
|
57
67
|
#### Check Local Port Availability
|
|
58
68
|
|
|
59
|
-
Verify if a
|
|
69
|
+
Verify if a port is available on your local machine (checks both IPv4 and IPv6):
|
|
60
70
|
|
|
61
71
|
```typescript
|
|
62
72
|
const checkLocalPort = async (port: number) => {
|
|
63
|
-
const isUnused = await
|
|
73
|
+
const isUnused = await network.isLocalPortUnused(port);
|
|
64
74
|
if (isUnused) {
|
|
65
|
-
console.log(
|
|
75
|
+
console.log(`✅ Port ${port} is available`);
|
|
66
76
|
} else {
|
|
67
|
-
console.log(
|
|
77
|
+
console.log(`❌ Port ${port} is in use`);
|
|
68
78
|
}
|
|
69
79
|
};
|
|
70
80
|
|
|
@@ -73,136 +83,139 @@ await checkLocalPort(8080);
|
|
|
73
83
|
|
|
74
84
|
#### Find Free Port in Range
|
|
75
85
|
|
|
76
|
-
Automatically
|
|
86
|
+
Automatically discover available ports:
|
|
77
87
|
|
|
78
88
|
```typescript
|
|
79
89
|
const findFreePort = async () => {
|
|
80
90
|
// Find a free port between 3000 and 3100
|
|
81
|
-
const freePort = await
|
|
91
|
+
const freePort = await network.findFreePort(3000, 3100);
|
|
82
92
|
|
|
83
93
|
if (freePort) {
|
|
84
|
-
console.log(
|
|
94
|
+
console.log(`🎉 Found free port: ${freePort}`);
|
|
85
95
|
} else {
|
|
86
|
-
console.log('No free ports available in
|
|
96
|
+
console.log('😢 No free ports available in range');
|
|
87
97
|
}
|
|
88
98
|
};
|
|
89
99
|
```
|
|
90
100
|
|
|
91
101
|
#### Check Remote Port Availability
|
|
92
102
|
|
|
93
|
-
|
|
103
|
+
Test if services are accessible on remote servers:
|
|
94
104
|
|
|
95
105
|
```typescript
|
|
96
106
|
// Method 1: Using "host:port" syntax
|
|
97
|
-
const isOpen1 = await
|
|
107
|
+
const isOpen1 = await network.isRemotePortAvailable('example.com:443');
|
|
98
108
|
|
|
99
109
|
// Method 2: Using separate host and port
|
|
100
|
-
const isOpen2 = await
|
|
110
|
+
const isOpen2 = await network.isRemotePortAvailable('example.com', 443);
|
|
101
111
|
|
|
102
|
-
// Method 3: With options
|
|
103
|
-
const isOpen3 = await
|
|
112
|
+
// Method 3: With advanced options
|
|
113
|
+
const isOpen3 = await network.isRemotePortAvailable('example.com', {
|
|
104
114
|
port: 443,
|
|
105
115
|
protocol: 'tcp', // Only TCP is supported
|
|
106
116
|
retries: 3, // Number of connection attempts
|
|
107
117
|
timeout: 5000 // Timeout per attempt in ms
|
|
108
118
|
});
|
|
109
119
|
|
|
110
|
-
// Note: UDP is not supported
|
|
120
|
+
// Note: UDP is not supported
|
|
111
121
|
try {
|
|
112
|
-
await
|
|
122
|
+
await network.isRemotePortAvailable('example.com', {
|
|
113
123
|
port: 53,
|
|
114
124
|
protocol: 'udp'
|
|
115
125
|
});
|
|
116
126
|
} catch (e) {
|
|
117
|
-
console.error(e.code); // ENOTSUP
|
|
127
|
+
console.error('UDP not supported:', e.code); // ENOTSUP
|
|
118
128
|
}
|
|
119
129
|
```
|
|
120
130
|
|
|
121
|
-
### Network Connectivity
|
|
131
|
+
### 📡 Network Connectivity
|
|
122
132
|
|
|
123
133
|
#### Ping Operations
|
|
124
134
|
|
|
125
|
-
|
|
135
|
+
Test connectivity and measure latency:
|
|
126
136
|
|
|
127
137
|
```typescript
|
|
128
138
|
// Simple ping
|
|
129
|
-
const pingResult = await
|
|
139
|
+
const pingResult = await network.ping('google.com');
|
|
130
140
|
console.log(`Host alive: ${pingResult.alive}`);
|
|
131
141
|
console.log(`RTT: ${pingResult.time} ms`);
|
|
132
142
|
|
|
133
|
-
//
|
|
134
|
-
const pingStats = await
|
|
143
|
+
// Detailed ping statistics
|
|
144
|
+
const pingStats = await network.ping('google.com', {
|
|
135
145
|
count: 5, // Number of pings
|
|
136
146
|
timeout: 1000 // Timeout per ping in ms
|
|
137
147
|
});
|
|
138
148
|
|
|
139
|
-
console.log(
|
|
140
|
-
console.log(`
|
|
141
|
-
console.log(`
|
|
142
|
-
console.log(`
|
|
143
|
-
console.log(`
|
|
149
|
+
console.log(`📊 Ping Statistics:`);
|
|
150
|
+
console.log(` Packet loss: ${pingStats.packetLoss}%`);
|
|
151
|
+
console.log(` Min: ${pingStats.min} ms`);
|
|
152
|
+
console.log(` Max: ${pingStats.max} ms`);
|
|
153
|
+
console.log(` Avg: ${pingStats.avg.toFixed(2)} ms`);
|
|
154
|
+
console.log(` Stddev: ${pingStats.stddev.toFixed(2)} ms`);
|
|
144
155
|
```
|
|
145
156
|
|
|
146
157
|
#### Traceroute
|
|
147
158
|
|
|
148
|
-
|
|
159
|
+
Analyze network paths hop-by-hop:
|
|
149
160
|
|
|
150
161
|
```typescript
|
|
151
|
-
const hops = await
|
|
162
|
+
const hops = await network.traceroute('google.com', {
|
|
152
163
|
maxHops: 10, // Maximum number of hops
|
|
153
164
|
timeout: 5000 // Timeout in ms
|
|
154
165
|
});
|
|
155
166
|
|
|
167
|
+
console.log('🛤️ Route to destination:');
|
|
156
168
|
hops.forEach(hop => {
|
|
157
169
|
const rtt = hop.rtt === null ? '*' : `${hop.rtt} ms`;
|
|
158
|
-
console.log(
|
|
170
|
+
console.log(` ${hop.ttl}\t${hop.ip}\t${rtt}`);
|
|
159
171
|
});
|
|
160
172
|
```
|
|
161
173
|
|
|
162
|
-
Note: Falls back to a single-hop stub if the `traceroute` binary is unavailable
|
|
174
|
+
*Note: Falls back to a single-hop stub if the `traceroute` binary is unavailable.*
|
|
163
175
|
|
|
164
|
-
### DNS Operations
|
|
176
|
+
### 🌍 DNS Operations
|
|
165
177
|
|
|
166
|
-
Resolve DNS
|
|
178
|
+
Resolve various DNS record types:
|
|
167
179
|
|
|
168
180
|
```typescript
|
|
169
|
-
const dnsRecords = await
|
|
181
|
+
const dnsRecords = await network.resolveDns('example.com');
|
|
170
182
|
|
|
171
|
-
console.log('
|
|
172
|
-
console.log('
|
|
173
|
-
console.log('
|
|
183
|
+
console.log('🔍 DNS Records:');
|
|
184
|
+
console.log(' A records:', dnsRecords.A); // IPv4 addresses
|
|
185
|
+
console.log(' AAAA records:', dnsRecords.AAAA); // IPv6 addresses
|
|
174
186
|
|
|
175
187
|
// MX records include priority
|
|
176
188
|
dnsRecords.MX.forEach(mx => {
|
|
177
|
-
console.log(`Mail server: ${mx.exchange} (priority: ${mx.priority})`);
|
|
189
|
+
console.log(` 📧 Mail server: ${mx.exchange} (priority: ${mx.priority})`);
|
|
178
190
|
});
|
|
179
191
|
```
|
|
180
192
|
|
|
181
|
-
### HTTP/HTTPS
|
|
193
|
+
### 🏥 HTTP/HTTPS Health Checks
|
|
182
194
|
|
|
183
|
-
|
|
195
|
+
Monitor endpoint availability and response times:
|
|
184
196
|
|
|
185
197
|
```typescript
|
|
186
|
-
const health = await
|
|
198
|
+
const health = await network.checkEndpoint('https://api.example.com/health', {
|
|
187
199
|
timeout: 5000 // Request timeout in ms
|
|
188
200
|
});
|
|
189
201
|
|
|
190
|
-
console.log(
|
|
191
|
-
console.log(`
|
|
192
|
-
console.log(
|
|
202
|
+
console.log(`🩺 Endpoint Health:`);
|
|
203
|
+
console.log(` Status: ${health.status}`);
|
|
204
|
+
console.log(` RTT: ${health.rtt} ms`);
|
|
205
|
+
console.log(` Headers:`, health.headers);
|
|
193
206
|
```
|
|
194
207
|
|
|
195
|
-
### Network Interface Information
|
|
208
|
+
### 🖥️ Network Interface Information
|
|
196
209
|
|
|
197
|
-
#### Get Network
|
|
210
|
+
#### Get All Network Interfaces
|
|
198
211
|
|
|
199
|
-
List all network
|
|
212
|
+
List all network adapters on the system:
|
|
200
213
|
|
|
201
214
|
```typescript
|
|
202
|
-
const gateways = await
|
|
215
|
+
const gateways = await network.getGateways();
|
|
203
216
|
|
|
204
217
|
Object.entries(gateways).forEach(([name, interfaces]) => {
|
|
205
|
-
console.log(
|
|
218
|
+
console.log(`🔌 Interface: ${name}`);
|
|
206
219
|
interfaces.forEach(iface => {
|
|
207
220
|
console.log(` ${iface.family}: ${iface.address}`);
|
|
208
221
|
console.log(` Netmask: ${iface.netmask}`);
|
|
@@ -213,48 +226,50 @@ Object.entries(gateways).forEach(([name, interfaces]) => {
|
|
|
213
226
|
|
|
214
227
|
#### Get Default Gateway
|
|
215
228
|
|
|
216
|
-
Retrieve the
|
|
229
|
+
Retrieve the primary network interface:
|
|
217
230
|
|
|
218
231
|
```typescript
|
|
219
|
-
const defaultGateway = await
|
|
232
|
+
const defaultGateway = await network.getDefaultGateway();
|
|
220
233
|
|
|
221
234
|
if (defaultGateway) {
|
|
222
|
-
console.log('
|
|
223
|
-
console.log('
|
|
235
|
+
console.log('🌐 Default Gateway:');
|
|
236
|
+
console.log(' IPv4:', defaultGateway.ipv4.address);
|
|
237
|
+
console.log(' IPv6:', defaultGateway.ipv6.address);
|
|
224
238
|
}
|
|
225
239
|
```
|
|
226
240
|
|
|
227
|
-
### Public IP Discovery
|
|
241
|
+
### 🌎 Public IP Discovery
|
|
228
242
|
|
|
229
|
-
Discover your public
|
|
243
|
+
Discover your public-facing IP addresses:
|
|
230
244
|
|
|
231
245
|
```typescript
|
|
232
|
-
const publicIps = await
|
|
246
|
+
const publicIps = await network.getPublicIps();
|
|
233
247
|
|
|
234
|
-
console.log(
|
|
235
|
-
console.log(`
|
|
248
|
+
console.log(`🌍 Public IPs:`);
|
|
249
|
+
console.log(` IPv4: ${publicIps.v4 || 'Not available'}`);
|
|
250
|
+
console.log(` IPv6: ${publicIps.v6 || 'Not available'}`);
|
|
236
251
|
```
|
|
237
252
|
|
|
238
|
-
### Caching
|
|
253
|
+
### ⚡ Performance Caching
|
|
239
254
|
|
|
240
|
-
|
|
255
|
+
Reduce network calls with built-in caching:
|
|
241
256
|
|
|
242
257
|
```typescript
|
|
243
258
|
// Create instance with 60-second cache TTL
|
|
244
259
|
const cachedNetwork = new SmartNetwork({ cacheTtl: 60000 });
|
|
245
260
|
|
|
246
|
-
//
|
|
261
|
+
// First call fetches from network
|
|
247
262
|
const gateways1 = await cachedNetwork.getGateways();
|
|
248
263
|
const publicIps1 = await cachedNetwork.getPublicIps();
|
|
249
264
|
|
|
250
|
-
// Subsequent calls within
|
|
251
|
-
const gateways2 = await cachedNetwork.getGateways(); // From cache
|
|
252
|
-
const publicIps2 = await cachedNetwork.getPublicIps(); // From cache
|
|
265
|
+
// Subsequent calls within 60 seconds use cache
|
|
266
|
+
const gateways2 = await cachedNetwork.getGateways(); // From cache ⚡
|
|
267
|
+
const publicIps2 = await cachedNetwork.getPublicIps(); // From cache ⚡
|
|
253
268
|
```
|
|
254
269
|
|
|
255
|
-
### Plugin Architecture
|
|
270
|
+
### 🔧 Plugin Architecture
|
|
256
271
|
|
|
257
|
-
Extend SmartNetwork
|
|
272
|
+
Extend SmartNetwork with custom functionality:
|
|
258
273
|
|
|
259
274
|
```typescript
|
|
260
275
|
// Define your plugin
|
|
@@ -262,7 +277,8 @@ class CustomNetworkPlugin {
|
|
|
262
277
|
constructor(private smartNetwork: SmartNetwork) {}
|
|
263
278
|
|
|
264
279
|
async customMethod() {
|
|
265
|
-
// Your custom network
|
|
280
|
+
// Your custom network logic here
|
|
281
|
+
return 'Custom result';
|
|
266
282
|
}
|
|
267
283
|
}
|
|
268
284
|
|
|
@@ -271,33 +287,34 @@ SmartNetwork.registerPlugin('customPlugin', CustomNetworkPlugin);
|
|
|
271
287
|
|
|
272
288
|
// Use the plugin
|
|
273
289
|
const network = new SmartNetwork();
|
|
274
|
-
const
|
|
290
|
+
const PluginClass = SmartNetwork.pluginsRegistry.get('customPlugin');
|
|
291
|
+
const plugin = new PluginClass(network);
|
|
275
292
|
await plugin.customMethod();
|
|
276
293
|
|
|
277
|
-
//
|
|
294
|
+
// Clean up when done
|
|
278
295
|
SmartNetwork.unregisterPlugin('customPlugin');
|
|
279
296
|
```
|
|
280
297
|
|
|
281
|
-
### Error Handling
|
|
298
|
+
### 🚨 Error Handling
|
|
282
299
|
|
|
283
|
-
|
|
300
|
+
Handle network errors gracefully with custom error types:
|
|
284
301
|
|
|
285
302
|
```typescript
|
|
286
303
|
import { NetworkError } from '@push.rocks/smartnetwork';
|
|
287
304
|
|
|
288
305
|
try {
|
|
289
|
-
await
|
|
306
|
+
await network.isRemotePortAvailable('example.com', { protocol: 'udp' });
|
|
290
307
|
} catch (error) {
|
|
291
308
|
if (error instanceof NetworkError) {
|
|
292
|
-
console.error(
|
|
293
|
-
console.error(`Error code: ${error.code}`);
|
|
309
|
+
console.error(`❌ Network error: ${error.message}`);
|
|
310
|
+
console.error(` Error code: ${error.code}`);
|
|
294
311
|
}
|
|
295
312
|
}
|
|
296
313
|
```
|
|
297
314
|
|
|
298
|
-
### TypeScript Support
|
|
315
|
+
### 📚 TypeScript Support
|
|
299
316
|
|
|
300
|
-
This package is written in TypeScript and provides
|
|
317
|
+
This package is written in TypeScript and provides comprehensive type definitions:
|
|
301
318
|
|
|
302
319
|
```typescript
|
|
303
320
|
interface SmartNetworkOptions {
|
|
@@ -309,6 +326,59 @@ interface Hop {
|
|
|
309
326
|
ip: string; // IP address of the hop
|
|
310
327
|
rtt: number | null; // Round trip time in ms
|
|
311
328
|
}
|
|
329
|
+
|
|
330
|
+
// ... and many more types for complete type safety
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
## 🛠️ Advanced Examples
|
|
334
|
+
|
|
335
|
+
### Building a Network Monitor
|
|
336
|
+
|
|
337
|
+
```typescript
|
|
338
|
+
const monitorNetwork = async () => {
|
|
339
|
+
const network = new SmartNetwork({ cacheTtl: 30000 });
|
|
340
|
+
|
|
341
|
+
// Check critical services
|
|
342
|
+
const services = [
|
|
343
|
+
{ name: 'Web Server', host: 'example.com', port: 443 },
|
|
344
|
+
{ name: 'Database', host: 'db.internal', port: 5432 },
|
|
345
|
+
{ name: 'Cache', host: 'redis.internal', port: 6379 }
|
|
346
|
+
];
|
|
347
|
+
|
|
348
|
+
for (const service of services) {
|
|
349
|
+
const isUp = await network.isRemotePortAvailable(service.host, service.port);
|
|
350
|
+
console.log(`${service.name}: ${isUp ? '✅ UP' : '❌ DOWN'}`);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// Check internet connectivity
|
|
354
|
+
const ping = await network.ping('8.8.8.8');
|
|
355
|
+
console.log(`Internet: ${ping.alive ? '✅ Connected' : '❌ Disconnected'}`);
|
|
356
|
+
|
|
357
|
+
// Measure network performance
|
|
358
|
+
const speed = await network.getSpeed();
|
|
359
|
+
console.log(`Speed: ⬇️ ${speed.downloadSpeed} Mbps / ⬆️ ${speed.uploadSpeed} Mbps`);
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
// Run monitor every minute
|
|
363
|
+
setInterval(monitorNetwork, 60000);
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### Service Discovery
|
|
367
|
+
|
|
368
|
+
```typescript
|
|
369
|
+
const discoverServices = async () => {
|
|
370
|
+
const network = new SmartNetwork();
|
|
371
|
+
const commonPorts = [22, 80, 443, 3000, 3306, 5432, 6379, 8080, 9200];
|
|
372
|
+
|
|
373
|
+
console.log('🔍 Scanning local services...');
|
|
374
|
+
|
|
375
|
+
for (const port of commonPorts) {
|
|
376
|
+
const isUsed = !(await network.isLocalPortUnused(port));
|
|
377
|
+
if (isUsed) {
|
|
378
|
+
console.log(` Port ${port}: In use (possible service running)`);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
};
|
|
312
382
|
```
|
|
313
383
|
|
|
314
384
|
## License and Legal Information
|
package/ts/00_commitinfo_data.ts
CHANGED
package/ts/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from './smartnetwork.classes.smartnetwork.js';
|
|
2
2
|
export type { SmartNetworkOptions, Hop } from './smartnetwork.classes.smartnetwork.js';
|
|
3
|
+
export { PublicIp } from './smartnetwork.classes.publicip.js';
|
|
3
4
|
export { setLogger, getLogger } from './logging.js';
|
|
4
5
|
export { NetworkError, TimeoutError } from './errors.js';
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { getLogger } from './logging.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Service configuration for IP detection
|
|
5
|
+
*/
|
|
6
|
+
interface IpService {
|
|
7
|
+
name: string;
|
|
8
|
+
v4Url?: string;
|
|
9
|
+
v6Url?: string;
|
|
10
|
+
parseResponse?: (text: string) => string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* PublicIp class for detecting public IPv4 and IPv6 addresses
|
|
15
|
+
* Uses multiple fallback services for reliability
|
|
16
|
+
*/
|
|
17
|
+
export class PublicIp {
|
|
18
|
+
private readonly services: IpService[] = [
|
|
19
|
+
{
|
|
20
|
+
name: 'ipify',
|
|
21
|
+
v4Url: 'https://api.ipify.org?format=text',
|
|
22
|
+
v6Url: 'https://api6.ipify.org?format=text',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
name: 'ident.me',
|
|
26
|
+
v4Url: 'https://v4.ident.me',
|
|
27
|
+
v6Url: 'https://v6.ident.me',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
name: 'seeip',
|
|
31
|
+
v4Url: 'https://ipv4.seeip.org',
|
|
32
|
+
v6Url: 'https://ipv6.seeip.org',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: 'icanhazip',
|
|
36
|
+
v4Url: 'https://ipv4.icanhazip.com',
|
|
37
|
+
v6Url: 'https://ipv6.icanhazip.com',
|
|
38
|
+
},
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
private readonly timeout: number;
|
|
42
|
+
private readonly logger = getLogger();
|
|
43
|
+
|
|
44
|
+
constructor(options?: { timeout?: number }) {
|
|
45
|
+
this.timeout = options?.timeout ?? 2000;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Get public IPv4 address
|
|
50
|
+
*/
|
|
51
|
+
public async getPublicIpv4(): Promise<string | null> {
|
|
52
|
+
for (const service of this.services) {
|
|
53
|
+
if (!service.v4Url) continue;
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
const ip = await this.fetchIpFromService(service.v4Url, service.parseResponse);
|
|
57
|
+
if (this.isValidIpv4(ip)) {
|
|
58
|
+
this.logger.info?.(`Got IPv4 from ${service.name}: ${ip}`);
|
|
59
|
+
return ip;
|
|
60
|
+
}
|
|
61
|
+
} catch (error) {
|
|
62
|
+
this.logger.debug?.(`Failed to get IPv4 from ${service.name}: ${error.message}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
this.logger.warn?.('Could not determine public IPv4 address from any service');
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Get public IPv6 address
|
|
72
|
+
*/
|
|
73
|
+
public async getPublicIpv6(): Promise<string | null> {
|
|
74
|
+
for (const service of this.services) {
|
|
75
|
+
if (!service.v6Url) continue;
|
|
76
|
+
|
|
77
|
+
try {
|
|
78
|
+
const ip = await this.fetchIpFromService(service.v6Url, service.parseResponse);
|
|
79
|
+
if (this.isValidIpv6(ip)) {
|
|
80
|
+
this.logger.info?.(`Got IPv6 from ${service.name}: ${ip}`);
|
|
81
|
+
return ip;
|
|
82
|
+
}
|
|
83
|
+
} catch (error) {
|
|
84
|
+
this.logger.debug?.(`Failed to get IPv6 from ${service.name}: ${error.message}`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
this.logger.warn?.('Could not determine public IPv6 address from any service');
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Get both IPv4 and IPv6 addresses
|
|
94
|
+
*/
|
|
95
|
+
public async getPublicIps(): Promise<{ v4: string | null; v6: string | null }> {
|
|
96
|
+
const [v4, v6] = await Promise.all([
|
|
97
|
+
this.getPublicIpv4(),
|
|
98
|
+
this.getPublicIpv6(),
|
|
99
|
+
]);
|
|
100
|
+
|
|
101
|
+
return { v4, v6 };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Fetch IP from a service URL
|
|
106
|
+
*/
|
|
107
|
+
private async fetchIpFromService(
|
|
108
|
+
url: string,
|
|
109
|
+
parseResponse?: (text: string) => string
|
|
110
|
+
): Promise<string> {
|
|
111
|
+
const controller = new AbortController();
|
|
112
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
const response = await fetch(url, {
|
|
116
|
+
signal: controller.signal,
|
|
117
|
+
headers: {
|
|
118
|
+
'User-Agent': '@push.rocks/smartnetwork',
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
if (!response.ok) {
|
|
123
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const text = await response.text();
|
|
127
|
+
const ip = parseResponse ? parseResponse(text) : text.trim();
|
|
128
|
+
|
|
129
|
+
return ip;
|
|
130
|
+
} finally {
|
|
131
|
+
clearTimeout(timeoutId);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Validate IPv4 address format
|
|
137
|
+
*/
|
|
138
|
+
private isValidIpv4(ip: string): boolean {
|
|
139
|
+
if (!ip) return false;
|
|
140
|
+
|
|
141
|
+
const ipv4Regex = /^(\d{1,3}\.){3}\d{1,3}$/;
|
|
142
|
+
if (!ipv4Regex.test(ip)) return false;
|
|
143
|
+
|
|
144
|
+
const parts = ip.split('.');
|
|
145
|
+
return parts.every(part => {
|
|
146
|
+
const num = parseInt(part, 10);
|
|
147
|
+
return num >= 0 && num <= 255;
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Validate IPv6 address format
|
|
153
|
+
*/
|
|
154
|
+
private isValidIpv6(ip: string): boolean {
|
|
155
|
+
if (!ip) return false;
|
|
156
|
+
|
|
157
|
+
// Simplified IPv6 validation - checks for colon-separated hex values
|
|
158
|
+
const ipv6Regex = /^([0-9a-fA-F]{0,4}:){2,7}[0-9a-fA-F]{0,4}$/;
|
|
159
|
+
const ipv6CompressedRegex = /^::([0-9a-fA-F]{0,4}:){0,6}[0-9a-fA-F]{0,4}$|^([0-9a-fA-F]{0,4}:){1,7}:$/;
|
|
160
|
+
|
|
161
|
+
return ipv6Regex.test(ip) || ipv6CompressedRegex.test(ip);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as plugins from './smartnetwork.plugins.js';
|
|
2
2
|
import { CloudflareSpeed } from './smartnetwork.classes.cloudflarespeed.js';
|
|
3
|
+
import { PublicIp } from './smartnetwork.classes.publicip.js';
|
|
3
4
|
import { getLogger } from './logging.js';
|
|
4
5
|
import { NetworkError } from './errors.js';
|
|
5
6
|
import * as stats from './helpers/stats.js';
|
|
@@ -259,10 +260,10 @@ export class SmartNetwork {
|
|
|
259
260
|
* Lookup public IPv4 and IPv6
|
|
260
261
|
*/
|
|
261
262
|
public async getPublicIps(): Promise<{ v4: string | null; v6: string | null }> {
|
|
262
|
-
const fetcher = async () =>
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
}
|
|
263
|
+
const fetcher = async () => {
|
|
264
|
+
const publicIp = new PublicIp({ timeout: 1000 });
|
|
265
|
+
return publicIp.getPublicIps();
|
|
266
|
+
};
|
|
266
267
|
if (this.options.cacheTtl && this.options.cacheTtl > 0) {
|
|
267
268
|
return this.getCached('publicIps', fetcher);
|
|
268
269
|
}
|
|
@@ -15,8 +15,6 @@ export { smartpromise, smartping, smartstring };
|
|
|
15
15
|
// @third party scope
|
|
16
16
|
// @ts-ignore
|
|
17
17
|
import isopen from 'isopen';
|
|
18
|
-
// @ts-ignore
|
|
19
|
-
import * as publicIp from 'public-ip';
|
|
20
18
|
import * as systeminformation from 'systeminformation';
|
|
21
19
|
|
|
22
|
-
export { isopen,
|
|
20
|
+
export { isopen, systeminformation };
|