nlcurl 0.1.0 → 0.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/README.md +5 -13
- package/dist/cli/args.d.ts +37 -5
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +6 -17
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/index.d.ts +3 -3
- package/dist/cli/index.js +25 -10
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/output.d.ts +24 -7
- package/dist/cli/output.d.ts.map +1 -1
- package/dist/cli/output.js +24 -12
- package/dist/cli/output.js.map +1 -1
- package/dist/cookies/jar.d.ts +45 -13
- package/dist/cookies/jar.d.ts.map +1 -1
- package/dist/cookies/jar.js +88 -29
- package/dist/cookies/jar.js.map +1 -1
- package/dist/cookies/parser.d.ts +25 -3
- package/dist/cookies/parser.d.ts.map +1 -1
- package/dist/cookies/parser.js +12 -7
- package/dist/cookies/parser.js.map +1 -1
- package/dist/core/client.d.ts +49 -33
- package/dist/core/client.d.ts.map +1 -1
- package/dist/core/client.js +64 -38
- package/dist/core/client.js.map +1 -1
- package/dist/core/errors.d.ts +94 -6
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +95 -6
- package/dist/core/errors.js.map +1 -1
- package/dist/core/request.d.ts +96 -30
- package/dist/core/request.d.ts.map +1 -1
- package/dist/core/request.js +0 -3
- package/dist/core/request.js.map +1 -1
- package/dist/core/response.d.ts +92 -8
- package/dist/core/response.d.ts.map +1 -1
- package/dist/core/response.js +92 -7
- package/dist/core/response.js.map +1 -1
- package/dist/core/session.d.ts +109 -14
- package/dist/core/session.d.ts.map +1 -1
- package/dist/core/session.js +124 -46
- package/dist/core/session.js.map +1 -1
- package/dist/fingerprints/akamai.d.ts +11 -11
- package/dist/fingerprints/akamai.d.ts.map +1 -1
- package/dist/fingerprints/akamai.js +10 -14
- package/dist/fingerprints/akamai.js.map +1 -1
- package/dist/fingerprints/database.d.ts +14 -15
- package/dist/fingerprints/database.d.ts.map +1 -1
- package/dist/fingerprints/database.js +14 -19
- package/dist/fingerprints/database.js.map +1 -1
- package/dist/fingerprints/extensions.d.ts +121 -27
- package/dist/fingerprints/extensions.d.ts.map +1 -1
- package/dist/fingerprints/extensions.js +132 -49
- package/dist/fingerprints/extensions.js.map +1 -1
- package/dist/fingerprints/ja3.d.ts +34 -18
- package/dist/fingerprints/ja3.d.ts.map +1 -1
- package/dist/fingerprints/ja3.js +34 -18
- package/dist/fingerprints/ja3.js.map +1 -1
- package/dist/fingerprints/profiles/chrome.d.ts +21 -10
- package/dist/fingerprints/profiles/chrome.d.ts.map +1 -1
- package/dist/fingerprints/profiles/chrome.js +25 -22
- package/dist/fingerprints/profiles/chrome.js.map +1 -1
- package/dist/fingerprints/profiles/edge.d.ts +10 -7
- package/dist/fingerprints/profiles/edge.d.ts.map +1 -1
- package/dist/fingerprints/profiles/edge.js +10 -10
- package/dist/fingerprints/profiles/edge.js.map +1 -1
- package/dist/fingerprints/profiles/firefox.d.ts +11 -3
- package/dist/fingerprints/profiles/firefox.d.ts.map +1 -1
- package/dist/fingerprints/profiles/firefox.js +15 -14
- package/dist/fingerprints/profiles/firefox.js.map +1 -1
- package/dist/fingerprints/profiles/safari.d.ts +14 -3
- package/dist/fingerprints/profiles/safari.d.ts.map +1 -1
- package/dist/fingerprints/profiles/safari.js +16 -13
- package/dist/fingerprints/profiles/safari.js.map +1 -1
- package/dist/fingerprints/profiles/tor.d.ts +8 -7
- package/dist/fingerprints/profiles/tor.d.ts.map +1 -1
- package/dist/fingerprints/profiles/tor.js +8 -14
- package/dist/fingerprints/profiles/tor.js.map +1 -1
- package/dist/fingerprints/types.d.ts +70 -47
- package/dist/fingerprints/types.d.ts.map +1 -1
- package/dist/fingerprints/types.js +0 -7
- package/dist/fingerprints/types.js.map +1 -1
- package/dist/http/h1/client.d.ts +30 -9
- package/dist/http/h1/client.d.ts.map +1 -1
- package/dist/http/h1/client.js +152 -15
- package/dist/http/h1/client.js.map +1 -1
- package/dist/http/h1/encoder.d.ts +9 -6
- package/dist/http/h1/encoder.d.ts.map +1 -1
- package/dist/http/h1/encoder.js +8 -12
- package/dist/http/h1/encoder.js.map +1 -1
- package/dist/http/h1/parser.d.ts +68 -14
- package/dist/http/h1/parser.d.ts.map +1 -1
- package/dist/http/h1/parser.js +92 -37
- package/dist/http/h1/parser.js.map +1 -1
- package/dist/http/h2/client.d.ts +81 -14
- package/dist/http/h2/client.d.ts.map +1 -1
- package/dist/http/h2/client.js +465 -63
- package/dist/http/h2/client.js.map +1 -1
- package/dist/http/h2/frames.d.ts +103 -6
- package/dist/http/h2/frames.d.ts.map +1 -1
- package/dist/http/h2/frames.js +96 -17
- package/dist/http/h2/frames.js.map +1 -1
- package/dist/http/h2/hpack.d.ts +30 -5
- package/dist/http/h2/hpack.d.ts.map +1 -1
- package/dist/http/h2/hpack.js +39 -35
- package/dist/http/h2/hpack.js.map +1 -1
- package/dist/http/negotiator.d.ts +35 -12
- package/dist/http/negotiator.d.ts.map +1 -1
- package/dist/http/negotiator.js +89 -24
- package/dist/http/negotiator.js.map +1 -1
- package/dist/http/pool.d.ts +66 -17
- package/dist/http/pool.d.ts.map +1 -1
- package/dist/http/pool.js +47 -20
- package/dist/http/pool.js.map +1 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -13
- package/dist/index.js.map +1 -1
- package/dist/middleware/interceptor.d.ts +40 -8
- package/dist/middleware/interceptor.d.ts.map +1 -1
- package/dist/middleware/interceptor.js +28 -6
- package/dist/middleware/interceptor.js.map +1 -1
- package/dist/middleware/rate-limiter.d.ts +18 -5
- package/dist/middleware/rate-limiter.d.ts.map +1 -1
- package/dist/middleware/rate-limiter.js +12 -7
- package/dist/middleware/rate-limiter.js.map +1 -1
- package/dist/middleware/retry.d.ts +17 -5
- package/dist/middleware/retry.d.ts.map +1 -1
- package/dist/middleware/retry.js +13 -11
- package/dist/middleware/retry.js.map +1 -1
- package/dist/proxy/http-proxy.d.ts +17 -9
- package/dist/proxy/http-proxy.d.ts.map +1 -1
- package/dist/proxy/http-proxy.js +9 -13
- package/dist/proxy/http-proxy.js.map +1 -1
- package/dist/proxy/socks.d.ts +20 -9
- package/dist/proxy/socks.d.ts.map +1 -1
- package/dist/proxy/socks.js +20 -31
- package/dist/proxy/socks.js.map +1 -1
- package/dist/tls/constants.d.ts +74 -4
- package/dist/tls/constants.d.ts.map +1 -1
- package/dist/tls/constants.js +75 -21
- package/dist/tls/constants.js.map +1 -1
- package/dist/tls/node-engine.d.ts +17 -16
- package/dist/tls/node-engine.d.ts.map +1 -1
- package/dist/tls/node-engine.js +20 -27
- package/dist/tls/node-engine.js.map +1 -1
- package/dist/tls/stealth/client-hello.d.ts +32 -16
- package/dist/tls/stealth/client-hello.d.ts.map +1 -1
- package/dist/tls/stealth/client-hello.js +13 -37
- package/dist/tls/stealth/client-hello.js.map +1 -1
- package/dist/tls/stealth/engine.d.ts +18 -10
- package/dist/tls/stealth/engine.d.ts.map +1 -1
- package/dist/tls/stealth/engine.js +18 -24
- package/dist/tls/stealth/engine.js.map +1 -1
- package/dist/tls/stealth/handshake.d.ts +31 -17
- package/dist/tls/stealth/handshake.d.ts.map +1 -1
- package/dist/tls/stealth/handshake.js +173 -74
- package/dist/tls/stealth/handshake.js.map +1 -1
- package/dist/tls/stealth/key-schedule.d.ts +89 -32
- package/dist/tls/stealth/key-schedule.d.ts.map +1 -1
- package/dist/tls/stealth/key-schedule.js +62 -42
- package/dist/tls/stealth/key-schedule.js.map +1 -1
- package/dist/tls/stealth/record-layer.d.ts +76 -25
- package/dist/tls/stealth/record-layer.d.ts.map +1 -1
- package/dist/tls/stealth/record-layer.js +66 -36
- package/dist/tls/stealth/record-layer.js.map +1 -1
- package/dist/tls/types.d.ts +33 -25
- package/dist/tls/types.d.ts.map +1 -1
- package/dist/tls/types.js +0 -4
- package/dist/tls/types.js.map +1 -1
- package/dist/utils/buffer-reader.d.ts +99 -7
- package/dist/utils/buffer-reader.d.ts.map +1 -1
- package/dist/utils/buffer-reader.js +99 -7
- package/dist/utils/buffer-reader.js.map +1 -1
- package/dist/utils/buffer-writer.d.ts +99 -10
- package/dist/utils/buffer-writer.d.ts.map +1 -1
- package/dist/utils/buffer-writer.js +101 -12
- package/dist/utils/buffer-writer.js.map +1 -1
- package/dist/utils/encoding.d.ts +33 -8
- package/dist/utils/encoding.d.ts.map +1 -1
- package/dist/utils/encoding.js +58 -13
- package/dist/utils/encoding.js.map +1 -1
- package/dist/utils/logger.d.ts +61 -2
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +52 -4
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/url.d.ts +47 -7
- package/dist/utils/url.d.ts.map +1 -1
- package/dist/utils/url.js +47 -7
- package/dist/utils/url.js.map +1 -1
- package/dist/ws/client.d.ts +59 -15
- package/dist/ws/client.d.ts.map +1 -1
- package/dist/ws/client.js +34 -27
- package/dist/ws/client.js.map +1 -1
- package/dist/ws/frame.d.ts +43 -9
- package/dist/ws/frame.d.ts.map +1 -1
- package/dist/ws/frame.js +35 -19
- package/dist/ws/frame.js.map +1 -1
- package/package.json +2 -2
package/dist/utils/logger.js
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Structured logger with configurable verbosity.
|
|
3
|
-
*/
|
|
4
1
|
const LEVEL_ORDER = {
|
|
5
2
|
debug: 0,
|
|
6
3
|
info: 1,
|
|
@@ -8,26 +5,64 @@ const LEVEL_ORDER = {
|
|
|
8
5
|
error: 3,
|
|
9
6
|
silent: 4,
|
|
10
7
|
};
|
|
8
|
+
/**
|
|
9
|
+
* Default {@link Logger} implementation that writes to `process.stderr`.
|
|
10
|
+
* Messages are prefixed with `[nlcurl:<level>]` and only emitted when the
|
|
11
|
+
* message severity meets or exceeds the configured `level`.
|
|
12
|
+
*/
|
|
11
13
|
export class ConsoleLogger {
|
|
12
14
|
level;
|
|
15
|
+
/**
|
|
16
|
+
* Creates a new ConsoleLogger.
|
|
17
|
+
*
|
|
18
|
+
* @param {LogLevel} [level='warn'] - Minimum severity level to emit.
|
|
19
|
+
*/
|
|
13
20
|
constructor(level = 'warn') {
|
|
14
21
|
this.level = LEVEL_ORDER[level];
|
|
15
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* Emits a debug-level message to `stderr` — only written when the
|
|
25
|
+
* configured minimum level is `'debug'`.
|
|
26
|
+
*
|
|
27
|
+
* @param {string} message - Primary log message.
|
|
28
|
+
* @param {...unknown} args - Additional values appended after the message.
|
|
29
|
+
*/
|
|
16
30
|
debug(message, ...args) {
|
|
17
31
|
if (this.level <= LEVEL_ORDER.debug) {
|
|
18
32
|
process.stderr.write(`[nlcurl:debug] ${message}${this.formatArgs(args)}\n`);
|
|
19
33
|
}
|
|
20
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Emits an info-level message to `stderr` — only written when the
|
|
37
|
+
* configured minimum level is `'debug'` or `'info'`.
|
|
38
|
+
*
|
|
39
|
+
* @param {string} message - Primary log message.
|
|
40
|
+
* @param {...unknown} args - Additional values appended after the message.
|
|
41
|
+
*/
|
|
21
42
|
info(message, ...args) {
|
|
22
43
|
if (this.level <= LEVEL_ORDER.info) {
|
|
23
44
|
process.stderr.write(`[nlcurl:info] ${message}${this.formatArgs(args)}\n`);
|
|
24
45
|
}
|
|
25
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Emits a warn-level message to `stderr` — only written when the
|
|
49
|
+
* configured minimum level is `'debug'`, `'info'`, or `'warn'`.
|
|
50
|
+
*
|
|
51
|
+
* @param {string} message - Primary log message.
|
|
52
|
+
* @param {...unknown} args - Additional values appended after the message.
|
|
53
|
+
*/
|
|
26
54
|
warn(message, ...args) {
|
|
27
55
|
if (this.level <= LEVEL_ORDER.warn) {
|
|
28
56
|
process.stderr.write(`[nlcurl:warn] ${message}${this.formatArgs(args)}\n`);
|
|
29
57
|
}
|
|
30
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Emits an error-level message to `stderr` — only written when the
|
|
61
|
+
* configured minimum level is not `'silent'`.
|
|
62
|
+
*
|
|
63
|
+
* @param {string} message - Primary log message.
|
|
64
|
+
* @param {...unknown} args - Additional values appended after the message.
|
|
65
|
+
*/
|
|
31
66
|
error(message, ...args) {
|
|
32
67
|
if (this.level <= LEVEL_ORDER.error) {
|
|
33
68
|
process.stderr.write(`[nlcurl:error] ${message}${this.formatArgs(args)}\n`);
|
|
@@ -39,7 +74,10 @@ export class ConsoleLogger {
|
|
|
39
74
|
return ' ' + args.map((a) => (typeof a === 'string' ? a : JSON.stringify(a))).join(' ');
|
|
40
75
|
}
|
|
41
76
|
}
|
|
42
|
-
/**
|
|
77
|
+
/**
|
|
78
|
+
* A no-op {@link Logger} that discards all messages. Assign this via
|
|
79
|
+
* {@link setDefaultLogger} to silence the library entirely.
|
|
80
|
+
*/
|
|
43
81
|
export const SILENT_LOGGER = {
|
|
44
82
|
debug() { },
|
|
45
83
|
info() { },
|
|
@@ -47,9 +85,19 @@ export const SILENT_LOGGER = {
|
|
|
47
85
|
error() { },
|
|
48
86
|
};
|
|
49
87
|
let _default = new ConsoleLogger('warn');
|
|
88
|
+
/**
|
|
89
|
+
* Replaces the process-wide default logger used by all NLcURL internals.
|
|
90
|
+
*
|
|
91
|
+
* @param {Logger} logger - New logger instance to install.
|
|
92
|
+
*/
|
|
50
93
|
export function setDefaultLogger(logger) {
|
|
51
94
|
_default = logger;
|
|
52
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* Returns the currently active process-wide logger.
|
|
98
|
+
*
|
|
99
|
+
* @returns {Logger} The active logger instance.
|
|
100
|
+
*/
|
|
53
101
|
export function getDefaultLogger() {
|
|
54
102
|
return _default;
|
|
55
103
|
}
|
package/dist/utils/logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,GAA6B;IAC5C,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;IACR,MAAM,EAAE,CAAC;CACV,CAAC;AAcF;;;;GAIG;AACH,MAAM,OAAO,aAAa;IAChB,KAAK,CAAS;IAEtB;;;;OAIG;IACH,YAAY,QAAkB,MAAM;QAClC,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,OAAe,EAAE,GAAG,IAAe;QACvC,IAAI,IAAI,CAAC,KAAK,IAAI,WAAW,CAAC,KAAK,EAAE,CAAC;YACpC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kBAAkB,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9E,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACH,IAAI,CAAC,OAAe,EAAE,GAAG,IAAe;QACtC,IAAI,IAAI,CAAC,KAAK,IAAI,WAAW,CAAC,IAAI,EAAE,CAAC;YACnC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7E,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACH,IAAI,CAAC,OAAe,EAAE,GAAG,IAAe;QACtC,IAAI,IAAI,CAAC,KAAK,IAAI,WAAW,CAAC,IAAI,EAAE,CAAC;YACnC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7E,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,OAAe,EAAE,GAAG,IAAe;QACvC,IAAI,IAAI,CAAC,KAAK,IAAI,WAAW,CAAC,KAAK,EAAE,CAAC;YACpC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kBAAkB,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9E,CAAC;IACH,CAAC;IAEO,UAAU,CAAC,IAAe;QAChC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QACjC,OAAO,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1F,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAW;IACnC,KAAK,KAAI,CAAC;IACV,IAAI,KAAI,CAAC;IACT,IAAI,KAAI,CAAC;IACT,KAAK,KAAI,CAAC;CACX,CAAC;AAEF,IAAI,QAAQ,GAAW,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC;AAEjD;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,QAAQ,GAAG,MAAM,CAAC;AACpB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
package/dist/utils/url.d.ts
CHANGED
|
@@ -1,22 +1,62 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Resolves `relative` against `base`. When `base` is `undefined` or the
|
|
3
|
+
* resolution fails, `relative` is returned as-is.
|
|
4
|
+
*
|
|
5
|
+
* @param {string | undefined} base - Base URL string.
|
|
6
|
+
* @param {string} relative - Relative or absolute URL to resolve.
|
|
7
|
+
* @returns {string} The resolved absolute URL, or `relative` if resolution fails.
|
|
4
8
|
*/
|
|
5
9
|
export declare function resolveURL(base: string | undefined, relative: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* Appends `params` as query-string parameters to `url`. Existing parameters in
|
|
12
|
+
* the URL are preserved. `undefined` and `null` values are omitted.
|
|
13
|
+
*
|
|
14
|
+
* @param {string} url - Base URL.
|
|
15
|
+
* @param {Record<string, string | number | boolean>} [params] - Key-value pairs to append.
|
|
16
|
+
* @returns {string} URL with appended query parameters.
|
|
17
|
+
*/
|
|
6
18
|
export declare function appendParams(url: string, params?: Record<string, string | number | boolean>): string;
|
|
19
|
+
/**
|
|
20
|
+
* Parses `raw` into a `URL` object.
|
|
21
|
+
*
|
|
22
|
+
* @param {string} raw - Absolute URL string to parse.
|
|
23
|
+
* @returns {URL} Parsed URL.
|
|
24
|
+
* @throws {TypeError} If `raw` is not a valid absolute URL.
|
|
25
|
+
*/
|
|
7
26
|
export declare function parseURL(raw: string): URL;
|
|
8
27
|
/**
|
|
9
|
-
*
|
|
10
|
-
* `
|
|
28
|
+
* Returns the origin of `url` in `scheme://hostname:port` form. The port is
|
|
29
|
+
* always included explicitly, defaulting to `443` for `https:` and `80` for
|
|
30
|
+
* `http:`.
|
|
31
|
+
*
|
|
32
|
+
* @param {string} url - Absolute URL string.
|
|
33
|
+
* @returns {string} Origin string (e.g. `"https://example.com:443"`).
|
|
11
34
|
*/
|
|
12
35
|
export declare function originOf(url: string): string;
|
|
13
|
-
/**
|
|
36
|
+
/**
|
|
37
|
+
* Extracts the hostname from `url` for use as the TLS SNI server-name value.
|
|
38
|
+
*
|
|
39
|
+
* @param {string} url - Absolute URL string.
|
|
40
|
+
* @returns {string} Hostname without port (e.g. `"example.com"`).
|
|
41
|
+
*/
|
|
14
42
|
export declare function sniHost(url: string): string;
|
|
15
|
-
/**
|
|
43
|
+
/**
|
|
44
|
+
* Extracts the host and port from `url`. The port defaults to `443` for
|
|
45
|
+
* `https:` and `80` for `http:` when not explicitly specified in the URL.
|
|
46
|
+
*
|
|
47
|
+
* @param {string} url - Absolute URL string.
|
|
48
|
+
* @returns {{ host: string; port: number }} Hostname and numeric port.
|
|
49
|
+
*/
|
|
16
50
|
export declare function hostPort(url: string): {
|
|
17
51
|
host: string;
|
|
18
52
|
port: number;
|
|
19
53
|
};
|
|
20
|
-
/**
|
|
54
|
+
/**
|
|
55
|
+
* Returns the path and query string of `url` suitable for use as the
|
|
56
|
+
* request-target in an HTTP/1.1 request line.
|
|
57
|
+
*
|
|
58
|
+
* @param {string} url - Absolute URL string.
|
|
59
|
+
* @returns {string} Path + query string (e.g. `"/search?q=hello"`).
|
|
60
|
+
*/
|
|
21
61
|
export declare function requestPath(url: string): string;
|
|
22
62
|
//# sourceMappingURL=url.d.ts.map
|
package/dist/utils/url.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../../src/utils/url.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../../src/utils/url.ts"],"names":[],"mappings":"AACA;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAO7E;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,GACjD,MAAM,CASR;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAEzC;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAI5C;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE3C;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAOpE;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAG/C"}
|
package/dist/utils/url.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Resolves `relative` against `base`. When `base` is `undefined` or the
|
|
3
|
+
* resolution fails, `relative` is returned as-is.
|
|
4
|
+
*
|
|
5
|
+
* @param {string | undefined} base - Base URL string.
|
|
6
|
+
* @param {string} relative - Relative or absolute URL to resolve.
|
|
7
|
+
* @returns {string} The resolved absolute URL, or `relative` if resolution fails.
|
|
4
8
|
*/
|
|
5
9
|
export function resolveURL(base, relative) {
|
|
6
10
|
if (!base)
|
|
@@ -12,6 +16,14 @@ export function resolveURL(base, relative) {
|
|
|
12
16
|
return relative;
|
|
13
17
|
}
|
|
14
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Appends `params` as query-string parameters to `url`. Existing parameters in
|
|
21
|
+
* the URL are preserved. `undefined` and `null` values are omitted.
|
|
22
|
+
*
|
|
23
|
+
* @param {string} url - Base URL.
|
|
24
|
+
* @param {Record<string, string | number | boolean>} [params] - Key-value pairs to append.
|
|
25
|
+
* @returns {string} URL with appended query parameters.
|
|
26
|
+
*/
|
|
15
27
|
export function appendParams(url, params) {
|
|
16
28
|
if (!params || Object.keys(params).length === 0)
|
|
17
29
|
return url;
|
|
@@ -23,23 +35,45 @@ export function appendParams(url, params) {
|
|
|
23
35
|
}
|
|
24
36
|
return parsed.toString();
|
|
25
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Parses `raw` into a `URL` object.
|
|
40
|
+
*
|
|
41
|
+
* @param {string} raw - Absolute URL string to parse.
|
|
42
|
+
* @returns {URL} Parsed URL.
|
|
43
|
+
* @throws {TypeError} If `raw` is not a valid absolute URL.
|
|
44
|
+
*/
|
|
26
45
|
export function parseURL(raw) {
|
|
27
46
|
return new URL(raw);
|
|
28
47
|
}
|
|
29
48
|
/**
|
|
30
|
-
*
|
|
31
|
-
* `
|
|
49
|
+
* Returns the origin of `url` in `scheme://hostname:port` form. The port is
|
|
50
|
+
* always included explicitly, defaulting to `443` for `https:` and `80` for
|
|
51
|
+
* `http:`.
|
|
52
|
+
*
|
|
53
|
+
* @param {string} url - Absolute URL string.
|
|
54
|
+
* @returns {string} Origin string (e.g. `"https://example.com:443"`).
|
|
32
55
|
*/
|
|
33
56
|
export function originOf(url) {
|
|
34
57
|
const u = new URL(url);
|
|
35
58
|
const port = u.port || (u.protocol === 'https:' ? '443' : '80');
|
|
36
59
|
return `${u.protocol}//${u.hostname}:${port}`;
|
|
37
60
|
}
|
|
38
|
-
/**
|
|
61
|
+
/**
|
|
62
|
+
* Extracts the hostname from `url` for use as the TLS SNI server-name value.
|
|
63
|
+
*
|
|
64
|
+
* @param {string} url - Absolute URL string.
|
|
65
|
+
* @returns {string} Hostname without port (e.g. `"example.com"`).
|
|
66
|
+
*/
|
|
39
67
|
export function sniHost(url) {
|
|
40
68
|
return new URL(url).hostname;
|
|
41
69
|
}
|
|
42
|
-
/**
|
|
70
|
+
/**
|
|
71
|
+
* Extracts the host and port from `url`. The port defaults to `443` for
|
|
72
|
+
* `https:` and `80` for `http:` when not explicitly specified in the URL.
|
|
73
|
+
*
|
|
74
|
+
* @param {string} url - Absolute URL string.
|
|
75
|
+
* @returns {{ host: string; port: number }} Hostname and numeric port.
|
|
76
|
+
*/
|
|
43
77
|
export function hostPort(url) {
|
|
44
78
|
const u = new URL(url);
|
|
45
79
|
const defaultPort = u.protocol === 'https:' ? 443 : 80;
|
|
@@ -48,7 +82,13 @@ export function hostPort(url) {
|
|
|
48
82
|
port: u.port ? parseInt(u.port, 10) : defaultPort,
|
|
49
83
|
};
|
|
50
84
|
}
|
|
51
|
-
/**
|
|
85
|
+
/**
|
|
86
|
+
* Returns the path and query string of `url` suitable for use as the
|
|
87
|
+
* request-target in an HTTP/1.1 request line.
|
|
88
|
+
*
|
|
89
|
+
* @param {string} url - Absolute URL string.
|
|
90
|
+
* @returns {string} Path + query string (e.g. `"/search?q=hello"`).
|
|
91
|
+
*/
|
|
52
92
|
export function requestPath(url) {
|
|
53
93
|
const u = new URL(url);
|
|
54
94
|
return u.pathname + u.search;
|
package/dist/utils/url.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"url.js","sourceRoot":"","sources":["../../src/utils/url.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"url.js","sourceRoot":"","sources":["../../src/utils/url.ts"],"names":[],"mappings":"AACA;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CAAC,IAAwB,EAAE,QAAgB;IACnE,IAAI,CAAC,IAAI;QAAE,OAAO,QAAQ,CAAC;IAC3B,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,QAAQ,CAAC;IAClB,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAC1B,GAAW,EACX,MAAkD;IAElD,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC;IAE5D,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IAC5B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;YAAE,SAAS;QACpD,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,MAAM,CAAC,QAAQ,EAAE,CAAC;AAC3B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ,CAAC,GAAW;IAClC,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;AACtB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,QAAQ,CAAC,GAAW;IAClC,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IACvB,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAChE,OAAO,GAAG,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,QAAQ,IAAI,IAAI,EAAE,CAAC;AAChD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CAAC,GAAW;IACjC,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;AAC/B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ,CAAC,GAAW;IAClC,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IACvB,MAAM,WAAW,GAAG,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IACvD,OAAO;QACL,IAAI,EAAE,CAAC,CAAC,QAAQ;QAChB,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW;KAClD,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IACvB,OAAO,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,MAAM,CAAC;AAC/B,CAAC"}
|
package/dist/ws/client.d.ts
CHANGED
|
@@ -1,26 +1,40 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
1
2
|
/**
|
|
2
|
-
*
|
|
3
|
+
* Options for creating a {@link WebSocketClient} connection.
|
|
3
4
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* @typedef {Object} WebSocketOptions
|
|
6
|
+
* @property {string} [impersonate] - Browser profile name for fingerprint impersonation.
|
|
7
|
+
* @property {boolean} [stealth] - Use the stealth TLS engine for byte-level fingerprinting.
|
|
8
|
+
* @property {Record<string, string>} [headers] - Additional HTTP upgrade request headers.
|
|
9
|
+
* @property {string[]} [protocols] - Sub-protocol names to negotiate.
|
|
10
|
+
* @property {boolean} [insecure] - Skip TLS certificate validation for `wss:` connections.
|
|
11
|
+
* @property {number} [timeout] - Connection timeout in milliseconds.
|
|
7
12
|
*/
|
|
8
|
-
import { EventEmitter } from 'node:events';
|
|
9
13
|
export interface WebSocketOptions {
|
|
10
|
-
/** Browser profile name to impersonate. */
|
|
11
14
|
impersonate?: string;
|
|
12
|
-
/** Use the stealth TLS engine. */
|
|
13
15
|
stealth?: boolean;
|
|
14
|
-
/** Extra headers for the upgrade request. */
|
|
15
16
|
headers?: Record<string, string>;
|
|
16
|
-
/** WebSocket sub-protocols. */
|
|
17
17
|
protocols?: string[];
|
|
18
|
-
/** Skip TLS certificate verification. */
|
|
19
18
|
insecure?: boolean;
|
|
20
|
-
/** Connection timeout in milliseconds. */
|
|
21
19
|
timeout?: number;
|
|
22
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* WebSocket connection state.
|
|
23
|
+
*
|
|
24
|
+
* @typedef {'connecting' | 'open' | 'closing' | 'closed'} WebSocketState
|
|
25
|
+
*/
|
|
23
26
|
export type WebSocketState = 'connecting' | 'open' | 'closing' | 'closed';
|
|
27
|
+
/**
|
|
28
|
+
* Typed event map for {@link WebSocketClient}.
|
|
29
|
+
*
|
|
30
|
+
* @typedef {Object} WebSocketEvents
|
|
31
|
+
* @property {[]} open - Emitted when the connection is established.
|
|
32
|
+
* @property {[data: string | Buffer, isBinary: boolean]} message - Emitted for each incoming message.
|
|
33
|
+
* @property {[code: number, reason: string]} close - Emitted when the connection closes.
|
|
34
|
+
* @property {[error: Error]} error - Emitted on connection or protocol errors.
|
|
35
|
+
* @property {[data: Buffer]} ping - Emitted when a PING frame is received.
|
|
36
|
+
* @property {[data: Buffer]} pong - Emitted when a PONG frame is received.
|
|
37
|
+
*/
|
|
24
38
|
export interface WebSocketEvents {
|
|
25
39
|
open: [];
|
|
26
40
|
message: [data: string | Buffer, isBinary: boolean];
|
|
@@ -29,6 +43,17 @@ export interface WebSocketEvents {
|
|
|
29
43
|
ping: [data: Buffer];
|
|
30
44
|
pong: [data: Buffer];
|
|
31
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* WebSocket client with optional browser fingerprint impersonation. Emits
|
|
48
|
+
* typed lifecycle events (`open`, `message`, `close`, `error`, `ping`, `pong`).
|
|
49
|
+
* The connection is initiated asynchronously in the constructor; listen for
|
|
50
|
+
* the `'open'` event before sending frames.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* const ws = new WebSocketClient('wss://echo.example.com', { impersonate: 'chrome136' });
|
|
54
|
+
* ws.on('open', () => ws.sendText('hello'));
|
|
55
|
+
* ws.on('message', (data) => console.log(data));
|
|
56
|
+
*/
|
|
32
57
|
export declare class WebSocketClient extends EventEmitter {
|
|
33
58
|
state: WebSocketState;
|
|
34
59
|
protocol: string;
|
|
@@ -37,21 +62,40 @@ export declare class WebSocketClient extends EventEmitter {
|
|
|
37
62
|
private parser;
|
|
38
63
|
private fragments;
|
|
39
64
|
private fragmentOpcode;
|
|
65
|
+
/**
|
|
66
|
+
* Creates a new WebSocketClient and begins connecting to `url`.
|
|
67
|
+
*
|
|
68
|
+
* @param {string} url - WebSocket URL (`ws:` or `wss:`).
|
|
69
|
+
* @param {WebSocketOptions} [options={}] - Connection and impersonation options.
|
|
70
|
+
*/
|
|
40
71
|
constructor(url: string, options?: WebSocketOptions);
|
|
41
72
|
/**
|
|
42
|
-
*
|
|
73
|
+
* Sends a UTF-8 text message.
|
|
74
|
+
*
|
|
75
|
+
* @param {string} data - Text to send.
|
|
76
|
+
* @throws {NLcURLError} If the WebSocket is not in the `'open'` state.
|
|
43
77
|
*/
|
|
44
78
|
sendText(data: string): void;
|
|
45
79
|
/**
|
|
46
|
-
*
|
|
80
|
+
* Sends a binary message.
|
|
81
|
+
*
|
|
82
|
+
* @param {Buffer} data - Binary data to send.
|
|
83
|
+
* @throws {NLcURLError} If the WebSocket is not in the `'open'` state.
|
|
47
84
|
*/
|
|
48
85
|
sendBinary(data: Buffer): void;
|
|
49
86
|
/**
|
|
50
|
-
*
|
|
87
|
+
* Sends a PING control frame.
|
|
88
|
+
*
|
|
89
|
+
* @param {Buffer} [data=Buffer.alloc(0)] - Optional ping payload (up to 125 bytes).
|
|
90
|
+
* @throws {NLcURLError} If the WebSocket is not in the `'open'` state.
|
|
51
91
|
*/
|
|
52
92
|
ping(data?: Buffer): void;
|
|
53
93
|
/**
|
|
54
|
-
*
|
|
94
|
+
* Initiates a graceful close handshake by sending a CLOSE frame with the
|
|
95
|
+
* given status code and reason. Does nothing if the connection is not open.
|
|
96
|
+
*
|
|
97
|
+
* @param {number} [code=1000] - WebSocket close status code.
|
|
98
|
+
* @param {string} [reason=''] - Human-readable close reason (UTF-8, max 123 bytes).
|
|
55
99
|
*/
|
|
56
100
|
close(code?: number, reason?: string): void;
|
|
57
101
|
private assertOpen;
|
package/dist/ws/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/ws/client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/ws/client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAiB3C;;;;;;;;;;GAUG;AACH,MAAM,WAAW,gBAAgB;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE1E;;;;;;;;;;GAUG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,EAAE,CAAC;IACT,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IACpD,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACtB,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACrB,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;CACtB;AAED;;;;;;;;;;GAUG;AACH,qBAAa,eAAgB,SAAQ,YAAY;IACxC,KAAK,EAAE,cAAc,CAAgB;IACrC,QAAQ,SAAM;IACrB,SAAgB,GAAG,EAAE,MAAM,CAAC;IAE5B,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,SAAS,CAAgB;IACjC,OAAO,CAAC,cAAc,CAAuB;IAE7C;;;;;OAKG;gBACS,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB;IAUvD;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAM5B;;;;;OAKG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAK9B;;;;;OAKG;IACH,IAAI,CAAC,IAAI,GAAE,MAAwB,GAAG,IAAI;IAK1C;;;;;;OAMG;IACH,KAAK,CAAC,IAAI,SAAO,EAAE,MAAM,SAAK,GAAG,IAAI;IAYrC,OAAO,CAAC,UAAU;YAMJ,OAAO;IAgErB,OAAO,CAAC,cAAc;IAyGtB,OAAO,CAAC,MAAM;IASd,OAAO,CAAC,WAAW;CAwDpB"}
|
package/dist/ws/client.js
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* WebSocket client with TLS fingerprint impersonation.
|
|
3
|
-
*
|
|
4
|
-
* Implements the WebSocket protocol (RFC 6455) over impersonated
|
|
5
|
-
* TLS connections. Supports text and binary messages, ping/pong,
|
|
6
|
-
* and graceful close.
|
|
7
|
-
*/
|
|
8
1
|
import { EventEmitter } from 'node:events';
|
|
9
2
|
import { NodeTLSEngine } from '../tls/node-engine.js';
|
|
10
3
|
import { StealthTLSEngine } from '../tls/stealth/engine.js';
|
|
11
4
|
import { getProfile } from '../fingerprints/database.js';
|
|
12
5
|
import { NLcURLError, ConnectionError } from '../core/errors.js';
|
|
13
6
|
import { encodeFrame, FrameParser, Opcode, generateWebSocketKey, computeAcceptKey, } from './frame.js';
|
|
7
|
+
/**
|
|
8
|
+
* WebSocket client with optional browser fingerprint impersonation. Emits
|
|
9
|
+
* typed lifecycle events (`open`, `message`, `close`, `error`, `ping`, `pong`).
|
|
10
|
+
* The connection is initiated asynchronously in the constructor; listen for
|
|
11
|
+
* the `'open'` event before sending frames.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* const ws = new WebSocketClient('wss://echo.example.com', { impersonate: 'chrome136' });
|
|
15
|
+
* ws.on('open', () => ws.sendText('hello'));
|
|
16
|
+
* ws.on('message', (data) => console.log(data));
|
|
17
|
+
*/
|
|
14
18
|
export class WebSocketClient extends EventEmitter {
|
|
15
19
|
state = 'connecting';
|
|
16
20
|
protocol = '';
|
|
@@ -19,17 +23,25 @@ export class WebSocketClient extends EventEmitter {
|
|
|
19
23
|
parser = new FrameParser();
|
|
20
24
|
fragments = [];
|
|
21
25
|
fragmentOpcode = Opcode.TEXT;
|
|
26
|
+
/**
|
|
27
|
+
* Creates a new WebSocketClient and begins connecting to `url`.
|
|
28
|
+
*
|
|
29
|
+
* @param {string} url - WebSocket URL (`ws:` or `wss:`).
|
|
30
|
+
* @param {WebSocketOptions} [options={}] - Connection and impersonation options.
|
|
31
|
+
*/
|
|
22
32
|
constructor(url, options = {}) {
|
|
23
33
|
super();
|
|
24
34
|
this.url = url;
|
|
25
|
-
// Start connection asynchronously
|
|
26
35
|
this.connect(url, options).catch((err) => {
|
|
27
36
|
this.state = 'closed';
|
|
28
37
|
this.emit('error', err);
|
|
29
38
|
});
|
|
30
39
|
}
|
|
31
40
|
/**
|
|
32
|
-
*
|
|
41
|
+
* Sends a UTF-8 text message.
|
|
42
|
+
*
|
|
43
|
+
* @param {string} data - Text to send.
|
|
44
|
+
* @throws {NLcURLError} If the WebSocket is not in the `'open'` state.
|
|
33
45
|
*/
|
|
34
46
|
sendText(data) {
|
|
35
47
|
this.assertOpen();
|
|
@@ -37,21 +49,31 @@ export class WebSocketClient extends EventEmitter {
|
|
|
37
49
|
this.socket.write(encodeFrame(Opcode.TEXT, payload));
|
|
38
50
|
}
|
|
39
51
|
/**
|
|
40
|
-
*
|
|
52
|
+
* Sends a binary message.
|
|
53
|
+
*
|
|
54
|
+
* @param {Buffer} data - Binary data to send.
|
|
55
|
+
* @throws {NLcURLError} If the WebSocket is not in the `'open'` state.
|
|
41
56
|
*/
|
|
42
57
|
sendBinary(data) {
|
|
43
58
|
this.assertOpen();
|
|
44
59
|
this.socket.write(encodeFrame(Opcode.BINARY, data));
|
|
45
60
|
}
|
|
46
61
|
/**
|
|
47
|
-
*
|
|
62
|
+
* Sends a PING control frame.
|
|
63
|
+
*
|
|
64
|
+
* @param {Buffer} [data=Buffer.alloc(0)] - Optional ping payload (up to 125 bytes).
|
|
65
|
+
* @throws {NLcURLError} If the WebSocket is not in the `'open'` state.
|
|
48
66
|
*/
|
|
49
67
|
ping(data = Buffer.alloc(0)) {
|
|
50
68
|
this.assertOpen();
|
|
51
69
|
this.socket.write(encodeFrame(Opcode.PING, data));
|
|
52
70
|
}
|
|
53
71
|
/**
|
|
54
|
-
*
|
|
72
|
+
* Initiates a graceful close handshake by sending a CLOSE frame with the
|
|
73
|
+
* given status code and reason. Does nothing if the connection is not open.
|
|
74
|
+
*
|
|
75
|
+
* @param {number} [code=1000] - WebSocket close status code.
|
|
76
|
+
* @param {string} [reason=''] - Human-readable close reason (UTF-8, max 123 bytes).
|
|
55
77
|
*/
|
|
56
78
|
close(code = 1000, reason = '') {
|
|
57
79
|
if (this.state !== 'open')
|
|
@@ -63,7 +85,6 @@ export class WebSocketClient extends EventEmitter {
|
|
|
63
85
|
reasonBuf.copy(payload, 2);
|
|
64
86
|
this.socket.write(encodeFrame(Opcode.CLOSE, payload));
|
|
65
87
|
}
|
|
66
|
-
// ---- Internal ----
|
|
67
88
|
assertOpen() {
|
|
68
89
|
if (this.state !== 'open') {
|
|
69
90
|
throw new NLcURLError('WebSocket is not open', 'ERR_WS_NOT_OPEN');
|
|
@@ -76,13 +97,11 @@ export class WebSocketClient extends EventEmitter {
|
|
|
76
97
|
? parseInt(parsed.port, 10)
|
|
77
98
|
: isSecure ? 443 : 80;
|
|
78
99
|
const host = parsed.hostname;
|
|
79
|
-
// Resolve profile
|
|
80
100
|
const profile = options.impersonate
|
|
81
101
|
? getProfile(options.impersonate) ?? undefined
|
|
82
102
|
: undefined;
|
|
83
103
|
let transport;
|
|
84
104
|
if (isSecure) {
|
|
85
|
-
// TLS connection with impersonation
|
|
86
105
|
const engine = options.stealth
|
|
87
106
|
? new StealthTLSEngine()
|
|
88
107
|
: new NodeTLSEngine();
|
|
@@ -98,7 +117,6 @@ export class WebSocketClient extends EventEmitter {
|
|
|
98
117
|
transport = tlsSocket;
|
|
99
118
|
}
|
|
100
119
|
else {
|
|
101
|
-
// Plain TCP (ws://)
|
|
102
120
|
const net = await import('node:net');
|
|
103
121
|
transport = await new Promise((resolve, reject) => {
|
|
104
122
|
const sock = net.createConnection({ host, port }, () => resolve(sock));
|
|
@@ -112,12 +130,9 @@ export class WebSocketClient extends EventEmitter {
|
|
|
112
130
|
});
|
|
113
131
|
}
|
|
114
132
|
this.socket = transport;
|
|
115
|
-
// Perform HTTP upgrade handshake
|
|
116
133
|
await this.performUpgrade(transport, parsed, options);
|
|
117
|
-
// Now in open state
|
|
118
134
|
this.state = 'open';
|
|
119
135
|
this.emit('open');
|
|
120
|
-
// Start reading frames
|
|
121
136
|
transport.on('data', (chunk) => this.onData(chunk));
|
|
122
137
|
transport.on('error', (err) => {
|
|
123
138
|
this.state = 'closed';
|
|
@@ -150,7 +165,6 @@ export class WebSocketClient extends EventEmitter {
|
|
|
150
165
|
}
|
|
151
166
|
request += `\r\n`;
|
|
152
167
|
socket.write(request);
|
|
153
|
-
// Read the upgrade response
|
|
154
168
|
let responseData = Buffer.alloc(0);
|
|
155
169
|
const expectedAccept = computeAcceptKey(key);
|
|
156
170
|
const onData = (chunk) => {
|
|
@@ -158,7 +172,6 @@ export class WebSocketClient extends EventEmitter {
|
|
|
158
172
|
const text = responseData.toString('utf8');
|
|
159
173
|
const headerEnd = text.indexOf('\r\n\r\n');
|
|
160
174
|
if (headerEnd === -1) {
|
|
161
|
-
// Limit response header size
|
|
162
175
|
if (responseData.length > 16384) {
|
|
163
176
|
cleanup();
|
|
164
177
|
reject(new NLcURLError('WebSocket upgrade response too large', 'ERR_WS_UPGRADE'));
|
|
@@ -175,7 +188,6 @@ export class WebSocketClient extends EventEmitter {
|
|
|
175
188
|
if (!statusMatch || statusMatch[1] !== '101') {
|
|
176
189
|
return reject(new NLcURLError(`WebSocket upgrade failed: ${statusLine}`, 'ERR_WS_UPGRADE'));
|
|
177
190
|
}
|
|
178
|
-
// Validate Sec-WebSocket-Accept
|
|
179
191
|
const headers = new Map();
|
|
180
192
|
for (const line of headerLines) {
|
|
181
193
|
const colonIdx = line.indexOf(':');
|
|
@@ -188,7 +200,6 @@ export class WebSocketClient extends EventEmitter {
|
|
|
188
200
|
return reject(new NLcURLError('Invalid Sec-WebSocket-Accept header', 'ERR_WS_UPGRADE'));
|
|
189
201
|
}
|
|
190
202
|
this.protocol = headers.get('sec-websocket-protocol') ?? '';
|
|
191
|
-
// Push any remaining data after headers into frame parser
|
|
192
203
|
const remaining = responseData.subarray(headerEnd + 4);
|
|
193
204
|
if (remaining.length > 0) {
|
|
194
205
|
this.parser.push(remaining);
|
|
@@ -219,13 +230,11 @@ export class WebSocketClient extends EventEmitter {
|
|
|
219
230
|
case Opcode.TEXT:
|
|
220
231
|
case Opcode.BINARY:
|
|
221
232
|
if (frame.fin) {
|
|
222
|
-
// Complete message
|
|
223
233
|
const isBinary = frame.opcode === Opcode.BINARY;
|
|
224
234
|
const data = isBinary ? frame.payload : frame.payload.toString('utf8');
|
|
225
235
|
this.emit('message', data, isBinary);
|
|
226
236
|
}
|
|
227
237
|
else {
|
|
228
|
-
// Start of fragmented message
|
|
229
238
|
this.fragmentOpcode = frame.opcode;
|
|
230
239
|
this.fragments = [frame.payload];
|
|
231
240
|
}
|
|
@@ -248,7 +257,6 @@ export class WebSocketClient extends EventEmitter {
|
|
|
248
257
|
reason = frame.payload.subarray(2).toString('utf8');
|
|
249
258
|
}
|
|
250
259
|
if (this.state === 'open') {
|
|
251
|
-
// Server-initiated close, echo it back
|
|
252
260
|
this.state = 'closing';
|
|
253
261
|
this.socket.write(encodeFrame(Opcode.CLOSE, frame.payload));
|
|
254
262
|
}
|
|
@@ -259,7 +267,6 @@ export class WebSocketClient extends EventEmitter {
|
|
|
259
267
|
}
|
|
260
268
|
case Opcode.PING:
|
|
261
269
|
this.emit('ping', frame.payload);
|
|
262
|
-
// Auto-respond with pong
|
|
263
270
|
if (this.state === 'open') {
|
|
264
271
|
this.socket.write(encodeFrame(Opcode.PONG, frame.payload));
|
|
265
272
|
}
|
package/dist/ws/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/ws/client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/ws/client.ts"],"names":[],"mappings":"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"}
|