@push.rocks/smartnetwork 3.0.2 → 4.0.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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * autocreated commitinfo by @pushrocks/commitinfo
2
+ * autocreated commitinfo by @push.rocks/commitinfo
3
3
  */
4
4
  export declare const commitinfo: {
5
5
  name: string;
@@ -1,9 +1,9 @@
1
1
  /**
2
- * autocreated commitinfo by @pushrocks/commitinfo
2
+ * autocreated commitinfo by @push.rocks/commitinfo
3
3
  */
4
4
  export const commitinfo = {
5
- name: '@pushrocks/smartnetwork',
6
- version: '3.0.2',
7
- description: 'network diagnostics'
5
+ name: '@push.rocks/smartnetwork',
6
+ version: '4.0.1',
7
+ description: 'A toolkit for network diagnostics including speed tests, port availability checks, and more.'
8
8
  };
9
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx5QkFBeUI7SUFDL0IsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLHFCQUFxQjtDQUNuQyxDQUFBIn0=
9
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSwwQkFBMEI7SUFDaEMsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLDhGQUE4RjtDQUM1RyxDQUFBIn0=
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Custom error classes for network operations
3
+ */
4
+ export declare class NetworkError extends Error {
5
+ code?: string;
6
+ constructor(message?: string, code?: string);
7
+ }
8
+ export declare class TimeoutError extends NetworkError {
9
+ constructor(message?: string);
10
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Custom error classes for network operations
3
+ */
4
+ export class NetworkError extends Error {
5
+ constructor(message, code) {
6
+ super(message);
7
+ this.name = 'NetworkError';
8
+ this.code = code;
9
+ Object.setPrototypeOf(this, new.target.prototype);
10
+ }
11
+ }
12
+ export class TimeoutError extends NetworkError {
13
+ constructor(message) {
14
+ super(message, 'ETIMEOUT');
15
+ this.name = 'TimeoutError';
16
+ Object.setPrototypeOf(this, new.target.prototype);
17
+ }
18
+ }
19
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3JzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvZXJyb3JzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxPQUFPLFlBQWEsU0FBUSxLQUFLO0lBRXJDLFlBQVksT0FBZ0IsRUFBRSxJQUFhO1FBQ3pDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNmLElBQUksQ0FBQyxJQUFJLEdBQUcsY0FBYyxDQUFDO1FBQzNCLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO1FBQ2pCLE1BQU0sQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDcEQsQ0FBQztDQUNGO0FBRUQsTUFBTSxPQUFPLFlBQWEsU0FBUSxZQUFZO0lBQzVDLFlBQVksT0FBZ0I7UUFDMUIsS0FBSyxDQUFDLE9BQU8sRUFBRSxVQUFVLENBQUMsQ0FBQztRQUMzQixJQUFJLENBQUMsSUFBSSxHQUFHLGNBQWMsQ0FBQztRQUMzQixNQUFNLENBQUMsY0FBYyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ3BELENBQUM7Q0FDRiJ9
@@ -30,4 +30,4 @@ export function jitter(values) {
30
30
  }
31
31
  return average(jitters);
32
32
  }
33
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhdHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9oZWxwZXJzL3N0YXRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE1BQU0sVUFBVSxPQUFPLENBQUMsTUFBZ0I7SUFDdEMsSUFBSSxLQUFLLEdBQUcsQ0FBQyxDQUFDO0lBRWQsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFBRTtRQUN6QyxLQUFLLElBQUksTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO0tBQ3BCO0lBRUQsT0FBTyxLQUFLLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQztBQUMvQixDQUFDO0FBRUQsTUFBTSxVQUFVLE1BQU0sQ0FBQyxNQUFnQjtJQUNyQyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFFM0MsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUU3QixJQUFJLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQztRQUFFLE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBRTNDLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUMvQyxDQUFDO0FBRUQsTUFBTSxVQUFVLFFBQVEsQ0FBQyxNQUFnQixFQUFFLFVBQWtCO0lBQzNELE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDN0IsTUFBTSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxHQUFHLFVBQVUsQ0FBQztJQUM3QyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQzdCLE1BQU0sSUFBSSxHQUFHLEdBQUcsR0FBRyxJQUFJLENBQUM7SUFFeEIsSUFBSSxNQUFNLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQyxLQUFLLFNBQVMsRUFBRTtRQUNsQyxPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFJLEdBQUcsQ0FBQyxNQUFNLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0tBQ2hFO0lBRUQsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDdEIsQ0FBQztBQUVELE1BQU0sVUFBVSxNQUFNLENBQUMsTUFBZ0I7SUFDckMsK0RBQStEO0lBQy9ELElBQUksT0FBTyxHQUFHLEVBQUUsQ0FBQztJQUVqQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFBRTtRQUM3QyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0tBQ25EO0lBRUQsT0FBTyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7QUFDMUIsQ0FBQyJ9
33
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhdHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9oZWxwZXJzL3N0YXRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE1BQU0sVUFBVSxPQUFPLENBQUMsTUFBZ0I7SUFDdEMsSUFBSSxLQUFLLEdBQUcsQ0FBQyxDQUFDO0lBRWQsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1FBQzFDLEtBQUssSUFBSSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDckIsQ0FBQztJQUVELE9BQU8sS0FBSyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUM7QUFDL0IsQ0FBQztBQUVELE1BQU0sVUFBVSxNQUFNLENBQUMsTUFBZ0I7SUFDckMsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBRTNDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFFN0IsSUFBSSxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUM7UUFBRSxPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUUzQyxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksR0FBRyxDQUFDLENBQUMsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDL0MsQ0FBQztBQUVELE1BQU0sVUFBVSxRQUFRLENBQUMsTUFBZ0IsRUFBRSxVQUFrQjtJQUMzRCxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQzdCLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsR0FBRyxVQUFVLENBQUM7SUFDN0MsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUM3QixNQUFNLElBQUksR0FBRyxHQUFHLEdBQUcsSUFBSSxDQUFDO0lBRXhCLElBQUksTUFBTSxDQUFDLElBQUksR0FBRyxDQUFDLENBQUMsS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUNuQyxPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFJLEdBQUcsQ0FBQyxNQUFNLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ2pFLENBQUM7SUFFRCxPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztBQUN0QixDQUFDO0FBRUQsTUFBTSxVQUFVLE1BQU0sQ0FBQyxNQUFnQjtJQUNyQywrREFBK0Q7SUFDL0QsSUFBSSxPQUFPLEdBQUcsRUFBRSxDQUFDO0lBRWpCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7UUFDOUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsR0FBRyxNQUFNLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNwRCxDQUFDO0lBRUQsT0FBTyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7QUFDMUIsQ0FBQyJ9
@@ -1 +1,4 @@
1
1
  export * from './smartnetwork.classes.smartnetwork.js';
2
+ export type { SmartNetworkOptions, Hop } from './smartnetwork.classes.smartnetwork.js';
3
+ export { setLogger, getLogger } from './logging.js';
4
+ export { NetworkError, TimeoutError } from './errors.js';
package/dist_ts/index.js CHANGED
@@ -1,2 +1,4 @@
1
1
  export * from './smartnetwork.classes.smartnetwork.js';
2
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLHdDQUF3QyxDQUFDIn0=
2
+ export { setLogger, getLogger } from './logging.js';
3
+ export { NetworkError, TimeoutError } from './errors.js';
4
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLHdDQUF3QyxDQUFDO0FBRXZELE9BQU8sRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ3BELE9BQU8sRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLE1BQU0sYUFBYSxDQUFDIn0=
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Injectable logging interface and global logger
3
+ */
4
+ export interface Logger {
5
+ /** Debug-level messages */
6
+ debug?(...args: unknown[]): void;
7
+ /** Informational messages */
8
+ info(...args: unknown[]): void;
9
+ /** Warning messages */
10
+ warn?(...args: unknown[]): void;
11
+ /** Error messages */
12
+ error(...args: unknown[]): void;
13
+ }
14
+ /**
15
+ * Replace the global logger implementation
16
+ * @param logger Custom logger adhering to Logger interface
17
+ */
18
+ export declare function setLogger(logger: Logger): void;
19
+ /**
20
+ * Retrieve the current global logger
21
+ */
22
+ export declare function getLogger(): Logger;
@@ -0,0 +1,15 @@
1
+ let globalLogger = console;
2
+ /**
3
+ * Replace the global logger implementation
4
+ * @param logger Custom logger adhering to Logger interface
5
+ */
6
+ export function setLogger(logger) {
7
+ globalLogger = logger;
8
+ }
9
+ /**
10
+ * Retrieve the current global logger
11
+ */
12
+ export function getLogger() {
13
+ return globalLogger;
14
+ }
15
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9nZ2luZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2xvZ2dpbmcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBY0EsSUFBSSxZQUFZLEdBQVcsT0FBTyxDQUFDO0FBRW5DOzs7R0FHRztBQUNILE1BQU0sVUFBVSxTQUFTLENBQUMsTUFBYztJQUN0QyxZQUFZLEdBQUcsTUFBTSxDQUFDO0FBQ3hCLENBQUM7QUFFRDs7R0FFRztBQUNILE1BQU0sVUFBVSxTQUFTO0lBQ3ZCLE9BQU8sWUFBWSxDQUFDO0FBQ3RCLENBQUMifQ==
@@ -1,7 +1,11 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
1
  import * as plugins from './smartnetwork.plugins.js';
2
+ export interface SpeedOptions {
3
+ parallelStreams?: number;
4
+ duration?: number;
5
+ }
3
6
  export declare class CloudflareSpeed {
4
- constructor();
7
+ private opts;
8
+ constructor(opts?: SpeedOptions);
5
9
  speedTest(): Promise<{
6
10
  ip: string;
7
11
  serverLocation: {
@@ -36,19 +40,8 @@ export declare class CloudflareSpeed {
36
40
  download(bytes: number): Promise<number[]>;
37
41
  upload(bytes: number): Promise<number[]>;
38
42
  request(options: plugins.https.RequestOptions, data?: string): Promise<number[]>;
39
- fetchCfCdnCgiTrace(): Promise<{
40
- fl: string;
41
- h: string;
42
- ip: string;
43
- ts: string;
44
- visit_scheme: string;
45
- uag: string;
46
- colo: string;
47
- http: string;
48
- loc: string;
49
- tls: string;
50
- sni: string;
51
- warp: string;
52
- gateway: string;
53
- }>;
43
+ /**
44
+ * Fetch Cloudflare's trace endpoint and parse key=value lines to a record.
45
+ */
46
+ fetchCfCdnCgiTrace(): Promise<Record<string, string>>;
54
47
  }
@@ -1,24 +1,79 @@
1
1
  import * as plugins from './smartnetwork.plugins.js';
2
+ import { getLogger } from './logging.js';
3
+ import { NetworkError, TimeoutError } from './errors.js';
2
4
  import * as stats from './helpers/stats.js';
3
5
  export class CloudflareSpeed {
4
- constructor() { }
6
+ constructor(opts) {
7
+ this.opts = opts || {};
8
+ }
5
9
  async speedTest() {
6
10
  const latency = await this.measureLatency();
7
11
  const serverLocations = await this.fetchServerLocations();
8
12
  const cgiData = await this.fetchCfCdnCgiTrace();
9
- // lets test the download speed
10
- const testDown1 = await this.measureDownload(101000, 10);
11
- const testDown2 = await this.measureDownload(1001000, 8);
12
- const testDown3 = await this.measureDownload(10001000, 6);
13
- const testDown4 = await this.measureDownload(25001000, 4);
14
- const testDown5 = await this.measureDownload(100001000, 1);
15
- const downloadTests = [...testDown1, ...testDown2, ...testDown3, ...testDown4, ...testDown5];
13
+ // speed tests: either fixed segments or duration-based mode
14
+ const parallel = this.opts.parallelStreams ?? 1;
15
+ const measureDownloadParallel = (bytes, iterations) => {
16
+ if (parallel <= 1) {
17
+ return this.measureDownload(bytes, iterations);
18
+ }
19
+ return Promise.all(Array(parallel)
20
+ .fill(null)
21
+ .map(() => this.measureDownload(bytes, iterations))).then((arrays) => arrays.flat());
22
+ };
23
+ let downloadTests;
24
+ if (this.opts.duration && this.opts.duration > 0) {
25
+ // duration-based download: run for specified seconds
26
+ downloadTests = [];
27
+ const durMs = this.opts.duration * 1000;
28
+ const startMs = Date.now();
29
+ // use medium chunk size for download
30
+ const chunkBytes = 25001000;
31
+ while (Date.now() - startMs < durMs) {
32
+ const speeds = await measureDownloadParallel(chunkBytes, 1);
33
+ downloadTests.push(...speeds);
34
+ }
35
+ if (downloadTests.length === 0)
36
+ downloadTests = [0];
37
+ }
38
+ else {
39
+ // fixed download segments
40
+ const t1 = await measureDownloadParallel(101000, 10);
41
+ const t2 = await measureDownloadParallel(1001000, 8);
42
+ const t3 = await measureDownloadParallel(10001000, 6);
43
+ const t4 = await measureDownloadParallel(25001000, 4);
44
+ const t5 = await measureDownloadParallel(100001000, 1);
45
+ downloadTests = [...t1, ...t2, ...t3, ...t4, ...t5];
46
+ }
16
47
  const speedDownload = stats.quartile(downloadTests, 0.9).toFixed(2);
17
- // lets test the upload speed
18
- const testUp1 = await this.measureUpload(11000, 10);
19
- const testUp2 = await this.measureUpload(101000, 10);
20
- const testUp3 = await this.measureUpload(1001000, 8);
21
- const uploadTests = [...testUp1, ...testUp2, ...testUp3];
48
+ // lets test the upload speed with configurable parallel streams
49
+ const measureUploadParallel = (bytes, iterations) => {
50
+ if (parallel <= 1) {
51
+ return this.measureUpload(bytes, iterations);
52
+ }
53
+ return Promise.all(Array(parallel)
54
+ .fill(null)
55
+ .map(() => this.measureUpload(bytes, iterations))).then((arrays) => arrays.flat());
56
+ };
57
+ let uploadTests;
58
+ if (this.opts.duration && this.opts.duration > 0) {
59
+ // duration-based upload: run for specified seconds
60
+ uploadTests = [];
61
+ const durMsUp = this.opts.duration * 1000;
62
+ const startMsUp = Date.now();
63
+ const chunkBytesUp = 1001000;
64
+ while (Date.now() - startMsUp < durMsUp) {
65
+ const speeds = await measureUploadParallel(chunkBytesUp, 1);
66
+ uploadTests.push(...speeds);
67
+ }
68
+ if (uploadTests.length === 0)
69
+ uploadTests = [0];
70
+ }
71
+ else {
72
+ const u1 = await measureUploadParallel(11000, 10);
73
+ const u2 = await measureUploadParallel(101000, 10);
74
+ const u3 = await measureUploadParallel(1001000, 8);
75
+ uploadTests = [...u1, ...u2, ...u3];
76
+ }
22
77
  const speedUpload = stats.quartile(uploadTests, 0.9).toFixed(2);
23
78
  return {
24
79
  ...latency,
@@ -39,7 +94,7 @@ export class CloudflareSpeed {
39
94
  // TTFB - Server processing time
40
95
  measurements.push(response[4] - response[0] - response[6]);
41
96
  }, (error) => {
42
- console.log(`Error: ${error}`);
97
+ getLogger().error('Error measuring latency:', error);
43
98
  });
44
99
  }
45
100
  return {
@@ -57,7 +112,7 @@ export class CloudflareSpeed {
57
112
  const transferTime = response[5] - response[4];
58
113
  measurements.push(await this.measureSpeed(bytes, transferTime));
59
114
  }, (error) => {
60
- console.log(`Error: ${error}`);
115
+ getLogger().error('Error measuring download chunk:', error);
61
116
  });
62
117
  }
63
118
  return measurements;
@@ -69,7 +124,7 @@ export class CloudflareSpeed {
69
124
  const transferTime = response[6];
70
125
  measurements.push(await this.measureSpeed(bytes, transferTime));
71
126
  }, (error) => {
72
- console.log(`Error: ${error}`);
127
+ getLogger().error('Error measuring upload chunk:', error);
73
128
  });
74
129
  }
75
130
  return measurements;
@@ -80,10 +135,8 @@ export class CloudflareSpeed {
80
135
  async fetchServerLocations() {
81
136
  const res = JSON.parse(await this.get('speed.cloudflare.com', '/locations'));
82
137
  return res.reduce((data, optionsArg) => {
83
- // Bypass prettier "no-assign-param" rules
84
- const data1 = data;
85
- data1[optionsArg.iata] = optionsArg.city;
86
- return data1;
138
+ data[optionsArg.iata] = optionsArg.city;
139
+ return data;
87
140
  }, {});
88
141
  }
89
142
  async get(hostname, path) {
@@ -92,6 +145,8 @@ export class CloudflareSpeed {
92
145
  hostname,
93
146
  path,
94
147
  method: 'GET',
148
+ // disable connection pooling to avoid listener accumulation
149
+ agent: false,
95
150
  }, (res) => {
96
151
  const body = [];
97
152
  res.on('data', (chunk) => {
@@ -106,7 +161,7 @@ export class CloudflareSpeed {
106
161
  }
107
162
  });
108
163
  req.on('error', (err) => {
109
- reject(err);
164
+ reject(new NetworkError(err.message, err.code));
110
165
  });
111
166
  });
112
167
  req.end();
@@ -141,7 +196,9 @@ export class CloudflareSpeed {
141
196
  let ended;
142
197
  return new Promise((resolve, reject) => {
143
198
  started = plugins.perfHooks.performance.now();
144
- const req = plugins.https.request(options, (res) => {
199
+ // disable connection pooling to avoid listener accumulation across requests
200
+ const reqOptions = { ...options, agent: false };
201
+ const req = plugins.https.request(reqOptions, (res) => {
145
202
  res.once('readable', () => {
146
203
  ttfb = plugins.perfHooks.performance.now();
147
204
  });
@@ -159,41 +216,42 @@ export class CloudflareSpeed {
159
216
  ]);
160
217
  });
161
218
  });
162
- req.on('socket', (socket) => {
163
- socket.on('lookup', () => {
219
+ // Listen for timing events once per new socket
220
+ req.once('socket', (socket) => {
221
+ socket.once('lookup', () => {
164
222
  dnsLookup = plugins.perfHooks.performance.now();
165
223
  });
166
- socket.on('connect', () => {
224
+ socket.once('connect', () => {
167
225
  tcpHandshake = plugins.perfHooks.performance.now();
168
226
  });
169
- socket.on('secureConnect', () => {
227
+ socket.once('secureConnect', () => {
170
228
  sslHandshake = plugins.perfHooks.performance.now();
171
229
  });
172
230
  });
173
231
  req.on('error', (error) => {
174
- reject(error);
232
+ reject(new NetworkError(error.message, error.code));
175
233
  });
176
234
  req.write(data);
177
235
  req.end();
178
236
  });
179
237
  }
238
+ /**
239
+ * Fetch Cloudflare's trace endpoint and parse key=value lines to a record.
240
+ */
180
241
  async fetchCfCdnCgiTrace() {
181
242
  const parseCfCdnCgiTrace = (text) => text
182
243
  .split('\n')
183
244
  .map((i) => {
184
- const j = i.split('=');
185
- return [j[0], j[1]];
245
+ const parts = i.split('=');
246
+ return [parts[0], parts[1]];
186
247
  })
187
248
  .reduce((data, [k, v]) => {
188
249
  if (v === undefined)
189
250
  return data;
190
- // Bypass prettier "no-assign-param" rules
191
- const data1 = data;
192
- // Object.fromEntries is only supported by Node.js 12 or newer
193
- data1[k] = v;
194
- return data1;
251
+ data[k] = v;
252
+ return data;
195
253
  }, {});
196
254
  return this.get('speed.cloudflare.com', '/cdn-cgi/trace').then(parseCfCdnCgiTrace);
197
255
  }
198
256
  }
199
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRuZXR3b3JrLmNsYXNzZXMuY2xvdWRmbGFyZXNwZWVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvc21hcnRuZXR3b3JrLmNsYXNzZXMuY2xvdWRmbGFyZXNwZWVkLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sMkJBQTJCLENBQUM7QUFDckQsT0FBTyxLQUFLLEtBQUssTUFBTSxvQkFBb0IsQ0FBQztBQUU1QyxNQUFNLE9BQU8sZUFBZTtJQUMxQixnQkFBZSxDQUFDO0lBRVQsS0FBSyxDQUFDLFNBQVM7UUFDcEIsTUFBTSxPQUFPLEdBQUcsTUFBTSxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7UUFFNUMsTUFBTSxlQUFlLEdBQUcsTUFBTSxJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztRQUMxRCxNQUFNLE9BQU8sR0FBRyxNQUFNLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1FBRWhELCtCQUErQjtRQUMvQixNQUFNLFNBQVMsR0FBRyxNQUFNLElBQUksQ0FBQyxlQUFlLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ3pELE1BQU0sU0FBUyxHQUFHLE1BQU0sSUFBSSxDQUFDLGVBQWUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDekQsTUFBTSxTQUFTLEdBQUcsTUFBTSxJQUFJLENBQUMsZUFBZSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUMxRCxNQUFNLFNBQVMsR0FBRyxNQUFNLElBQUksQ0FBQyxlQUFlLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQzFELE1BQU0sU0FBUyxHQUFHLE1BQU0sSUFBSSxDQUFDLGVBQWUsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDM0QsTUFBTSxhQUFhLEdBQUcsQ0FBQyxHQUFHLFNBQVMsRUFBRSxHQUFHLFNBQVMsRUFBRSxHQUFHLFNBQVMsRUFBRSxHQUFHLFNBQVMs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
257
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRuZXR3b3JrLmNsYXNzZXMuY2xvdWRmbGFyZXNwZWVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvc21hcnRuZXR3b3JrLmNsYXNzZXMuY2xvdWRmbGFyZXNwZWVkLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sMkJBQTJCLENBQUM7QUFDckQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUN6QyxPQUFPLEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUN6RCxPQUFPLEtBQUssS0FBSyxNQUFNLG9CQUFvQixDQUFDO0FBTTVDLE1BQU0sT0FBTyxlQUFlO0lBRTFCLFlBQVksSUFBbUI7UUFDN0IsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLElBQUksRUFBRSxDQUFDO0lBQ3pCLENBQUM7SUFFTSxLQUFLLENBQUMsU0FBUztRQUNwQixNQUFNLE9BQU8sR0FBRyxNQUFNLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUU1QyxNQUFNLGVBQWUsR0FBRyxNQUFNLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO1FBQzFELE1BQU0sT0FBTyxHQUFHLE1BQU0sSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7UUFFaEQsNERBQTREO1FBQzVELE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsZUFBZSxJQUFJLENBQUMsQ0FBQztRQUNoRCxNQUFNLHVCQUF1QixHQUFHLENBQUMsS0FBYSxFQUFFLFVBQWtCLEVBQUUsRUFBRTtZQUNwRSxJQUFJLFFBQVEsSUFBSSxDQUFDLEVBQUUsQ0FBQztnQkFDbEIsT0FBTyxJQUFJLENBQUMsZUFBZSxDQUFDLEtBQUssRUFBRSxVQUFVLENBQUMsQ0FBQztZQUNqRCxDQUFDO1lBQ0QsT0FBTyxPQUFPLENBQUMsR0FBRyxDQUNoQixLQUFLLENBQUMsUUFBUSxDQUFDO2lCQUNaLElBQUksQ0FBQyxJ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
@@ -1,15 +1,40 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
- /// <reference types="node" resolution-mode="require"/>
3
1
  import * as plugins from './smartnetwork.plugins.js';
4
2
  /**
5
3
  * SmartNetwork simplifies actions within the network
6
4
  */
5
+ /**
6
+ * Configuration options for SmartNetwork
7
+ */
8
+ export interface SmartNetworkOptions {
9
+ /** Cache time-to-live in milliseconds for gateway and public IP lookups */
10
+ cacheTtl?: number;
11
+ }
12
+ /**
13
+ * A hop in a traceroute result
14
+ */
15
+ export interface Hop {
16
+ ttl: number;
17
+ ip: string;
18
+ rtt: number | null;
19
+ }
7
20
  export declare class SmartNetwork {
21
+ /** Static registry for external plugins */
22
+ static pluginsRegistry: Map<string, any>;
23
+ /** Register a plugin by name */
24
+ static registerPlugin(name: string, ctor: any): void;
25
+ /** Unregister a plugin by name */
26
+ static unregisterPlugin(name: string): void;
27
+ private options;
28
+ private cache;
29
+ constructor(options?: SmartNetworkOptions);
8
30
  /**
9
31
  * get network speed
10
- * @param measurementTime
32
+ * @param opts optional speed test parameters
11
33
  */
12
- getSpeed(): Promise<{
34
+ getSpeed(opts?: {
35
+ parallelStreams?: number;
36
+ duration?: number;
37
+ }): Promise<{
13
38
  ip: string;
14
39
  serverLocation: {
15
40
  shortId: string;
@@ -26,25 +51,88 @@ export declare class SmartNetwork {
26
51
  medianTime: number;
27
52
  jitter: number;
28
53
  }>;
29
- ping(hostArg: string, timeoutArg?: number): Promise<ReturnType<typeof plugins.smartping.Smartping.prototype.ping>>;
54
+ /**
55
+ * Send ICMP pings to a host. Optionally specify count for multiple pings.
56
+ */
57
+ ping(host: string, opts?: {
58
+ timeout?: number;
59
+ count?: number;
60
+ }): Promise<any>;
30
61
  /**
31
62
  * returns a promise with a boolean answer
32
63
  * note: false also resolves with false as argument
33
64
  * @param port
34
65
  */
66
+ /**
67
+ * Check if a local port is unused (both IPv4 and IPv6)
68
+ */
35
69
  isLocalPortUnused(port: number): Promise<boolean>;
36
70
  /**
37
71
  * checks wether a remote port is available
38
72
  * @param domainArg
39
73
  */
40
- isRemotePortAvailable(domainArg: string, portArg?: number): Promise<boolean>;
41
- getGateways(): Promise<NodeJS.Dict<plugins.os.NetworkInterfaceInfo[]>>;
74
+ /**
75
+ * Check if a remote port is available
76
+ * @param target host or "host:port"
77
+ * @param opts options including port, protocol (only tcp), retries and timeout
78
+ */
79
+ /**
80
+ * Check if a remote port is available
81
+ * @param target host or "host:port"
82
+ * @param portOrOpts either a port number (deprecated) or options object
83
+ */
84
+ isRemotePortAvailable(target: string, portOrOpts?: number | {
85
+ port?: number;
86
+ protocol?: 'tcp' | 'udp';
87
+ timeout?: number;
88
+ retries?: number;
89
+ }): Promise<boolean>;
90
+ /**
91
+ * List network interfaces (gateways)
92
+ */
93
+ getGateways(): Promise<Record<string, plugins.os.NetworkInterfaceInfo[]>>;
42
94
  getDefaultGateway(): Promise<{
43
95
  ipv4: plugins.os.NetworkInterfaceInfo;
44
96
  ipv6: plugins.os.NetworkInterfaceInfo;
45
97
  }>;
98
+ /**
99
+ * Lookup public IPv4 and IPv6
100
+ */
46
101
  getPublicIps(): Promise<{
47
- v4: any;
48
- v6: any;
102
+ v4: string | null;
103
+ v6: string | null;
104
+ }>;
105
+ /**
106
+ * Resolve DNS records (A, AAAA, MX)
107
+ */
108
+ resolveDns(host: string): Promise<{
109
+ A: string[];
110
+ AAAA: string[];
111
+ MX: {
112
+ exchange: string;
113
+ priority: number;
114
+ }[];
49
115
  }>;
116
+ /**
117
+ * Perform a simple HTTP/HTTPS endpoint health check
118
+ */
119
+ checkEndpoint(urlString: string, opts?: {
120
+ timeout?: number;
121
+ }): Promise<{
122
+ status: number;
123
+ headers: Record<string, string>;
124
+ rtt: number;
125
+ }>;
126
+ /**
127
+ * Perform a traceroute: hop-by-hop latency using the system traceroute tool.
128
+ * Falls back to a single-hop stub if traceroute is unavailable or errors.
129
+ */
130
+ traceroute(host: string, opts?: {
131
+ maxHops?: number;
132
+ timeout?: number;
133
+ }): Promise<Hop[]>;
134
+ /**
135
+ * Internal caching helper
136
+ */
137
+ private getCached;
50
138
  }