wreq-js 1.4.0 → 1.5.2

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 (62) hide show
  1. package/README.md +45 -228
  2. package/dist/wreq-js.cjs +1174 -0
  3. package/dist/wreq-js.cjs.map +1 -0
  4. package/dist/{types.d.ts → wreq-js.d.cts} +244 -22
  5. package/dist/wreq-js.d.ts +479 -27
  6. package/dist/wreq-js.js +1049 -1095
  7. package/dist/wreq-js.js.map +1 -1
  8. package/package.json +23 -14
  9. package/rust/wreq-js.darwin-arm64.node +0 -0
  10. package/rust/wreq-js.darwin-x64.node +0 -0
  11. package/rust/wreq-js.linux-arm64-gnu.node +0 -0
  12. package/rust/wreq-js.linux-x64-gnu.node +0 -0
  13. package/rust/wreq-js.linux-x64-musl.node +0 -0
  14. package/rust/wreq-js.win32-x64-msvc.node +0 -0
  15. package/dist/generated-types.d.ts +0 -13
  16. package/dist/generated-types.d.ts.map +0 -1
  17. package/dist/generated-types.js +0 -7
  18. package/dist/generated-types.js.map +0 -1
  19. package/dist/test/helpers/http.d.ts +0 -4
  20. package/dist/test/helpers/http.d.ts.map +0 -1
  21. package/dist/test/helpers/http.js +0 -14
  22. package/dist/test/helpers/http.js.map +0 -1
  23. package/dist/test/helpers/local-test-server.d.ts +0 -7
  24. package/dist/test/helpers/local-test-server.d.ts.map +0 -1
  25. package/dist/test/helpers/local-test-server.js +0 -406
  26. package/dist/test/helpers/local-test-server.js.map +0 -1
  27. package/dist/test/http/errors.spec.d.ts +0 -2
  28. package/dist/test/http/errors.spec.d.ts.map +0 -1
  29. package/dist/test/http/errors.spec.js +0 -33
  30. package/dist/test/http/errors.spec.js.map +0 -1
  31. package/dist/test/http/headers.spec.d.ts +0 -2
  32. package/dist/test/http/headers.spec.d.ts.map +0 -1
  33. package/dist/test/http/headers.spec.js +0 -98
  34. package/dist/test/http/headers.spec.js.map +0 -1
  35. package/dist/test/http/insecure.spec.d.ts +0 -2
  36. package/dist/test/http/insecure.spec.d.ts.map +0 -1
  37. package/dist/test/http/insecure.spec.js +0 -126
  38. package/dist/test/http/insecure.spec.js.map +0 -1
  39. package/dist/test/http/profiles.spec.d.ts +0 -2
  40. package/dist/test/http/profiles.spec.d.ts.map +0 -1
  41. package/dist/test/http/profiles.spec.js +0 -28
  42. package/dist/test/http/profiles.spec.js.map +0 -1
  43. package/dist/test/http/requests.spec.d.ts +0 -2
  44. package/dist/test/http/requests.spec.d.ts.map +0 -1
  45. package/dist/test/http/requests.spec.js +0 -198
  46. package/dist/test/http/requests.spec.js.map +0 -1
  47. package/dist/test/http/sessions.spec.d.ts +0 -2
  48. package/dist/test/http/sessions.spec.d.ts.map +0 -1
  49. package/dist/test/http/sessions.spec.js +0 -68
  50. package/dist/test/http/sessions.spec.js.map +0 -1
  51. package/dist/test/run-with-local-server.d.ts +0 -2
  52. package/dist/test/run-with-local-server.d.ts.map +0 -1
  53. package/dist/test/run-with-local-server.js +0 -71
  54. package/dist/test/run-with-local-server.js.map +0 -1
  55. package/dist/test/websocket.spec.d.ts +0 -2
  56. package/dist/test/websocket.spec.d.ts.map +0 -1
  57. package/dist/test/websocket.spec.js +0 -122
  58. package/dist/test/websocket.spec.js.map +0 -1
  59. package/dist/types.d.ts.map +0 -1
  60. package/dist/types.js +0 -26
  61. package/dist/types.js.map +0 -1
  62. package/dist/wreq-js.d.ts.map +0 -1
