nlcurl 0.1.0 → 0.3.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.
Files changed (197) hide show
  1. package/README.md +5 -13
  2. package/dist/cli/args.d.ts +37 -5
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +6 -17
  5. package/dist/cli/args.js.map +1 -1
  6. package/dist/cli/index.d.ts +3 -3
  7. package/dist/cli/index.js +25 -10
  8. package/dist/cli/index.js.map +1 -1
  9. package/dist/cli/output.d.ts +24 -7
  10. package/dist/cli/output.d.ts.map +1 -1
  11. package/dist/cli/output.js +24 -12
  12. package/dist/cli/output.js.map +1 -1
  13. package/dist/cookies/jar.d.ts +45 -13
  14. package/dist/cookies/jar.d.ts.map +1 -1
  15. package/dist/cookies/jar.js +88 -29
  16. package/dist/cookies/jar.js.map +1 -1
  17. package/dist/cookies/parser.d.ts +25 -3
  18. package/dist/cookies/parser.d.ts.map +1 -1
  19. package/dist/cookies/parser.js +12 -7
  20. package/dist/cookies/parser.js.map +1 -1
  21. package/dist/core/client.d.ts +49 -33
  22. package/dist/core/client.d.ts.map +1 -1
  23. package/dist/core/client.js +65 -38
  24. package/dist/core/client.js.map +1 -1
  25. package/dist/core/errors.d.ts +94 -6
  26. package/dist/core/errors.d.ts.map +1 -1
  27. package/dist/core/errors.js +95 -6
  28. package/dist/core/errors.js.map +1 -1
  29. package/dist/core/request.d.ts +99 -32
  30. package/dist/core/request.d.ts.map +1 -1
  31. package/dist/core/request.js +0 -3
  32. package/dist/core/request.js.map +1 -1
  33. package/dist/core/response.d.ts +92 -8
  34. package/dist/core/response.d.ts.map +1 -1
  35. package/dist/core/response.js +92 -7
  36. package/dist/core/response.js.map +1 -1
  37. package/dist/core/session.d.ts +109 -14
  38. package/dist/core/session.d.ts.map +1 -1
  39. package/dist/core/session.js +143 -49
  40. package/dist/core/session.js.map +1 -1
  41. package/dist/fingerprints/akamai.d.ts +11 -11
  42. package/dist/fingerprints/akamai.d.ts.map +1 -1
  43. package/dist/fingerprints/akamai.js +10 -14
  44. package/dist/fingerprints/akamai.js.map +1 -1
  45. package/dist/fingerprints/database.d.ts +14 -15
  46. package/dist/fingerprints/database.d.ts.map +1 -1
  47. package/dist/fingerprints/database.js +14 -19
  48. package/dist/fingerprints/database.js.map +1 -1
  49. package/dist/fingerprints/extensions.d.ts +121 -27
  50. package/dist/fingerprints/extensions.d.ts.map +1 -1
  51. package/dist/fingerprints/extensions.js +132 -49
  52. package/dist/fingerprints/extensions.js.map +1 -1
  53. package/dist/fingerprints/ja3.d.ts +34 -18
  54. package/dist/fingerprints/ja3.d.ts.map +1 -1
  55. package/dist/fingerprints/ja3.js +34 -18
  56. package/dist/fingerprints/ja3.js.map +1 -1
  57. package/dist/fingerprints/profiles/chrome.d.ts +21 -10
  58. package/dist/fingerprints/profiles/chrome.d.ts.map +1 -1
  59. package/dist/fingerprints/profiles/chrome.js +25 -22
  60. package/dist/fingerprints/profiles/chrome.js.map +1 -1
  61. package/dist/fingerprints/profiles/edge.d.ts +10 -7
  62. package/dist/fingerprints/profiles/edge.d.ts.map +1 -1
  63. package/dist/fingerprints/profiles/edge.js +10 -10
  64. package/dist/fingerprints/profiles/edge.js.map +1 -1
  65. package/dist/fingerprints/profiles/firefox.d.ts +11 -3
  66. package/dist/fingerprints/profiles/firefox.d.ts.map +1 -1
  67. package/dist/fingerprints/profiles/firefox.js +15 -14
  68. package/dist/fingerprints/profiles/firefox.js.map +1 -1
  69. package/dist/fingerprints/profiles/safari.d.ts +14 -3
  70. package/dist/fingerprints/profiles/safari.d.ts.map +1 -1
  71. package/dist/fingerprints/profiles/safari.js +16 -13
  72. package/dist/fingerprints/profiles/safari.js.map +1 -1
  73. package/dist/fingerprints/profiles/tor.d.ts +8 -7
  74. package/dist/fingerprints/profiles/tor.d.ts.map +1 -1
  75. package/dist/fingerprints/profiles/tor.js +8 -14
  76. package/dist/fingerprints/profiles/tor.js.map +1 -1
  77. package/dist/fingerprints/types.d.ts +70 -47
  78. package/dist/fingerprints/types.d.ts.map +1 -1
  79. package/dist/fingerprints/types.js +0 -7
  80. package/dist/fingerprints/types.js.map +1 -1
  81. package/dist/http/h1/client.d.ts +30 -9
  82. package/dist/http/h1/client.d.ts.map +1 -1
  83. package/dist/http/h1/client.js +153 -20
  84. package/dist/http/h1/client.js.map +1 -1
  85. package/dist/http/h1/encoder.d.ts +9 -6
  86. package/dist/http/h1/encoder.d.ts.map +1 -1
  87. package/dist/http/h1/encoder.js +14 -13
  88. package/dist/http/h1/encoder.js.map +1 -1
  89. package/dist/http/h1/parser.d.ts +68 -14
  90. package/dist/http/h1/parser.d.ts.map +1 -1
  91. package/dist/http/h1/parser.js +92 -37
  92. package/dist/http/h1/parser.js.map +1 -1
  93. package/dist/http/h2/client.d.ts +87 -14
  94. package/dist/http/h2/client.d.ts.map +1 -1
  95. package/dist/http/h2/client.js +496 -74
  96. package/dist/http/h2/client.js.map +1 -1
  97. package/dist/http/h2/frames.d.ts +103 -6
  98. package/dist/http/h2/frames.d.ts.map +1 -1
  99. package/dist/http/h2/frames.js +96 -17
  100. package/dist/http/h2/frames.js.map +1 -1
  101. package/dist/http/h2/hpack.d.ts +40 -5
  102. package/dist/http/h2/hpack.d.ts.map +1 -1
  103. package/dist/http/h2/hpack.js +50 -36
  104. package/dist/http/h2/hpack.js.map +1 -1
  105. package/dist/http/negotiator.d.ts +36 -12
  106. package/dist/http/negotiator.d.ts.map +1 -1
  107. package/dist/http/negotiator.js +96 -24
  108. package/dist/http/negotiator.js.map +1 -1
  109. package/dist/http/pool.d.ts +66 -17
  110. package/dist/http/pool.d.ts.map +1 -1
  111. package/dist/http/pool.js +47 -20
  112. package/dist/http/pool.js.map +1 -1
  113. package/dist/index.d.ts +2 -3
  114. package/dist/index.d.ts.map +1 -1
  115. package/dist/index.js +0 -13
  116. package/dist/index.js.map +1 -1
  117. package/dist/middleware/interceptor.d.ts +40 -8
  118. package/dist/middleware/interceptor.d.ts.map +1 -1
  119. package/dist/middleware/interceptor.js +28 -6
  120. package/dist/middleware/interceptor.js.map +1 -1
  121. package/dist/middleware/rate-limiter.d.ts +18 -5
  122. package/dist/middleware/rate-limiter.d.ts.map +1 -1
  123. package/dist/middleware/rate-limiter.js +12 -7
  124. package/dist/middleware/rate-limiter.js.map +1 -1
  125. package/dist/middleware/retry.d.ts +17 -5
  126. package/dist/middleware/retry.d.ts.map +1 -1
  127. package/dist/middleware/retry.js +13 -11
  128. package/dist/middleware/retry.js.map +1 -1
  129. package/dist/proxy/http-proxy.d.ts +17 -9
  130. package/dist/proxy/http-proxy.d.ts.map +1 -1
  131. package/dist/proxy/http-proxy.js +9 -13
  132. package/dist/proxy/http-proxy.js.map +1 -1
  133. package/dist/proxy/socks.d.ts +20 -9
  134. package/dist/proxy/socks.d.ts.map +1 -1
  135. package/dist/proxy/socks.js +20 -31
  136. package/dist/proxy/socks.js.map +1 -1
  137. package/dist/tls/constants.d.ts +74 -4
  138. package/dist/tls/constants.d.ts.map +1 -1
  139. package/dist/tls/constants.js +75 -21
  140. package/dist/tls/constants.js.map +1 -1
  141. package/dist/tls/node-engine.d.ts +17 -16
  142. package/dist/tls/node-engine.d.ts.map +1 -1
  143. package/dist/tls/node-engine.js +20 -27
  144. package/dist/tls/node-engine.js.map +1 -1
  145. package/dist/tls/stealth/client-hello.d.ts +32 -16
  146. package/dist/tls/stealth/client-hello.d.ts.map +1 -1
  147. package/dist/tls/stealth/client-hello.js +13 -37
  148. package/dist/tls/stealth/client-hello.js.map +1 -1
  149. package/dist/tls/stealth/engine.d.ts +18 -10
  150. package/dist/tls/stealth/engine.d.ts.map +1 -1
  151. package/dist/tls/stealth/engine.js +55 -40
  152. package/dist/tls/stealth/engine.js.map +1 -1
  153. package/dist/tls/stealth/handshake.d.ts +31 -17
  154. package/dist/tls/stealth/handshake.d.ts.map +1 -1
  155. package/dist/tls/stealth/handshake.js +173 -74
  156. package/dist/tls/stealth/handshake.js.map +1 -1
  157. package/dist/tls/stealth/key-schedule.d.ts +90 -32
  158. package/dist/tls/stealth/key-schedule.d.ts.map +1 -1
  159. package/dist/tls/stealth/key-schedule.js +80 -46
  160. package/dist/tls/stealth/key-schedule.js.map +1 -1
  161. package/dist/tls/stealth/record-layer.d.ts +76 -25
  162. package/dist/tls/stealth/record-layer.d.ts.map +1 -1
  163. package/dist/tls/stealth/record-layer.js +66 -36
  164. package/dist/tls/stealth/record-layer.js.map +1 -1
  165. package/dist/tls/types.d.ts +33 -25
  166. package/dist/tls/types.d.ts.map +1 -1
  167. package/dist/tls/types.js +0 -4
  168. package/dist/tls/types.js.map +1 -1
  169. package/dist/utils/buffer-reader.d.ts +99 -7
  170. package/dist/utils/buffer-reader.d.ts.map +1 -1
  171. package/dist/utils/buffer-reader.js +99 -7
  172. package/dist/utils/buffer-reader.js.map +1 -1
  173. package/dist/utils/buffer-writer.d.ts +99 -10
  174. package/dist/utils/buffer-writer.d.ts.map +1 -1
  175. package/dist/utils/buffer-writer.js +101 -12
  176. package/dist/utils/buffer-writer.js.map +1 -1
  177. package/dist/utils/encoding.d.ts +33 -8
  178. package/dist/utils/encoding.d.ts.map +1 -1
  179. package/dist/utils/encoding.js +58 -13
  180. package/dist/utils/encoding.js.map +1 -1
  181. package/dist/utils/logger.d.ts +61 -2
  182. package/dist/utils/logger.d.ts.map +1 -1
  183. package/dist/utils/logger.js +52 -4
  184. package/dist/utils/logger.js.map +1 -1
  185. package/dist/utils/url.d.ts +47 -7
  186. package/dist/utils/url.d.ts.map +1 -1
  187. package/dist/utils/url.js +47 -7
  188. package/dist/utils/url.js.map +1 -1
  189. package/dist/ws/client.d.ts +60 -15
  190. package/dist/ws/client.d.ts.map +1 -1
  191. package/dist/ws/client.js +38 -27
  192. package/dist/ws/client.js.map +1 -1
  193. package/dist/ws/frame.d.ts +43 -9
  194. package/dist/ws/frame.d.ts.map +1 -1
  195. package/dist/ws/frame.js +35 -19
  196. package/dist/ws/frame.js.map +1 -1
  197. package/package.json +4 -4
