specters 3.0.0 → 3.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 CHANGED
@@ -10,6 +10,8 @@ Node.js bindings for Specter, a high-performance async HTTP client with TLS, HTT
10
10
  - Cookie store and shared cookie jar support across HTTP and WebSocket handshakes
11
11
  - Granular connect, TTFB, read/write idle, total, pool, and WebSocket handshake timeouts
12
12
 
13
+ Supported Chrome profiles are `FingerprintProfile.Chrome142` through `FingerprintProfile.Chrome148`; examples use `Chrome148`, the latest implemented profile.
14
+
13
15
  ## Installation
14
16
 
15
17
  ```bash
@@ -22,7 +24,7 @@ npm install specters
22
24
  const { clientBuilder, FingerprintProfile } = require('specters');
23
25
 
24
26
  const client = clientBuilder()
25
- .fingerprint(FingerprintProfile.Chrome142)
27
+ .fingerprint(FingerprintProfile.Chrome148)
26
28
  .cookieStore(true)
27
29
  .build();
28
30
 
package/index.d.ts CHANGED
@@ -4,6 +4,8 @@ export enum FingerprintProfile {
4
4
  Chrome144,
5
5
  Chrome145,
6
6
  Chrome146,
7
+ Chrome147,
8
+ Chrome148,
7
9
  Firefox133,
8
10
  None,
9
11
  }
@@ -55,7 +57,9 @@ export interface H3TunnelEvent {
55
57
  export class RequestBuilder {
56
58
  header(key: string, value: string): this;
57
59
  headers(headers: string[][]): this;
60
+ version(version: HttpVersion): this;
58
61
  body(body: Buffer): this;
62
+ bodyStream(body: AsyncIterable<Buffer | Uint8Array>): this;
59
63
  json(jsonStr: string): this;
60
64
  form(formStr: string): this;
61
65
  send(): Promise<Response>;
@@ -64,6 +68,7 @@ export class RequestBuilder {
64
68
  export class Response {
65
69
  get status(): number;
66
70
  get headers(): Record<string, string>;
71
+ get body(): AsyncIterable<Buffer>;
67
72
  headersList(): string[][];
68
73
  getHeader(name: string): string | null;
69
74
  text(): string;
package/index.js CHANGED
@@ -130,6 +130,7 @@ module.exports.Client = binding.Client;
130
130
  module.exports.ClientBuilder = binding.ClientBuilder;
131
131
  module.exports.RequestBuilder = binding.RequestBuilder;
132
132
  module.exports.Response = binding.Response;
133
+ module.exports.BodyStreamBridge = binding.BodyStreamBridge;
133
134
  module.exports.CookieJar = binding.CookieJar;
134
135
  module.exports.WebSocketBuilder = binding.WebSocketBuilder;
135
136
  module.exports.WebSocket = binding.WebSocket;
@@ -157,3 +158,67 @@ module.exports.isValidCloseCode = binding.isValidCloseCode;
157
158
  module.exports.clientBuilder = binding.clientBuilder;
158
159
  module.exports.timeoutsApiDefaults = binding.timeoutsApiDefaults;
159
160
  module.exports.timeoutsStreamingDefaults = binding.timeoutsStreamingDefaults;
161
+
162
+ const requestBuilderSend = binding.RequestBuilder.prototype.send;
163
+ const requestBuilderBodyStreamBridge = binding.RequestBuilder.prototype.bodyStreamBridge;
164
+
165
+ binding.RequestBuilder.prototype.bodyStream = function bodyStream(asyncIterable) {
166
+ if (!asyncIterable || typeof asyncIterable[Symbol.asyncIterator] !== 'function') {
167
+ throw new TypeError('bodyStream expects an AsyncIterable<Buffer | Uint8Array>');
168
+ }
169
+
170
+ const bridge = new binding.BodyStreamBridge();
171
+ requestBuilderBodyStreamBridge.call(this, bridge);
172
+ Object.defineProperty(this, '__specterBodyStream', {
173
+ value: { asyncIterable, bridge },
174
+ configurable: true,
175
+ });
176
+ return this;
177
+ };
178
+
179
+ binding.RequestBuilder.prototype.send = function send() {
180
+ const streamState = this.__specterBodyStream;
181
+ if (!streamState) {
182
+ return requestBuilderSend.call(this);
183
+ }
184
+
185
+ const pump = (async () => {
186
+ try {
187
+ for await (const chunk of streamState.asyncIterable) {
188
+ if (chunk == null) {
189
+ throw new TypeError('bodyStream chunks must be Buffer or Uint8Array values');
190
+ }
191
+ await streamState.bridge.write(Buffer.from(chunk));
192
+ }
193
+ streamState.bridge.close();
194
+ } catch (error) {
195
+ await streamState.bridge.fail(error?.message || String(error));
196
+ }
197
+ })();
198
+
199
+ pump.catch(() => {});
200
+ return requestBuilderSend.call(this).finally(() => {
201
+ streamState.bridge.close();
202
+ });
203
+ };
204
+
205
+ Object.defineProperty(binding.Response.prototype, 'body', {
206
+ configurable: true,
207
+ enumerable: true,
208
+ get() {
209
+ const response = this;
210
+ return {
211
+ [Symbol.asyncIterator]() {
212
+ return {
213
+ async next() {
214
+ const chunk = await response.nextBodyChunk();
215
+ if (chunk === null || chunk === undefined) {
216
+ return { done: true, value: undefined };
217
+ }
218
+ return { done: false, value: chunk };
219
+ },
220
+ };
221
+ },
222
+ };
223
+ },
224
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "specters",
3
- "version": "3.0.0",
3
+ "version": "3.2.0",
4
4
  "description": "Node.js bindings for Specter HTTP, WebSocket, HTTP/2, and HTTP/3 tunnel client",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -35,10 +35,10 @@
35
35
  ]
36
36
  },
37
37
  "optionalDependencies": {
38
- "specters-darwin-x64": "3.0.0",
39
- "specters-darwin-arm64": "3.0.0",
40
- "specters-linux-x64-gnu": "3.0.0",
41
- "specters-linux-arm64-gnu": "3.0.0"
38
+ "specters-darwin-x64": "3.2.0",
39
+ "specters-darwin-arm64": "3.2.0",
40
+ "specters-linux-x64-gnu": "3.2.0",
41
+ "specters-linux-arm64-gnu": "3.2.0"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@napi-rs/cli": "^3.6.2",