@@ -0,0 +1,1174 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/wreq-js.ts
21
+ var wreq_js_exports = {};
22
+ __export(wreq_js_exports, {
23
+ Headers: () => Headers,
24
+ RequestError: () => RequestError,
25
+ Response: () => Response,
26
+ Session: () => Session,
27
+ WebSocket: () => WebSocket,
28
+ createSession: () => createSession,
29
+ default: () => wreq_js_default,
30
+ fetch: () => fetch,
31
+ get: () => get,
32
+ getOperatingSystems: () => getOperatingSystems,
33
+ getProfiles: () => getProfiles,
34
+ post: () => post,
35
+ request: () => request,
36
+ websocket: () => websocket,
37
+ withSession: () => withSession
38
+ });
39
+ module.exports = __toCommonJS(wreq_js_exports);
40
+ var import_node_crypto = require("crypto");
41
+ var import_node_http = require("http");
42
+ var import_node_module = require("module");
43
+ var import_web = require("stream/web");
44
+
45
+ // src/types.ts
46
+ var RequestError = class extends Error {
47
+ constructor(message) {
48
+ super(message);
49
+ this.name = "RequestError";
50
+ }
51
+ };
52
+
53
+ // src/wreq-js.ts
54
+ var import_meta = {};
55
+ var nativeBinding;
56
+ var cachedProfiles;
57
+ var cachedOperatingSystems;
58
+ function detectLibc() {
59
+ if (process.platform !== "linux") {
60
+ return void 0;
61
+ }
62
+ const envLibc = process.env.LIBC ?? process.env.npm_config_libc;
63
+ if (envLibc) {
64
+ return envLibc.toLowerCase().includes("musl") ? "musl" : "gnu";
65
+ }
66
+ try {
67
+ const report = process.report?.getReport?.();
68
+ const glibcVersion = report?.header?.glibcVersionRuntime;
69
+ if (glibcVersion) {
70
+ return "gnu";
71
+ }
72
+ return "musl";
73
+ } catch {
74
+ return "gnu";
75
+ }
76
+ }
77
+ var require2 = typeof import_meta !== "undefined" && import_meta.url ? (0, import_node_module.createRequire)(import_meta.url) : (0, import_node_module.createRequire)(__filename);
78
+ function loadNativeBinding() {
79
+ const platform = process.platform;
80
+ const arch = process.arch;
81
+ const libc = detectLibc();
82
+ const platformArchMap = {
83
+ darwin: { x64: "darwin-x64", arm64: "darwin-arm64" },
84
+ linux: {
85
+ x64: { gnu: "linux-x64-gnu", musl: "linux-x64-musl" },
86
+ arm64: "linux-arm64-gnu"
87
+ },
88
+ win32: { x64: "win32-x64-msvc" }
89
+ };
90
+ const platformArchMapEntry = platformArchMap[platform]?.[arch];
91
+ const platformArch = typeof platformArchMapEntry === "string" ? platformArchMapEntry : platformArchMapEntry?.[libc ?? "gnu"];
92
+ if (!platformArch) {
93
+ throw new Error(
94
+ `Unsupported platform: ${platform}-${arch}${libc ? `-${libc}` : ""}. Supported platforms: darwin-x64, darwin-arm64, linux-x64-gnu, linux-x64-musl, linux-arm64-gnu, win32-x64-msvc`
95
+ );
96
+ }
97
+ const binaryName = `wreq-js.${platformArch}.node`;
98
+ try {
99
+ return require2(`../rust/${binaryName}`);
100
+ } catch {
101
+ try {
102
+ return require2("../rust/wreq-js.node");
103
+ } catch {
104
+ throw new Error(
105
+ `Failed to load native module for ${platform}-${arch}. Tried: ../rust/${binaryName} and ../rust/wreq-js.node. Make sure the package is installed correctly and the native module is built for your platform.`
106
+ );
107
+ }
108
+ }
109
+ }
110
+ nativeBinding = loadNativeBinding();
111
+ var websocketFinalizer = typeof FinalizationRegistry === "function" ? new FinalizationRegistry((connection) => {
112
+ void nativeBinding.websocketClose(connection).catch(() => void 0);
113
+ }) : void 0;
114
+ var bodyHandleFinalizer = typeof FinalizationRegistry === "function" ? new FinalizationRegistry((handle) => {
115
+ if (handle.released) {
116
+ return;
117
+ }
118
+ handle.released = true;
119
+ try {
120
+ nativeBinding.cancelBody(handle.id);
121
+ } catch {
122
+ }
123
+ }) : void 0;
124
+ var DEFAULT_BROWSER = "chrome_142";
125
+ var DEFAULT_OS = "macos";
126
+ var SUPPORTED_OSES = ["windows", "macos", "linux", "android", "ios"];
127
+ var UTF8_DECODER = new TextDecoder("utf-8");
128
+ function generateSessionId() {
129
+ return (0, import_node_crypto.randomUUID)();
130
+ }
131
+ function normalizeSessionOptions(options) {
132
+ const sessionId = options?.sessionId ?? generateSessionId();
133
+ const defaults = {
134
+ browser: options?.browser ?? DEFAULT_BROWSER,
135
+ os: options?.os ?? DEFAULT_OS
136
+ };
137
+ if (options?.proxy !== void 0) {
138
+ defaults.proxy = options.proxy;
139
+ }
140
+ if (options?.timeout !== void 0) {
141
+ validateTimeout(options.timeout);
142
+ defaults.timeout = options.timeout;
143
+ }
144
+ if (options?.insecure !== void 0) {
145
+ defaults.insecure = options.insecure;
146
+ }
147
+ return { sessionId, defaults };
148
+ }
149
+ function isIterable(value) {
150
+ return Boolean(value) && typeof value[Symbol.iterator] === "function";
151
+ }
152
+ function isPlainObject(value) {
153
+ if (typeof value !== "object" || value === null) {
154
+ return false;
155
+ }
156
+ const proto = Object.getPrototypeOf(value);
157
+ return proto === Object.prototype || proto === null;
158
+ }
159
+ function coerceHeaderValue(value) {
160
+ return String(value);
161
+ }
162
+ var Headers = class _Headers {
163
+ store = /* @__PURE__ */ new Map();
164
+ constructor(init) {
165
+ if (init) {
166
+ this.applyInit(init);
167
+ }
168
+ }
169
+ applyInit(init) {
170
+ if (init instanceof _Headers) {
171
+ for (const [name, value] of init) {
172
+ this.append(name, value);
173
+ }
174
+ return;
175
+ }
176
+ if (Array.isArray(init) || isIterable(init)) {
177
+ for (const tuple of init) {
178
+ if (!tuple) {
179
+ continue;
180
+ }
181
+ const [name, value] = tuple;
182
+ this.append(name, value);
183
+ }
184
+ return;
185
+ }
186
+ if (isPlainObject(init)) {
187
+ for (const [name, value] of Object.entries(init)) {
188
+ if (value === void 0 || value === null) {
189
+ continue;
190
+ }
191
+ this.set(name, coerceHeaderValue(value));
192
+ }
193
+ }
194
+ }
195
+ normalizeName(name) {
196
+ if (typeof name !== "string") {
197
+ throw new TypeError("Header name must be a string");
198
+ }
199
+ const trimmed = name.trim();
200
+ if (!trimmed) {
201
+ throw new TypeError("Header name must not be empty");
202
+ }
203
+ return { key: trimmed.toLowerCase(), display: trimmed };
204
+ }
205
+ assertValue(value) {
206
+ if (value === void 0 || value === null) {
207
+ throw new TypeError("Header value must not be null or undefined");
208
+ }
209
+ return coerceHeaderValue(value);
210
+ }
211
+ append(name, value) {
212
+ const normalized = this.normalizeName(name);
213
+ const existing = this.store.get(normalized.key);
214
+ const coercedValue = this.assertValue(value);
215
+ if (existing) {
216
+ existing.values.push(coercedValue);
217
+ return;
218
+ }
219
+ this.store.set(normalized.key, {
220
+ name: normalized.display,
221
+ values: [coercedValue]
222
+ });
223
+ }
224
+ set(name, value) {
225
+ const normalized = this.normalizeName(name);
226
+ const coercedValue = this.assertValue(value);
227
+ this.store.set(normalized.key, {
228
+ name: normalized.display,
229
+ values: [coercedValue]
230
+ });
231
+ }
232
+ get(name) {
233
+ const normalized = this.normalizeName(name);
234
+ const entry = this.store.get(normalized.key);
235
+ return entry ? entry.values.join(", ") : null;
236
+ }
237
+ has(name) {
238
+ const normalized = this.normalizeName(name);
239
+ return this.store.has(normalized.key);
240
+ }
241
+ delete(name) {
242
+ const normalized = this.normalizeName(name);
243
+ this.store.delete(normalized.key);
244
+ }
245
+ entries() {
246
+ return this[Symbol.iterator]();
247
+ }
248
+ *keys() {
249
+ for (const [name] of this) {
250
+ yield name;
251
+ }
252
+ }
253
+ *values() {
254
+ for (const [, value] of this) {
255
+ yield value;
256
+ }
257
+ }
258
+ forEach(callback, thisArg) {
259
+ for (const [name, value] of this) {
260
+ callback.call(thisArg, value, name, this);
261
+ }
262
+ }
263
+ [Symbol.iterator]() {
264
+ const generator = function* (store) {
265
+ for (const entry of store.values()) {
266
+ yield [entry.name, entry.values.join(", ")];
267
+ }
268
+ };
269
+ return generator(this.store);
270
+ }
271
+ toObject() {
272
+ const result = {};
273
+ for (const [name, value] of this) {
274
+ result[name] = value;
275
+ }
276
+ return result;
277
+ }
278
+ toTuples() {
279
+ const result = [];
280
+ for (const [name, value] of this) {
281
+ result.push([name, value]);
282
+ }
283
+ return result;
284
+ }
285
+ };
286
+ function headersToTuples(init) {
287
+ if (Array.isArray(init)) {
288
+ return init;
289
+ }
290
+ if (init instanceof Headers) {
291
+ return init.toTuples();
292
+ }
293
+ const out = [];
294
+ if (isPlainObject(init)) {
295
+ for (const name in init) {
296
+ if (!Object.hasOwn(init, name)) {
297
+ continue;
298
+ }
299
+ const value = init[name];
300
+ if (value === void 0 || value === null) {
301
+ continue;
302
+ }
303
+ out.push([name, String(value)]);
304
+ }
305
+ return out;
306
+ }
307
+ if (isIterable(init)) {
308
+ for (const tuple of init) {
309
+ if (!tuple) {
310
+ continue;
311
+ }
312
+ const [name, value] = tuple;
313
+ out.push([name, value]);
314
+ }
315
+ return out;
316
+ }
317
+ return out;
318
+ }
319
+ function cloneNativeResponse(payload) {
320
+ return {
321
+ status: payload.status,
322
+ headers: payload.headers.map(([name, value]) => [name, value]),
323
+ bodyHandle: payload.bodyHandle,
324
+ bodyBytes: payload.bodyBytes,
325
+ contentLength: payload.contentLength,
326
+ cookies: payload.cookies.map(([name, value]) => [name, value]),
327
+ url: payload.url
328
+ };
329
+ }
330
+ function releaseNativeBody(handle) {
331
+ if (handle.released) {
332
+ return;
333
+ }
334
+ handle.released = true;
335
+ try {
336
+ nativeBinding.cancelBody(handle.id);
337
+ } catch {
338
+ }
339
+ bodyHandleFinalizer?.unregister(handle);
340
+ }
341
+ function createNativeBodyStream(handleId) {
342
+ const handle = { id: handleId, released: false };
343
+ const stream = new import_web.ReadableStream({
344
+ async pull(controller) {
345
+ try {
346
+ const chunk = await nativeBinding.readBodyChunk(handle.id);
347
+ if (chunk === null) {
348
+ releaseNativeBody(handle);
349
+ controller.close();
350
+ return;
351
+ }
352
+ controller.enqueue(chunk);
353
+ } catch (error) {
354
+ releaseNativeBody(handle);
355
+ controller.error(error);
356
+ }
357
+ },
358
+ cancel() {
359
+ releaseNativeBody(handle);
360
+ }
361
+ });
362
+ bodyHandleFinalizer?.register(stream, handle, handle);
363
+ return stream;
364
+ }
365
+ function wrapBodyStream(source, onFirstUse) {
366
+ let started = false;
367
+ const reader = source.getReader();
368
+ return new import_web.ReadableStream({
369
+ async pull(controller) {
370
+ if (!started) {
371
+ started = true;
372
+ onFirstUse();
373
+ }
374
+ try {
375
+ const { done, value } = await reader.read();
376
+ if (done) {
377
+ controller.close();
378
+ return;
379
+ }
380
+ controller.enqueue(value);
381
+ } catch (error) {
382
+ controller.error(error);
383
+ }
384
+ },
385
+ cancel(reason) {
386
+ return reader.cancel(reason);
387
+ }
388
+ });
389
+ }
390
+ var Response = class _Response {
391
+ status;
392
+ ok;
393
+ contentLength;
394
+ url;
395
+ type = "basic";
396
+ bodyUsed = false;
397
+ payload;
398
+ requestUrl;
399
+ redirectedMemo;
400
+ headersInit;
401
+ headersInstance;
402
+ cookiesInit;
403
+ cookiesRecord;
404
+ inlineBody;
405
+ bodySource;
406
+ bodyStream;
407
+ // Track if we can use the fast path (native handle not yet wrapped in a stream)
408
+ nativeHandleAvailable;
409
+ constructor(payload, requestUrl, bodySource) {
410
+ this.payload = payload;
411
+ this.requestUrl = requestUrl;
412
+ this.status = this.payload.status;
413
+ this.ok = this.status >= 200 && this.status < 300;
414
+ this.headersInit = this.payload.headers;
415
+ this.headersInstance = null;
416
+ this.url = this.payload.url;
417
+ this.cookiesInit = this.payload.cookies;
418
+ this.cookiesRecord = null;
419
+ this.contentLength = this.payload.contentLength ?? null;
420
+ this.inlineBody = this.payload.bodyBytes ?? null;
421
+ if (typeof bodySource !== "undefined") {
422
+ this.bodySource = bodySource;
423
+ this.nativeHandleAvailable = false;
424
+ } else if (this.inlineBody !== null) {
425
+ this.bodySource = null;
426
+ this.nativeHandleAvailable = false;
427
+ } else if (this.payload.bodyHandle !== null) {
428
+ this.bodySource = null;
429
+ this.nativeHandleAvailable = true;
430
+ } else {
431
+ this.bodySource = null;
432
+ this.nativeHandleAvailable = false;
433
+ }
434
+ this.bodyStream = void 0;
435
+ }
436
+ get redirected() {
437
+ if (this.redirectedMemo !== void 0) {
438
+ return this.redirectedMemo;
439
+ }
440
+ if (this.url === this.requestUrl) {
441
+ this.redirectedMemo = false;
442
+ return false;
443
+ }
444
+ const normalizedRequestUrl = normalizeUrlForComparison(this.requestUrl);
445
+ this.redirectedMemo = normalizedRequestUrl ? this.url !== normalizedRequestUrl : true;
446
+ return this.redirectedMemo;
447
+ }
448
+ get statusText() {
449
+ return import_node_http.STATUS_CODES[this.status] ?? "";
450
+ }
451
+ get headers() {
452
+ if (!this.headersInstance) {
453
+ this.headersInstance = new Headers(this.headersInit);
454
+ }
455
+ return this.headersInstance;
456
+ }
457
+ get cookies() {
458
+ if (!this.cookiesRecord) {
459
+ const record = /* @__PURE__ */ Object.create(null);
460
+ for (const [name, value] of this.cookiesInit) {
461
+ const existing = record[name];
462
+ if (existing === void 0) {
463
+ record[name] = value;
464
+ } else if (Array.isArray(existing)) {
465
+ existing.push(value);
466
+ } else {
467
+ record[name] = [existing, value];
468
+ }
469
+ }
470
+ this.cookiesRecord = record;
471
+ }
472
+ return this.cookiesRecord;
473
+ }
474
+ get body() {
475
+ if (this.inlineBody && this.bodySource === null) {
476
+ const bytes = this.inlineBody;
477
+ this.inlineBody = null;
478
+ this.bodySource = new import_web.ReadableStream({
479
+ start(controller) {
480
+ controller.enqueue(bytes);
481
+ controller.close();
482
+ }
483
+ });
484
+ }
485
+ if (this.inlineBody === null && this.payload.bodyHandle === null && this.bodySource === null) {
486
+ return null;
487
+ }
488
+ if (this.bodySource === null && this.nativeHandleAvailable && this.payload.bodyHandle !== null) {
489
+ this.bodySource = createNativeBodyStream(this.payload.bodyHandle);
490
+ this.nativeHandleAvailable = false;
491
+ }
492
+ if (this.bodySource === null) {
493
+ return null;
494
+ }
495
+ if (this.bodyStream === void 0) {
496
+ this.bodyStream = wrapBodyStream(this.bodySource, () => {
497
+ this.bodyUsed = true;
498
+ });
499
+ }
500
+ return this.bodyStream;
501
+ }
502
+ async json() {
503
+ const text = await this.text();
504
+ return JSON.parse(text);
505
+ }
506
+ async arrayBuffer() {
507
+ const bytes = await this.consumeBody();
508
+ const { buffer, byteOffset, byteLength } = bytes;
509
+ if (buffer instanceof ArrayBuffer) {
510
+ return buffer.slice(byteOffset, byteOffset + byteLength);
511
+ }
512
+ const view = new Uint8Array(byteLength);
513
+ view.set(bytes);
514
+ return view.buffer;
515
+ }
516
+ async text() {
517
+ const bytes = await this.consumeBody();
518
+ return UTF8_DECODER.decode(bytes);
519
+ }
520
+ clone() {
521
+ if (this.bodyUsed || this.bodyStream) {
522
+ throw new TypeError("Cannot clone a Response whose body is already used");
523
+ }
524
+ if (this.nativeHandleAvailable && this.payload.bodyHandle !== null) {
525
+ this.bodySource = createNativeBodyStream(this.payload.bodyHandle);
526
+ this.nativeHandleAvailable = false;
527
+ }
528
+ if (this.bodySource === null) {
529
+ return new _Response(cloneNativeResponse(this.payload), this.requestUrl, null);
530
+ }
531
+ const [branchA, branchB] = this.bodySource.tee();
532
+ this.bodySource = branchA;
533
+ this.bodyStream = void 0;
534
+ return new _Response(cloneNativeResponse(this.payload), this.requestUrl, branchB);
535
+ }
536
+ assertBodyAvailable() {
537
+ if (this.bodyUsed) {
538
+ throw new TypeError("Response body is already used");
539
+ }
540
+ }
541
+ async consumeBody() {
542
+ this.assertBodyAvailable();
543
+ this.bodyUsed = true;
544
+ if (this.inlineBody) {
545
+ const bytes = this.inlineBody;
546
+ this.inlineBody = null;
547
+ return bytes;
548
+ }
549
+ if (this.nativeHandleAvailable && this.payload.bodyHandle !== null) {
550
+ this.nativeHandleAvailable = false;
551
+ try {
552
+ return await nativeBinding.readBodyAll(this.payload.bodyHandle);
553
+ } catch (error) {
554
+ if (String(error).includes("not found")) {
555
+ return Buffer.alloc(0);
556
+ }
557
+ throw error;
558
+ }
559
+ }
560
+ const stream = this.body;
561
+ if (!stream) {
562
+ return Buffer.alloc(0);
563
+ }
564
+ const reader = stream.getReader();
565
+ const chunks = [];
566
+ try {
567
+ while (true) {
568
+ const { done, value } = await reader.read();
569
+ if (done) {
570
+ break;
571
+ }
572
+ if (value && value.byteLength > 0) {
573
+ if (Buffer.isBuffer(value)) {
574
+ chunks.push(value);
575
+ } else {
576
+ chunks.push(Buffer.from(value.buffer, value.byteOffset, value.byteLength));
577
+ }
578
+ }
579
+ }
580
+ } finally {
581
+ }
582
+ return chunks.length === 0 ? Buffer.alloc(0) : Buffer.concat(chunks);
583
+ }
584
+ };
585
+ var Session = class {
586
+ id;
587
+ disposed = false;
588
+ defaults;
589
+ constructor(id, defaults) {
590
+ this.id = id;
591
+ this.defaults = defaults;
592
+ }
593
+ get closed() {
594
+ return this.disposed;
595
+ }
596
+ ensureActive() {
597
+ if (this.disposed) {
598
+ throw new RequestError("Session has been closed");
599
+ }
600
+ }
601
+ /** @internal */
602
+ getDefaults() {
603
+ return { ...this.defaults };
604
+ }
605
+ /** @internal */
606
+ _defaultsRef() {
607
+ return this.defaults;
608
+ }
609
+ async fetch(input, init) {
610
+ this.ensureActive();
611
+ return fetchWithSession(this, input, init);
612
+ }
613
+ async clearCookies() {
614
+ this.ensureActive();
615
+ try {
616
+ nativeBinding.clearSession(this.id);
617
+ } catch (error) {
618
+ throw new RequestError(String(error));
619
+ }
620
+ }
621
+ async close() {
622
+ if (this.disposed) {
623
+ return;
624
+ }
625
+ this.disposed = true;
626
+ try {
627
+ nativeBinding.dropSession(this.id);
628
+ } catch (error) {
629
+ throw new RequestError(String(error));
630
+ }
631
+ }
632
+ };
633
+ function resolveSessionContext(config) {
634
+ const requestedMode = config.cookieMode ?? "ephemeral";
635
+ const sessionCandidate = config.session;
636
+ const providedSessionId = typeof config.sessionId === "string" ? config.sessionId.trim() : void 0;
637
+ if (sessionCandidate && providedSessionId) {
638
+ throw new RequestError("Provide either `session` or `sessionId`, not both.");
639
+ }
640
+ if (sessionCandidate) {
641
+ if (!(sessionCandidate instanceof Session)) {
642
+ throw new RequestError("`session` must be created via createSession()");
643
+ }
644
+ if (sessionCandidate.closed) {
645
+ throw new RequestError("Session has been closed");
646
+ }
647
+ return {
648
+ sessionId: sessionCandidate.id,
649
+ cookieMode: "session",
650
+ dropAfterRequest: false,
651
+ defaults: sessionCandidate._defaultsRef()
652
+ };
653
+ }
654
+ if (providedSessionId) {
655
+ if (!providedSessionId) {
656
+ throw new RequestError("sessionId must not be empty");
657
+ }
658
+ if (requestedMode === "ephemeral") {
659
+ throw new RequestError("cookieMode 'ephemeral' cannot be combined with sessionId");
660
+ }
661
+ return {
662
+ sessionId: providedSessionId,
663
+ cookieMode: "session",
664
+ dropAfterRequest: false
665
+ };
666
+ }
667
+ if (requestedMode === "session") {
668
+ throw new RequestError("cookieMode 'session' requires a session or sessionId");
669
+ }
670
+ return {
671
+ sessionId: generateSessionId(),
672
+ cookieMode: "ephemeral",
673
+ dropAfterRequest: true
674
+ };
675
+ }
676
+ function createAbortError(reason) {
677
+ const fallbackMessage = typeof reason === "string" ? reason : "The operation was aborted";
678
+ if (typeof DOMException !== "undefined" && reason instanceof DOMException) {
679
+ return reason.name === "AbortError" ? reason : new DOMException(reason.message || fallbackMessage, "AbortError");
680
+ }
681
+ if (reason instanceof Error) {
682
+ reason.name = "AbortError";
683
+ return reason;
684
+ }
685
+ if (typeof DOMException !== "undefined") {
686
+ return new DOMException(fallbackMessage, "AbortError");
687
+ }
688
+ const error = new Error(fallbackMessage);
689
+ error.name = "AbortError";
690
+ return error;
691
+ }
692
+ function isAbortError(error) {
693
+ return Boolean(error) && typeof error.name === "string" && error.name === "AbortError";
694
+ }
695
+ var REQUEST_ID_MAX = 2 ** 48;
696
+ var requestIdCounter = Math.trunc(Number(process.hrtime.bigint() % BigInt(REQUEST_ID_MAX - 1))) + 1;
697
+ function generateRequestId() {
698
+ requestIdCounter += 1;
699
+ if (requestIdCounter >= REQUEST_ID_MAX) {
700
+ requestIdCounter = 1;
701
+ }
702
+ return requestIdCounter;
703
+ }
704
+ function setupAbort(signal, cancelNative) {
705
+ if (!signal) {
706
+ return null;
707
+ }
708
+ if (signal.aborted) {
709
+ cancelNative();
710
+ throw createAbortError(signal.reason);
711
+ }
712
+ let onAbortListener;
713
+ const promise = new Promise((_, reject) => {
714
+ onAbortListener = () => {
715
+ cancelNative();
716
+ reject(createAbortError(signal.reason));
717
+ };
718
+ signal.addEventListener("abort", onAbortListener, { once: true });
719
+ });
720
+ const cleanup = () => {
721
+ if (onAbortListener) {
722
+ signal.removeEventListener("abort", onAbortListener);
723
+ onAbortListener = void 0;
724
+ }
725
+ };
726
+ return { promise, cleanup };
727
+ }
728
+ function coerceUrlInput(input) {
729
+ const value = typeof input === "string" ? input.trim() : input.href;
730
+ if (!value) {
731
+ throw new RequestError("URL is required");
732
+ }
733
+ return value;
734
+ }
735
+ function normalizeUrlForComparison(value) {
736
+ try {
737
+ return new URL(value).toString();
738
+ } catch {
739
+ return null;
740
+ }
741
+ }
742
+ function validateRedirectMode(mode) {
743
+ if (mode === void 0 || mode === "follow" || mode === "manual" || mode === "error") {
744
+ return;
745
+ }
746
+ throw new RequestError(`Redirect mode '${mode}' is not supported`);
747
+ }
748
+ function serializeBody(body) {
749
+ if (body === null || body === void 0) {
750
+ return void 0;
751
+ }
752
+ if (typeof body === "string") {
753
+ return Buffer.from(body, "utf8");
754
+ }
755
+ if (Buffer.isBuffer(body)) {
756
+ return body;
757
+ }
758
+ if (body instanceof URLSearchParams) {
759
+ return Buffer.from(body.toString(), "utf8");
760
+ }
761
+ if (body instanceof ArrayBuffer) {
762
+ return Buffer.from(body);
763
+ }
764
+ if (ArrayBuffer.isView(body)) {
765
+ return Buffer.from(body.buffer, body.byteOffset, body.byteLength);
766
+ }
767
+ throw new TypeError("Unsupported body type; expected string, Buffer, ArrayBuffer, or URLSearchParams");
768
+ }
769
+ function ensureMethod(method) {
770
+ const normalized = method?.trim().toUpperCase();
771
+ return normalized && normalized.length > 0 ? normalized : "GET";
772
+ }
773
+ function ensureBodyAllowed(method, body) {
774
+ if (body === void 0) {
775
+ return;
776
+ }
777
+ if (method === "GET" || method === "HEAD") {
778
+ throw new RequestError(`Request with ${method} method cannot have a body`);
779
+ }
780
+ }
781
+ function validateBrowserProfile(browser) {
782
+ if (!browser) {
783
+ return;
784
+ }
785
+ const profiles = getProfiles();
786
+ if (!profiles.includes(browser)) {
787
+ throw new RequestError(`Invalid browser profile: ${browser}. Available profiles: ${profiles.join(", ")}`);
788
+ }
789
+ }
790
+ function validateOperatingSystem(os) {
791
+ if (!os) {
792
+ return;
793
+ }
794
+ const operatingSystems = getOperatingSystems();
795
+ if (!operatingSystems.includes(os)) {
796
+ throw new RequestError(`Invalid operating system: ${os}. Available options: ${operatingSystems.join(", ")}`);
797
+ }
798
+ }
799
+ function validateTimeout(timeout) {
800
+ if (timeout === void 0) {
801
+ return;
802
+ }
803
+ if (typeof timeout !== "number" || !Number.isFinite(timeout)) {
804
+ throw new RequestError("Timeout must be a finite number");
805
+ }
806
+ if (timeout <= 0) {
807
+ throw new RequestError("Timeout must be greater than 0");
808
+ }
809
+ }
810
+ async function fetchWithSession(session, input, init) {
811
+ const providedSessionId = typeof init?.sessionId === "string" ? init.sessionId.trim() : void 0;
812
+ if (providedSessionId) {
813
+ throw new RequestError("Provide either `session` or `sessionId`, not both.");
814
+ }
815
+ const url = coerceUrlInput(input);
816
+ const method = ensureMethod(init?.method);
817
+ const body = serializeBody(init?.body ?? null);
818
+ ensureBodyAllowed(method, body);
819
+ validateRedirectMode(init?.redirect);
820
+ const defaults = session._defaultsRef();
821
+ if (init?.browser != null && init.browser !== defaults.browser) {
822
+ throw new RequestError("Session browser cannot be changed after creation");
823
+ }
824
+ if (init?.os != null && init.os !== defaults.os) {
825
+ throw new RequestError("Session operating system cannot be changed after creation");
826
+ }
827
+ const initHasProxy = Boolean(init) && Object.hasOwn(init, "proxy");
828
+ const requestedProxy = initHasProxy ? init.proxy : void 0;
829
+ if (initHasProxy && requestedProxy !== void 0 && (defaults.proxy ?? null) !== (requestedProxy ?? null)) {
830
+ throw new RequestError("Session proxy cannot be changed after creation");
831
+ }
832
+ const timeout = init?.timeout ?? defaults.timeout;
833
+ if (Boolean(init) && init.timeout !== void 0) {
834
+ validateTimeout(timeout);
835
+ }
836
+ const insecure = init?.insecure ?? defaults.insecure;
837
+ const headerTuples = init?.headers === void 0 ? void 0 : headersToTuples(init.headers);
838
+ const requestOptions = {
839
+ url,
840
+ method,
841
+ browser: defaults.browser,
842
+ os: defaults.os,
843
+ sessionId: session.id,
844
+ ephemeral: false
845
+ };
846
+ if (body !== void 0) {
847
+ requestOptions.body = body;
848
+ }
849
+ const proxy = requestedProxy ?? defaults.proxy;
850
+ if (proxy !== void 0) {
851
+ requestOptions.proxy = proxy;
852
+ }
853
+ if (timeout !== void 0) {
854
+ requestOptions.timeout = timeout;
855
+ }
856
+ if (init?.redirect !== void 0) {
857
+ requestOptions.redirect = init.redirect;
858
+ }
859
+ if (init?.disableDefaultHeaders !== void 0) {
860
+ requestOptions.disableDefaultHeaders = init.disableDefaultHeaders;
861
+ }
862
+ if (insecure !== void 0) {
863
+ requestOptions.insecure = insecure;
864
+ }
865
+ if (headerTuples && headerTuples.length > 0) {
866
+ requestOptions.headers = headerTuples;
867
+ }
868
+ return dispatchRequest(requestOptions, url, init?.signal ?? null);
869
+ }
870
+ async function dispatchRequest(options, requestUrl, signal) {
871
+ if (!signal) {
872
+ const requestId2 = generateRequestId();
873
+ let payload2;
874
+ try {
875
+ payload2 = await nativeBinding.request(options, requestId2, false);
876
+ } catch (error) {
877
+ if (error instanceof RequestError) {
878
+ throw error;
879
+ }
880
+ throw new RequestError(String(error));
881
+ }
882
+ return new Response(payload2, requestUrl);
883
+ }
884
+ const requestId = generateRequestId();
885
+ const cancelNative = () => {
886
+ try {
887
+ nativeBinding.cancelRequest(requestId);
888
+ } catch {
889
+ }
890
+ };
891
+ const abortHandler = setupAbort(signal, cancelNative);
892
+ if (!abortHandler) {
893
+ cancelNative();
894
+ throw createAbortError(signal.reason);
895
+ }
896
+ const pending = Promise.race([nativeBinding.request(options, requestId, true), abortHandler.promise]);
897
+ let payload;
898
+ try {
899
+ payload = await pending;
900
+ } catch (error) {
901
+ if (isAbortError(error)) {
902
+ throw error;
903
+ }
904
+ if (error instanceof RequestError) {
905
+ throw error;
906
+ }
907
+ throw new RequestError(String(error));
908
+ } finally {
909
+ abortHandler.cleanup();
910
+ }
911
+ return new Response(payload, requestUrl);
912
+ }
913
+ async function fetch(input, init) {
914
+ const url = coerceUrlInput(input);
915
+ const config = init ?? {};
916
+ const sessionContext = resolveSessionContext(config);
917
+ const sessionDefaults = sessionContext.defaults;
918
+ const browser = config.browser ?? sessionDefaults?.browser ?? DEFAULT_BROWSER;
919
+ const os = config.os ?? sessionDefaults?.os ?? DEFAULT_OS;
920
+ const proxy = config.proxy ?? sessionDefaults?.proxy;
921
+ const timeout = config.timeout ?? sessionDefaults?.timeout;
922
+ const insecure = config.insecure ?? sessionDefaults?.insecure;
923
+ validateRedirectMode(config.redirect);
924
+ if (!sessionDefaults || config.browser !== void 0) {
925
+ validateBrowserProfile(browser);
926
+ }
927
+ if (!sessionDefaults || config.os !== void 0) {
928
+ validateOperatingSystem(os);
929
+ }
930
+ if (!sessionDefaults || config.timeout !== void 0) {
931
+ validateTimeout(timeout);
932
+ }
933
+ if (sessionDefaults) {
934
+ if (browser !== sessionDefaults.browser) {
935
+ throw new RequestError("Session browser cannot be changed after creation");
936
+ }
937
+ if (os !== sessionDefaults.os) {
938
+ throw new RequestError("Session operating system cannot be changed after creation");
939
+ }
940
+ if (config.proxy !== void 0 && config.proxy !== sessionDefaults.proxy) {
941
+ throw new RequestError("Session proxy cannot be changed after creation");
942
+ }
943
+ }
944
+ const method = ensureMethod(config.method);
945
+ const body = serializeBody(config.body ?? null);
946
+ ensureBodyAllowed(method, body);
947
+ const headerTuples = config.headers === void 0 ? void 0 : headersToTuples(config.headers);
948
+ const requestOptions = {
949
+ url,
950
+ method,
951
+ browser,
952
+ os,
953
+ sessionId: sessionContext.sessionId,
954
+ ephemeral: sessionContext.dropAfterRequest
955
+ };
956
+ if (body !== void 0) {
957
+ requestOptions.body = body;
958
+ }
959
+ if (proxy !== void 0) {
960
+ requestOptions.proxy = proxy;
961
+ }
962
+ if (timeout !== void 0) {
963
+ requestOptions.timeout = timeout;
964
+ }
965
+ if (config.redirect !== void 0) {
966
+ requestOptions.redirect = config.redirect;
967
+ }
968
+ if (config.disableDefaultHeaders !== void 0) {
969
+ requestOptions.disableDefaultHeaders = config.disableDefaultHeaders;
970
+ }
971
+ if (insecure !== void 0) {
972
+ requestOptions.insecure = insecure;
973
+ }
974
+ if (headerTuples && headerTuples.length > 0) {
975
+ requestOptions.headers = headerTuples;
976
+ }
977
+ return dispatchRequest(requestOptions, url, config.signal ?? null);
978
+ }
979
+ async function createSession(options) {
980
+ const { sessionId, defaults } = normalizeSessionOptions(options);
981
+ validateBrowserProfile(defaults.browser);
982
+ validateOperatingSystem(defaults.os);
983
+ let createdId;
984
+ try {
985
+ createdId = nativeBinding.createSession({
986
+ sessionId,
987
+ browser: defaults.browser,
988
+ os: defaults.os,
989
+ ...defaults.proxy !== void 0 && { proxy: defaults.proxy },
990
+ ...defaults.insecure !== void 0 && { insecure: defaults.insecure }
991
+ });
992
+ } catch (error) {
993
+ throw new RequestError(String(error));
994
+ }
995
+ return new Session(createdId, defaults);
996
+ }
997
+ async function withSession(fn, options) {
998
+ const session = await createSession(options);
999
+ try {
1000
+ return await fn(session);
1001
+ } finally {
1002
+ await session.close();
1003
+ }
1004
+ }
1005
+ async function request(options) {
1006
+ if (!options.url) {
1007
+ throw new RequestError("URL is required");
1008
+ }
1009
+ const { url, ...rest } = options;
1010
+ const init = {};
1011
+ if (rest.method !== void 0) {
1012
+ init.method = rest.method;
1013
+ }
1014
+ if (rest.headers !== void 0) {
1015
+ init.headers = rest.headers;
1016
+ }
1017
+ if (rest.body !== void 0) {
1018
+ init.body = rest.body;
1019
+ }
1020
+ if (rest.browser !== void 0) {
1021
+ init.browser = rest.browser;
1022
+ }
1023
+ if (rest.os !== void 0) {
1024
+ init.os = rest.os;
1025
+ }
1026
+ if (rest.proxy !== void 0) {
1027
+ init.proxy = rest.proxy;
1028
+ }
1029
+ if (rest.timeout !== void 0) {
1030
+ init.timeout = rest.timeout;
1031
+ }
1032
+ if (rest.sessionId !== void 0) {
1033
+ init.sessionId = rest.sessionId;
1034
+ }
1035
+ if (rest.disableDefaultHeaders !== void 0) {
1036
+ init.disableDefaultHeaders = rest.disableDefaultHeaders;
1037
+ }
1038
+ if (rest.redirect !== void 0) {
1039
+ init.redirect = rest.redirect;
1040
+ }
1041
+ return fetch(url, init);
1042
+ }
1043
+ function getProfiles() {
1044
+ if (!cachedProfiles) {
1045
+ cachedProfiles = nativeBinding.getProfiles();
1046
+ }
1047
+ return cachedProfiles;
1048
+ }
1049
+ function getOperatingSystems() {
1050
+ if (!cachedOperatingSystems) {
1051
+ const fromNative = nativeBinding.getOperatingSystems?.();
1052
+ cachedOperatingSystems = fromNative && fromNative.length > 0 ? fromNative : [...SUPPORTED_OSES];
1053
+ }
1054
+ return cachedOperatingSystems;
1055
+ }
1056
+ async function get(url, init) {
1057
+ const config = {};
1058
+ if (init) {
1059
+ Object.assign(config, init);
1060
+ }
1061
+ config.method = "GET";
1062
+ return fetch(url, config);
1063
+ }
1064
+ async function post(url, body, init) {
1065
+ const config = {};
1066
+ if (init) {
1067
+ Object.assign(config, init);
1068
+ }
1069
+ config.method = "POST";
1070
+ if (body !== void 0) {
1071
+ config.body = body;
1072
+ }
1073
+ return fetch(url, config);
1074
+ }
1075
+ var WebSocket = class {
1076
+ _connection;
1077
+ _finalizerToken;
1078
+ _closed = false;
1079
+ constructor(connection) {
1080
+ this._connection = connection;
1081
+ if (websocketFinalizer) {
1082
+ this._finalizerToken = connection;
1083
+ websocketFinalizer.register(this, connection, connection);
1084
+ }
1085
+ }
1086
+ /**
1087
+ * Send a message (text or binary)
1088
+ */
1089
+ async send(data) {
1090
+ try {
1091
+ await nativeBinding.websocketSend(this._connection, data);
1092
+ } catch (error) {
1093
+ throw new RequestError(String(error));
1094
+ }
1095
+ }
1096
+ /**
1097
+ * Close the WebSocket connection
1098
+ */
1099
+ async close() {
1100
+ if (this._closed) {
1101
+ return;
1102
+ }
1103
+ this._closed = true;
1104
+ if (this._finalizerToken && websocketFinalizer) {
1105
+ websocketFinalizer.unregister(this._finalizerToken);
1106
+ this._finalizerToken = void 0;
1107
+ }
1108
+ try {
1109
+ await nativeBinding.websocketClose(this._connection);
1110
+ } catch (error) {
1111
+ throw new RequestError(String(error));
1112
+ }
1113
+ }
1114
+ };
1115
+ async function websocket(options) {
1116
+ if (!options.url) {
1117
+ throw new RequestError("URL is required");
1118
+ }
1119
+ if (!options.onMessage) {
1120
+ throw new RequestError("onMessage callback is required");
1121
+ }
1122
+ validateBrowserProfile(options.browser);
1123
+ const os = options.os ?? DEFAULT_OS;
1124
+ validateOperatingSystem(os);
1125
+ const browser = options.browser ?? DEFAULT_BROWSER;
1126
+ try {
1127
+ const connection = await nativeBinding.websocketConnect({
1128
+ url: options.url,
1129
+ browser,
1130
+ os,
1131
+ headers: options.headers ?? {},
1132
+ ...options.proxy !== void 0 && { proxy: options.proxy },
1133
+ onMessage: options.onMessage,
1134
+ ...options.onClose !== void 0 && { onClose: options.onClose },
1135
+ ...options.onError !== void 0 && { onError: options.onError }
1136
+ });
1137
+ return new WebSocket(connection);
1138
+ } catch (error) {
1139
+ throw new RequestError(String(error));
1140
+ }
1141
+ }
1142
+ var wreq_js_default = {
1143
+ fetch,
1144
+ request,
1145
+ get,
1146
+ post,
1147
+ getProfiles,
1148
+ getOperatingSystems,
1149
+ createSession,
1150
+ withSession,
1151
+ websocket,
1152
+ WebSocket,
1153
+ Headers,
1154
+ Response,
1155
+ Session
1156
+ };
1157
+ // Annotate the CommonJS export names for ESM import in node:
1158
+ 0 && (module.exports = {
1159
+ Headers,
1160
+ RequestError,
1161
+ Response,
1162
+ Session,
1163
+ WebSocket,
1164
+ createSession,
1165
+ fetch,
1166
+ get,
1167
+ getOperatingSystems,
1168
+ getProfiles,
1169
+ post,
1170
+ request,
1171
+ websocket,
1172
+ withSession
1173
+ });
1174
+ //# sourceMappingURL=wreq-js.cjs.map