@@ -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
- /** Silent logger that discards all output. */
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
  }
@@ -1 +1 @@
1
- {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,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;AASF,MAAM,OAAO,aAAa;IAChB,KAAK,CAAS;IAEtB,YAAY,QAAkB,MAAM;QAClC,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC;IAED,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,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,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,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,8CAA8C;AAC9C,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,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,QAAQ,GAAG,MAAM,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,QAAQ,CAAC;AAClB,CAAC"}
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"}
@@ -1,22 +1,62 @@
1
1
  /**
2
- * URL utilities -- parsing, query string encoding, base URL joining.
3
- * Zero dependencies; uses the built-in WHATWG URL API.
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
- * Extract the origin key used for connection pooling:
10
- * `protocol://host:port`
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
- /** Return the hostname suitable for the TLS SNI extension. */
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
- /** Return the host:port string for TCP connection. */
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
- /** Return the request path including query string. */
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
@@ -1 +1 @@
1
- {"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../../src/utils/url.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAO7E;AAED,wBAAgB,YAAY,CAC1B,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,GACjD,MAAM,CASR;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAEzC;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAI5C;AAED,8DAA8D;AAC9D,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE3C;AAED,sDAAsD;AACtD,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAOpE;AAED,sDAAsD;AACtD,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAG/C"}
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
- * URL utilities -- parsing, query string encoding, base URL joining.
3
- * Zero dependencies; uses the built-in WHATWG URL API.
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
- * Extract the origin key used for connection pooling:
31
- * `protocol://host:port`
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
- /** Return the hostname suitable for the TLS SNI extension. */
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
- /** Return the host:port string for TCP connection. */
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
- /** Return the request path including query string. */
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;
@@ -1 +1 @@
1
- {"version":3,"file":"url.js","sourceRoot":"","sources":["../../src/utils/url.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,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,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,MAAM,UAAU,QAAQ,CAAC,GAAW;IAClC,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;AACtB,CAAC;AAED;;;GAGG;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,8DAA8D;AAC9D,MAAM,UAAU,OAAO,CAAC,GAAW;IACjC,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;AAC/B,CAAC;AAED,sDAAsD;AACtD,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,sDAAsD;AACtD,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"}
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"}
@@ -1,26 +1,40 @@
1
+ import { EventEmitter } from 'node:events';
1
2
  /**
2
- * WebSocket client with TLS fingerprint impersonation.
3
+ * Options for creating a {@link WebSocketClient} connection.
3
4
  *
4
- * Implements the WebSocket protocol (RFC 6455) over impersonated
5
- * TLS connections. Supports text and binary messages, ping/pong,
6
- * and graceful close.
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,27 +62,47 @@ 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
- * Send a text message.
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
- * Send a binary message.
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
- * Send a ping frame.
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
- * Initiate a graceful close handshake.
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;
58
102
  private connect;
59
103
  private performUpgrade;
60
104
  private onData;
105
+ private drainBufferedFrames;
61
106
  private handleFrame;
62
107
  }
63
108
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/ws/client.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAiB3C,MAAM,WAAW,gBAAgB;IAC/B,2CAA2C;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kCAAkC;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,+BAA+B;IAC/B,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,0CAA0C;IAC1C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE1E,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,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;gBAEjC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB;IAWvD;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAM5B;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAK9B;;OAEG;IACH,IAAI,CAAC,IAAI,GAAE,MAAwB,GAAG,IAAI;IAK1C;;OAEG;IACH,KAAK,CAAC,IAAI,SAAO,EAAE,MAAM,SAAK,GAAG,IAAI;IAcrC,OAAO,CAAC,UAAU;YAMJ,OAAO;IAsErB,OAAO,CAAC,cAAc;IA6GtB,OAAO,CAAC,MAAM;IASd,OAAO,CAAC,WAAW;CA4DpB"}
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;IAkErB,OAAO,CAAC,cAAc;IAyGtB,OAAO,CAAC,MAAM;IAKd,OAAO,CAAC,mBAAmB;IAO3B,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
- * Send a text message.
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
- * Send a binary message.
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
- * Send a ping frame.
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
- * Initiate a graceful close handshake.
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';
@@ -129,6 +144,7 @@ export class WebSocketClient extends EventEmitter {
129
144
  this.emit('close', 1006, 'Connection lost');
130
145
  }
131
146
  });
147
+ this.drainBufferedFrames();
132
148
  }
133
149
  performUpgrade(socket, url, options) {
134
150
  return new Promise((resolve, reject) => {
@@ -150,7 +166,6 @@ export class WebSocketClient extends EventEmitter {
150
166
  }
151
167
  request += `\r\n`;
152
168
  socket.write(request);
153
- // Read the upgrade response
154
169
  let responseData = Buffer.alloc(0);
155
170
  const expectedAccept = computeAcceptKey(key);
156
171
  const onData = (chunk) => {
@@ -158,7 +173,6 @@ export class WebSocketClient extends EventEmitter {
158
173
  const text = responseData.toString('utf8');
159
174
  const headerEnd = text.indexOf('\r\n\r\n');
160
175
  if (headerEnd === -1) {
161
- // Limit response header size
162
176
  if (responseData.length > 16384) {
163
177
  cleanup();
164
178
  reject(new NLcURLError('WebSocket upgrade response too large', 'ERR_WS_UPGRADE'));
@@ -175,7 +189,6 @@ export class WebSocketClient extends EventEmitter {
175
189
  if (!statusMatch || statusMatch[1] !== '101') {
176
190
  return reject(new NLcURLError(`WebSocket upgrade failed: ${statusLine}`, 'ERR_WS_UPGRADE'));
177
191
  }
178
- // Validate Sec-WebSocket-Accept
179
192
  const headers = new Map();
180
193
  for (const line of headerLines) {
181
194
  const colonIdx = line.indexOf(':');
@@ -188,7 +201,6 @@ export class WebSocketClient extends EventEmitter {
188
201
  return reject(new NLcURLError('Invalid Sec-WebSocket-Accept header', 'ERR_WS_UPGRADE'));
189
202
  }
190
203
  this.protocol = headers.get('sec-websocket-protocol') ?? '';
191
- // Push any remaining data after headers into frame parser
192
204
  const remaining = responseData.subarray(headerEnd + 4);
193
205
  if (remaining.length > 0) {
194
206
  this.parser.push(remaining);
@@ -209,6 +221,9 @@ export class WebSocketClient extends EventEmitter {
209
221
  }
210
222
  onData(chunk) {
211
223
  this.parser.push(chunk);
224
+ this.drainBufferedFrames();
225
+ }
226
+ drainBufferedFrames() {
212
227
  let frame;
213
228
  while ((frame = this.parser.pull()) !== null) {
214
229
  this.handleFrame(frame);
@@ -219,13 +234,11 @@ export class WebSocketClient extends EventEmitter {
219
234
  case Opcode.TEXT:
220
235
  case Opcode.BINARY:
221
236
  if (frame.fin) {
222
- // Complete message
223
237
  const isBinary = frame.opcode === Opcode.BINARY;
224
238
  const data = isBinary ? frame.payload : frame.payload.toString('utf8');
225
239
  this.emit('message', data, isBinary);
226
240
  }
227
241
  else {
228
- // Start of fragmented message
229
242
  this.fragmentOpcode = frame.opcode;
230
243
  this.fragments = [frame.payload];
231
244
  }
@@ -248,7 +261,6 @@ export class WebSocketClient extends EventEmitter {
248
261
  reason = frame.payload.subarray(2).toString('utf8');
249
262
  }
250
263
  if (this.state === 'open') {
251
- // Server-initiated close, echo it back
252
264
  this.state = 'closing';
253
265
  this.socket.write(encodeFrame(Opcode.CLOSE, frame.payload));
254
266
  }
@@ -259,7 +271,6 @@ export class WebSocketClient extends EventEmitter {
259
271
  }
260
272
  case Opcode.PING:
261
273
  this.emit('ping', frame.payload);
262
- // Auto-respond with pong
263
274
  if (this.state === 'open') {
264
275
  this.socket.write(encodeFrame(Opcode.PONG, frame.payload));
265
276
  }