rezo 1.0.13 → 1.0.14

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.
@@ -6,7 +6,7 @@ const { spawn, execSync } = require("node:child_process");
6
6
  const { Readable } = require("node:stream");
7
7
  const { EventEmitter } = require("node:events");
8
8
  const { RezoError } = require('../errors/rezo-error.cjs');
9
- const { buildSmartError } = require('../responses/buildError.cjs');
9
+ const { buildSmartError, builErrorFromResponse } = require('../responses/buildError.cjs');
10
10
  const { RezoCookieJar, Cookie } = require('../utils/cookies.cjs');
11
11
  const RezoFormData = require('../utils/form-data.cjs');
12
12
  const { existsSync } = require("node:fs");
@@ -1906,19 +1906,23 @@ async function executeRequest(options, defaultOptions, jar) {
1906
1906
  if (proxyManager && selectedProxy) {
1907
1907
  proxyManager.reportSuccess(selectedProxy);
1908
1908
  }
1909
- if (config.retry && response.status >= 400) {
1910
- const maxRetries = config.retry.maxRetries || 0;
1911
- const statusCodes = config.retry.statusCodes || [408, 429, 500, 502, 503, 504];
1912
- if (config.retryAttempts < maxRetries && statusCodes.includes(response.status)) {
1913
- const retryDelay = config.retry.retryDelay || 0;
1914
- const incrementDelay = config.retry.incrementDelay || false;
1915
- const delay = incrementDelay ? retryDelay * (config.retryAttempts + 1) : retryDelay;
1916
- if (delay > 0) {
1917
- await new Promise((resolve) => setTimeout(resolve, delay));
1909
+ if (response.status >= 400) {
1910
+ const httpError = builErrorFromResponse(`Request failed with status code ${response.status}`, response, config, originalRequest);
1911
+ if (config.retry) {
1912
+ const maxRetries = config.retry.maxRetries || 0;
1913
+ const statusCodes = config.retry.statusCodes || [408, 429, 500, 502, 503, 504];
1914
+ if (config.retryAttempts < maxRetries && statusCodes.includes(response.status)) {
1915
+ const retryDelay = config.retry.retryDelay || 0;
1916
+ const incrementDelay = config.retry.incrementDelay || false;
1917
+ const delay = incrementDelay ? retryDelay * (config.retryAttempts + 1) : retryDelay;
1918
+ if (delay > 0) {
1919
+ await new Promise((resolve) => setTimeout(resolve, delay));
1920
+ }
1921
+ config.retryAttempts++;
1922
+ return executeRequest(options, defaultOptions, jar);
1918
1923
  }
1919
- config.retryAttempts++;
1920
- return executeRequest(options, defaultOptions, jar);
1921
1924
  }
1925
+ throw httpError;
1922
1926
  }
1923
1927
  }
1924
1928
  return result;
@@ -6,7 +6,7 @@ import { spawn, execSync } from "node:child_process";
6
6
  import { Readable } from "node:stream";
7
7
  import { EventEmitter } from "node:events";
8
8
  import { RezoError } from '../errors/rezo-error.js';
9
- import { buildSmartError } from '../responses/buildError.js';
9
+ import { buildSmartError, builErrorFromResponse } from '../responses/buildError.js';
10
10
  import { RezoCookieJar, Cookie } from '../utils/cookies.js';
11
11
  import RezoFormData from '../utils/form-data.js';
12
12
  import { existsSync } from "node:fs";
@@ -1906,19 +1906,23 @@ export async function executeRequest(options, defaultOptions, jar) {
1906
1906
  if (proxyManager && selectedProxy) {
1907
1907
  proxyManager.reportSuccess(selectedProxy);
1908
1908
  }
1909
- if (config.retry && response.status >= 400) {
1910
- const maxRetries = config.retry.maxRetries || 0;
1911
- const statusCodes = config.retry.statusCodes || [408, 429, 500, 502, 503, 504];
1912
- if (config.retryAttempts < maxRetries && statusCodes.includes(response.status)) {
1913
- const retryDelay = config.retry.retryDelay || 0;
1914
- const incrementDelay = config.retry.incrementDelay || false;
1915
- const delay = incrementDelay ? retryDelay * (config.retryAttempts + 1) : retryDelay;
1916
- if (delay > 0) {
1917
- await new Promise((resolve) => setTimeout(resolve, delay));
1909
+ if (response.status >= 400) {
1910
+ const httpError = builErrorFromResponse(`Request failed with status code ${response.status}`, response, config, originalRequest);
1911
+ if (config.retry) {
1912
+ const maxRetries = config.retry.maxRetries || 0;
1913
+ const statusCodes = config.retry.statusCodes || [408, 429, 500, 502, 503, 504];
1914
+ if (config.retryAttempts < maxRetries && statusCodes.includes(response.status)) {
1915
+ const retryDelay = config.retry.retryDelay || 0;
1916
+ const incrementDelay = config.retry.incrementDelay || false;
1917
+ const delay = incrementDelay ? retryDelay * (config.retryAttempts + 1) : retryDelay;
1918
+ if (delay > 0) {
1919
+ await new Promise((resolve) => setTimeout(resolve, delay));
1920
+ }
1921
+ config.retryAttempts++;
1922
+ return executeRequest(options, defaultOptions, jar);
1918
1923
  }
1919
- config.retryAttempts++;
1920
- return executeRequest(options, defaultOptions, jar);
1921
1924
  }
1925
+ throw httpError;
1922
1926
  }
1923
1927
  }
1924
1928
  return result;
@@ -314,11 +314,19 @@ export declare class RezoFormData extends NodeFormData {
314
314
  toBuffer(): Buffer;
315
315
  /**
316
316
  * Create RezoFormData from object
317
+ * Properly handles nested objects by JSON.stringify-ing them
317
318
  * @param {Record<string, any>} obj - Object to convert
318
319
  * @param {Options} options - Optional RezoFormData options
319
320
  * @returns {RezoFormData}
320
321
  */
321
322
  static fromObject(obj: Record<string, any>, options?: Options): RezoFormData;
323
+ /**
324
+ * Helper to append a value to FormData with proper type handling
325
+ * @param {RezoFormData} formData - The form data to append to
326
+ * @param {string} key - The field name
327
+ * @param {any} value - The value to append
328
+ */
329
+ private static appendValue;
322
330
  /**
323
331
  * Convert to URL query string
324
332
  * Warning: File, Blob, and binary data will be omitted
@@ -314,11 +314,19 @@ export declare class RezoFormData extends NodeFormData {
314
314
  toBuffer(): Buffer;
315
315
  /**
316
316
  * Create RezoFormData from object
317
+ * Properly handles nested objects by JSON.stringify-ing them
317
318
  * @param {Record<string, any>} obj - Object to convert
318
319
  * @param {Options} options - Optional RezoFormData options
319
320
  * @returns {RezoFormData}
320
321
  */
321
322
  static fromObject(obj: Record<string, any>, options?: Options): RezoFormData;
323
+ /**
324
+ * Helper to append a value to FormData with proper type handling
325
+ * @param {RezoFormData} formData - The form data to append to
326
+ * @param {string} key - The field name
327
+ * @param {any} value - The value to append
328
+ */
329
+ private static appendValue;
322
330
  /**
323
331
  * Convert to URL query string
324
332
  * Warning: File, Blob, and binary data will be omitted
@@ -314,11 +314,19 @@ export declare class RezoFormData extends NodeFormData {
314
314
  toBuffer(): Buffer;
315
315
  /**
316
316
  * Create RezoFormData from object
317
+ * Properly handles nested objects by JSON.stringify-ing them
317
318
  * @param {Record<string, any>} obj - Object to convert
318
319
  * @param {Options} options - Optional RezoFormData options
319
320
  * @returns {RezoFormData}
320
321
  */
321
322
  static fromObject(obj: Record<string, any>, options?: Options): RezoFormData;
323
+ /**
324
+ * Helper to append a value to FormData with proper type handling
325
+ * @param {RezoFormData} formData - The form data to append to
326
+ * @param {string} key - The field name
327
+ * @param {any} value - The value to append
328
+ */
329
+ private static appendValue;
322
330
  /**
323
331
  * Convert to URL query string
324
332
  * Warning: File, Blob, and binary data will be omitted
@@ -314,11 +314,19 @@ export declare class RezoFormData extends NodeFormData {
314
314
  toBuffer(): Buffer;
315
315
  /**
316
316
  * Create RezoFormData from object
317
+ * Properly handles nested objects by JSON.stringify-ing them
317
318
  * @param {Record<string, any>} obj - Object to convert
318
319
  * @param {Options} options - Optional RezoFormData options
319
320
  * @returns {RezoFormData}
320
321
  */
321
322
  static fromObject(obj: Record<string, any>, options?: Options): RezoFormData;
323
+ /**
324
+ * Helper to append a value to FormData with proper type handling
325
+ * @param {RezoFormData} formData - The form data to append to
326
+ * @param {string} key - The field name
327
+ * @param {any} value - The value to append
328
+ */
329
+ private static appendValue;
322
330
  /**
323
331
  * Convert to URL query string
324
332
  * Warning: File, Blob, and binary data will be omitted
@@ -314,11 +314,19 @@ export declare class RezoFormData extends NodeFormData {
314
314
  toBuffer(): Buffer;
315
315
  /**
316
316
  * Create RezoFormData from object
317
+ * Properly handles nested objects by JSON.stringify-ing them
317
318
  * @param {Record<string, any>} obj - Object to convert
318
319
  * @param {Options} options - Optional RezoFormData options
319
320
  * @returns {RezoFormData}
320
321
  */
321
322
  static fromObject(obj: Record<string, any>, options?: Options): RezoFormData;
323
+ /**
324
+ * Helper to append a value to FormData with proper type handling
325
+ * @param {RezoFormData} formData - The form data to append to
326
+ * @param {string} key - The field name
327
+ * @param {any} value - The value to append
328
+ */
329
+ private static appendValue;
322
330
  /**
323
331
  * Convert to URL query string
324
332
  * Warning: File, Blob, and binary data will be omitted
@@ -314,11 +314,19 @@ export declare class RezoFormData extends NodeFormData {
314
314
  toBuffer(): Buffer;
315
315
  /**
316
316
  * Create RezoFormData from object
317
+ * Properly handles nested objects by JSON.stringify-ing them
317
318
  * @param {Record<string, any>} obj - Object to convert
318
319
  * @param {Options} options - Optional RezoFormData options
319
320
  * @returns {RezoFormData}
320
321
  */
321
322
  static fromObject(obj: Record<string, any>, options?: Options): RezoFormData;
323
+ /**
324
+ * Helper to append a value to FormData with proper type handling
325
+ * @param {RezoFormData} formData - The form data to append to
326
+ * @param {string} key - The field name
327
+ * @param {any} value - The value to append
328
+ */
329
+ private static appendValue;
322
330
  /**
323
331
  * Convert to URL query string
324
332
  * Warning: File, Blob, and binary data will be omitted
@@ -366,9 +366,32 @@ async function executeFetchRequest(fetchOptions, config, options, perform, strea
366
366
  }
367
367
  continue;
368
368
  }
369
- if (statusOnNext === "success" || statusOnNext === "error") {
369
+ if (statusOnNext === "success") {
370
370
  return response;
371
371
  }
372
+ if (statusOnNext === "error") {
373
+ const httpError = builErrorFromResponse(`Request failed with status code ${response.status}`, response, config, fetchOptions);
374
+ if (config.retry && statusCodes?.includes(response.status)) {
375
+ if (maxRetries > retries) {
376
+ retries++;
377
+ config.retryAttempts++;
378
+ config.errors.push({
379
+ attempt: config.retryAttempts,
380
+ error: httpError,
381
+ duration: perform.now()
382
+ });
383
+ perform.reset();
384
+ if (config.debug) {
385
+ console.log(`Request failed with status code ${response.status}, retrying...${retryDelay > 0 ? " in " + (incrementDelay ? retryDelay * retries : retryDelay) + "ms" : ""}`);
386
+ }
387
+ if (retryDelay > 0) {
388
+ await new Promise((resolve) => setTimeout(resolve, incrementDelay ? retryDelay * retries : retryDelay));
389
+ }
390
+ continue;
391
+ }
392
+ }
393
+ throw httpError;
394
+ }
372
395
  if (statusOnNext === "redirect") {
373
396
  const location = _stats.redirectUrl;
374
397
  if (!location) {
@@ -366,9 +366,32 @@ async function executeFetchRequest(fetchOptions, config, options, perform, strea
366
366
  }
367
367
  continue;
368
368
  }
369
- if (statusOnNext === "success" || statusOnNext === "error") {
369
+ if (statusOnNext === "success") {
370
370
  return response;
371
371
  }
372
+ if (statusOnNext === "error") {
373
+ const httpError = builErrorFromResponse(`Request failed with status code ${response.status}`, response, config, fetchOptions);
374
+ if (config.retry && statusCodes?.includes(response.status)) {
375
+ if (maxRetries > retries) {
376
+ retries++;
377
+ config.retryAttempts++;
378
+ config.errors.push({
379
+ attempt: config.retryAttempts,
380
+ error: httpError,
381
+ duration: perform.now()
382
+ });
383
+ perform.reset();
384
+ if (config.debug) {
385
+ console.log(`Request failed with status code ${response.status}, retrying...${retryDelay > 0 ? " in " + (incrementDelay ? retryDelay * retries : retryDelay) + "ms" : ""}`);
386
+ }
387
+ if (retryDelay > 0) {
388
+ await new Promise((resolve) => setTimeout(resolve, incrementDelay ? retryDelay * retries : retryDelay));
389
+ }
390
+ continue;
391
+ }
392
+ }
393
+ throw httpError;
394
+ }
372
395
  if (statusOnNext === "redirect") {
373
396
  const location = _stats.redirectUrl;
374
397
  if (!location) {
@@ -402,6 +402,29 @@ Redirecting to: ${fetchOptions.fullUrl} using GET method`);
402
402
  options = __.options;
403
403
  continue;
404
404
  }
405
+ if (statusOnNext === "error") {
406
+ const httpError = builErrorFromResponse(`Request failed with status code ${response.status}`, response, config, fetchOptions);
407
+ if (config.retry && statusCodes?.includes(response.status)) {
408
+ if (maxRetries > retries) {
409
+ retries++;
410
+ config.retryAttempts++;
411
+ config.errors.push({
412
+ attempt: config.retryAttempts,
413
+ error: httpError,
414
+ duration: perform.now()
415
+ });
416
+ perform.reset();
417
+ if (config.debug) {
418
+ console.log(`Request failed with status code ${response.status}, retrying...${retryDelay > 0 ? " in " + (incrementDelay ? retryDelay * retries : retryDelay) + "ms" : ""}`);
419
+ }
420
+ if (retryDelay > 0) {
421
+ await new Promise((resolve) => setTimeout(resolve, incrementDelay ? retryDelay * retries : retryDelay));
422
+ }
423
+ continue;
424
+ }
425
+ }
426
+ throw httpError;
427
+ }
405
428
  delete config.beforeRedirect;
406
429
  config.setSignal = () => {};
407
430
  return response;
@@ -402,6 +402,29 @@ Redirecting to: ${fetchOptions.fullUrl} using GET method`);
402
402
  options = __.options;
403
403
  continue;
404
404
  }
405
+ if (statusOnNext === "error") {
406
+ const httpError = builErrorFromResponse(`Request failed with status code ${response.status}`, response, config, fetchOptions);
407
+ if (config.retry && statusCodes?.includes(response.status)) {
408
+ if (maxRetries > retries) {
409
+ retries++;
410
+ config.retryAttempts++;
411
+ config.errors.push({
412
+ attempt: config.retryAttempts,
413
+ error: httpError,
414
+ duration: perform.now()
415
+ });
416
+ perform.reset();
417
+ if (config.debug) {
418
+ console.log(`Request failed with status code ${response.status}, retrying...${retryDelay > 0 ? " in " + (incrementDelay ? retryDelay * retries : retryDelay) + "ms" : ""}`);
419
+ }
420
+ if (retryDelay > 0) {
421
+ await new Promise((resolve) => setTimeout(resolve, incrementDelay ? retryDelay * retries : retryDelay));
422
+ }
423
+ continue;
424
+ }
425
+ }
426
+ throw httpError;
427
+ }
405
428
  delete config.beforeRedirect;
406
429
  config.setSignal = () => {};
407
430
  return response;
@@ -557,9 +557,32 @@ async function executeHttp2Request(fetchOptions, config, options, perform, fs, s
557
557
  }
558
558
  continue;
559
559
  }
560
- if (statusOnNext === "success" || statusOnNext === "error") {
560
+ if (statusOnNext === "success") {
561
561
  return response;
562
562
  }
563
+ if (statusOnNext === "error") {
564
+ const httpError = builErrorFromResponse(`Request failed with status code ${response.status}`, response, config, fetchOptions);
565
+ if (config.retry && statusCodes?.includes(response.status)) {
566
+ if (maxRetries > retries) {
567
+ retries++;
568
+ config.retryAttempts++;
569
+ config.errors.push({
570
+ attempt: config.retryAttempts,
571
+ error: httpError,
572
+ duration: perform.now()
573
+ });
574
+ perform.reset();
575
+ if (config.debug) {
576
+ console.log(`Request failed with status code ${response.status}, retrying...${retryDelay > 0 ? " in " + (incrementDelay ? retryDelay * retries : retryDelay) + "ms" : ""}`);
577
+ }
578
+ if (retryDelay > 0) {
579
+ await new Promise((resolve) => setTimeout(resolve, incrementDelay ? retryDelay * retries : retryDelay));
580
+ }
581
+ continue;
582
+ }
583
+ }
584
+ throw httpError;
585
+ }
563
586
  if (statusOnNext === "redirect") {
564
587
  const location = _stats.redirectUrl;
565
588
  if (!location) {
@@ -557,9 +557,32 @@ async function executeHttp2Request(fetchOptions, config, options, perform, fs, s
557
557
  }
558
558
  continue;
559
559
  }
560
- if (statusOnNext === "success" || statusOnNext === "error") {
560
+ if (statusOnNext === "success") {
561
561
  return response;
562
562
  }
563
+ if (statusOnNext === "error") {
564
+ const httpError = builErrorFromResponse(`Request failed with status code ${response.status}`, response, config, fetchOptions);
565
+ if (config.retry && statusCodes?.includes(response.status)) {
566
+ if (maxRetries > retries) {
567
+ retries++;
568
+ config.retryAttempts++;
569
+ config.errors.push({
570
+ attempt: config.retryAttempts,
571
+ error: httpError,
572
+ duration: perform.now()
573
+ });
574
+ perform.reset();
575
+ if (config.debug) {
576
+ console.log(`Request failed with status code ${response.status}, retrying...${retryDelay > 0 ? " in " + (incrementDelay ? retryDelay * retries : retryDelay) + "ms" : ""}`);
577
+ }
578
+ if (retryDelay > 0) {
579
+ await new Promise((resolve) => setTimeout(resolve, incrementDelay ? retryDelay * retries : retryDelay));
580
+ }
581
+ continue;
582
+ }
583
+ }
584
+ throw httpError;
585
+ }
563
586
  if (statusOnNext === "redirect") {
564
587
  const location = _stats.redirectUrl;
565
588
  if (!location) {
@@ -1,6 +1,6 @@
1
- const _mod_h6yyuw = require('./picker.cjs');
2
- exports.detectRuntime = _mod_h6yyuw.detectRuntime;
3
- exports.getAdapterCapabilities = _mod_h6yyuw.getAdapterCapabilities;
4
- exports.buildAdapterContext = _mod_h6yyuw.buildAdapterContext;
5
- exports.getAvailableAdapters = _mod_h6yyuw.getAvailableAdapters;
6
- exports.selectAdapter = _mod_h6yyuw.selectAdapter;;
1
+ const _mod_wby0uw = require('./picker.cjs');
2
+ exports.detectRuntime = _mod_wby0uw.detectRuntime;
3
+ exports.getAdapterCapabilities = _mod_wby0uw.getAdapterCapabilities;
4
+ exports.buildAdapterContext = _mod_wby0uw.buildAdapterContext;
5
+ exports.getAvailableAdapters = _mod_wby0uw.getAvailableAdapters;
6
+ exports.selectAdapter = _mod_wby0uw.selectAdapter;;
@@ -1,13 +1,13 @@
1
- const _mod_vgyhxh = require('./lru-cache.cjs');
2
- exports.LRUCache = _mod_vgyhxh.LRUCache;;
3
- const _mod_57d30y = require('./dns-cache.cjs');
4
- exports.DNSCache = _mod_57d30y.DNSCache;
5
- exports.getGlobalDNSCache = _mod_57d30y.getGlobalDNSCache;
6
- exports.resetGlobalDNSCache = _mod_57d30y.resetGlobalDNSCache;;
7
- const _mod_qx55fg = require('./response-cache.cjs');
8
- exports.ResponseCache = _mod_qx55fg.ResponseCache;
9
- exports.normalizeResponseCacheConfig = _mod_qx55fg.normalizeResponseCacheConfig;;
10
- const _mod_clz0cm = require('./file-cacher.cjs');
11
- exports.FileCacher = _mod_clz0cm.FileCacher;;
12
- const _mod_39vswi = require('./url-store.cjs');
13
- exports.UrlStore = _mod_39vswi.UrlStore;;
1
+ const _mod_hi5yx4 = require('./lru-cache.cjs');
2
+ exports.LRUCache = _mod_hi5yx4.LRUCache;;
3
+ const _mod_xvsb8i = require('./dns-cache.cjs');
4
+ exports.DNSCache = _mod_xvsb8i.DNSCache;
5
+ exports.getGlobalDNSCache = _mod_xvsb8i.getGlobalDNSCache;
6
+ exports.resetGlobalDNSCache = _mod_xvsb8i.resetGlobalDNSCache;;
7
+ const _mod_gble7l = require('./response-cache.cjs');
8
+ exports.ResponseCache = _mod_gble7l.ResponseCache;
9
+ exports.normalizeResponseCacheConfig = _mod_gble7l.normalizeResponseCacheConfig;;
10
+ const _mod_oq9kzw = require('./file-cacher.cjs');
11
+ exports.FileCacher = _mod_oq9kzw.FileCacher;;
12
+ const _mod_mhhavh = require('./url-store.cjs');
13
+ exports.UrlStore = _mod_mhhavh.UrlStore;;
@@ -176,11 +176,18 @@ class Rezo {
176
176
  }, this.defaults, this.jar);
177
177
  };
178
178
  postMultipart = async (url, data, options = {}) => {
179
- data = data instanceof FormData ? await RezoFormData.fromNativeFormData(data) : data;
179
+ let formData;
180
+ if (data instanceof RezoFormData) {
181
+ formData = data;
182
+ } else if (data instanceof FormData) {
183
+ formData = await RezoFormData.fromNativeFormData(data);
184
+ } else {
185
+ formData = RezoFormData.fromObject(data);
186
+ }
180
187
  return this.executeRequest({
181
188
  ...options,
182
189
  url,
183
- formData: data,
190
+ formData,
184
191
  method: "POST"
185
192
  }, this.defaults, this.jar);
186
193
  };
@@ -217,11 +224,18 @@ class Rezo {
217
224
  }, this.defaults, this.jar);
218
225
  };
219
226
  putMultipart = async (url, data, options = {}) => {
220
- data = data instanceof FormData ? await RezoFormData.fromNativeFormData(data) : data;
227
+ let formData;
228
+ if (data instanceof RezoFormData) {
229
+ formData = data;
230
+ } else if (data instanceof FormData) {
231
+ formData = await RezoFormData.fromNativeFormData(data);
232
+ } else {
233
+ formData = RezoFormData.fromObject(data);
234
+ }
221
235
  return this.executeRequest({
222
236
  ...options,
223
237
  url,
224
- formData: data,
238
+ formData,
225
239
  method: "PUT"
226
240
  }, this.defaults, this.jar);
227
241
  };
@@ -258,11 +272,18 @@ class Rezo {
258
272
  }, this.defaults, this.jar);
259
273
  };
260
274
  patchMultipart = async (url, data, options = {}) => {
261
- data = data instanceof FormData ? await RezoFormData.fromNativeFormData(data) : data;
275
+ let formData;
276
+ if (data instanceof RezoFormData) {
277
+ formData = data;
278
+ } else if (data instanceof FormData) {
279
+ formData = await RezoFormData.fromNativeFormData(data);
280
+ } else {
281
+ formData = RezoFormData.fromObject(data);
282
+ }
262
283
  return this.executeRequest({
263
284
  ...options,
264
285
  url,
265
- formData: data,
286
+ formData,
266
287
  method: "PATCH"
267
288
  }, this.defaults, this.jar);
268
289
  };
package/dist/core/rezo.js CHANGED
@@ -176,11 +176,18 @@ export class Rezo {
176
176
  }, this.defaults, this.jar);
177
177
  };
178
178
  postMultipart = async (url, data, options = {}) => {
179
- data = data instanceof FormData ? await RezoFormData.fromNativeFormData(data) : data;
179
+ let formData;
180
+ if (data instanceof RezoFormData) {
181
+ formData = data;
182
+ } else if (data instanceof FormData) {
183
+ formData = await RezoFormData.fromNativeFormData(data);
184
+ } else {
185
+ formData = RezoFormData.fromObject(data);
186
+ }
180
187
  return this.executeRequest({
181
188
  ...options,
182
189
  url,
183
- formData: data,
190
+ formData,
184
191
  method: "POST"
185
192
  }, this.defaults, this.jar);
186
193
  };
@@ -217,11 +224,18 @@ export class Rezo {
217
224
  }, this.defaults, this.jar);
218
225
  };
219
226
  putMultipart = async (url, data, options = {}) => {
220
- data = data instanceof FormData ? await RezoFormData.fromNativeFormData(data) : data;
227
+ let formData;
228
+ if (data instanceof RezoFormData) {
229
+ formData = data;
230
+ } else if (data instanceof FormData) {
231
+ formData = await RezoFormData.fromNativeFormData(data);
232
+ } else {
233
+ formData = RezoFormData.fromObject(data);
234
+ }
221
235
  return this.executeRequest({
222
236
  ...options,
223
237
  url,
224
- formData: data,
238
+ formData,
225
239
  method: "PUT"
226
240
  }, this.defaults, this.jar);
227
241
  };
@@ -258,11 +272,18 @@ export class Rezo {
258
272
  }, this.defaults, this.jar);
259
273
  };
260
274
  patchMultipart = async (url, data, options = {}) => {
261
- data = data instanceof FormData ? await RezoFormData.fromNativeFormData(data) : data;
275
+ let formData;
276
+ if (data instanceof RezoFormData) {
277
+ formData = data;
278
+ } else if (data instanceof FormData) {
279
+ formData = await RezoFormData.fromNativeFormData(data);
280
+ } else {
281
+ formData = RezoFormData.fromObject(data);
282
+ }
262
283
  return this.executeRequest({
263
284
  ...options,
264
285
  url,
265
- formData: data,
286
+ formData,
266
287
  method: "PATCH"
267
288
  }, this.defaults, this.jar);
268
289
  };
package/dist/crawler.d.ts CHANGED
@@ -537,11 +537,19 @@ declare class RezoFormData extends NodeFormData {
537
537
  toBuffer(): Buffer;
538
538
  /**
539
539
  * Create RezoFormData from object
540
+ * Properly handles nested objects by JSON.stringify-ing them
540
541
  * @param {Record<string, any>} obj - Object to convert
541
542
  * @param {Options} options - Optional RezoFormData options
542
543
  * @returns {RezoFormData}
543
544
  */
544
545
  static fromObject(obj: Record<string, any>, options?: Options): RezoFormData;
546
+ /**
547
+ * Helper to append a value to FormData with proper type handling
548
+ * @param {RezoFormData} formData - The form data to append to
549
+ * @param {string} key - The field name
550
+ * @param {any} value - The value to append
551
+ */
552
+ private static appendValue;
545
553
  /**
546
554
  * Convert to URL query string
547
555
  * Warning: File, Blob, and binary data will be omitted
@@ -1,5 +1,5 @@
1
- const _mod_m9euun = require('../plugin/crawler.cjs');
2
- exports.Crawler = _mod_m9euun.Crawler;;
3
- const _mod_358g2f = require('../plugin/crawler-options.cjs');
4
- exports.CrawlerOptions = _mod_358g2f.CrawlerOptions;
5
- exports.Domain = _mod_358g2f.Domain;;
1
+ const _mod_6aofz8 = require('../plugin/crawler.cjs');
2
+ exports.Crawler = _mod_6aofz8.Crawler;;
3
+ const _mod_t23px8 = require('../plugin/crawler-options.cjs');
4
+ exports.CrawlerOptions = _mod_t23px8.CrawlerOptions;
5
+ exports.Domain = _mod_t23px8.Domain;;
package/dist/index.cjs CHANGED
@@ -1,27 +1,27 @@
1
- const _mod_txkkmz = require('./core/rezo.cjs');
2
- exports.Rezo = _mod_txkkmz.Rezo;
3
- exports.createRezoInstance = _mod_txkkmz.createRezoInstance;
4
- exports.createDefaultInstance = _mod_txkkmz.createDefaultInstance;;
5
- const _mod_a3vsp1 = require('./errors/rezo-error.cjs');
6
- exports.RezoError = _mod_a3vsp1.RezoError;
7
- exports.RezoErrorCode = _mod_a3vsp1.RezoErrorCode;;
8
- const _mod_2ef980 = require('./utils/headers.cjs');
9
- exports.RezoHeaders = _mod_2ef980.RezoHeaders;;
10
- const _mod_e56bdp = require('./utils/form-data.cjs');
11
- exports.RezoFormData = _mod_e56bdp.RezoFormData;;
12
- const _mod_ss7zpn = require('./utils/cookies.cjs');
13
- exports.RezoCookieJar = _mod_ss7zpn.RezoCookieJar;
14
- exports.Cookie = _mod_ss7zpn.Cookie;;
15
- const _mod_vdi6fa = require('./core/hooks.cjs');
16
- exports.createDefaultHooks = _mod_vdi6fa.createDefaultHooks;
17
- exports.mergeHooks = _mod_vdi6fa.mergeHooks;;
18
- const _mod_049k4s = require('./proxy/manager.cjs');
19
- exports.ProxyManager = _mod_049k4s.ProxyManager;;
20
- const _mod_5l0v67 = require('./queue/index.cjs');
21
- exports.RezoQueue = _mod_5l0v67.RezoQueue;
22
- exports.HttpQueue = _mod_5l0v67.HttpQueue;
23
- exports.Priority = _mod_5l0v67.Priority;
24
- exports.HttpMethodPriority = _mod_5l0v67.HttpMethodPriority;;
1
+ const _mod_wsc945 = require('./core/rezo.cjs');
2
+ exports.Rezo = _mod_wsc945.Rezo;
3
+ exports.createRezoInstance = _mod_wsc945.createRezoInstance;
4
+ exports.createDefaultInstance = _mod_wsc945.createDefaultInstance;;
5
+ const _mod_pc2qgs = require('./errors/rezo-error.cjs');
6
+ exports.RezoError = _mod_pc2qgs.RezoError;
7
+ exports.RezoErrorCode = _mod_pc2qgs.RezoErrorCode;;
8
+ const _mod_wei4ay = require('./utils/headers.cjs');
9
+ exports.RezoHeaders = _mod_wei4ay.RezoHeaders;;
10
+ const _mod_honebj = require('./utils/form-data.cjs');
11
+ exports.RezoFormData = _mod_honebj.RezoFormData;;
12
+ const _mod_6yx1gr = require('./utils/cookies.cjs');
13
+ exports.RezoCookieJar = _mod_6yx1gr.RezoCookieJar;
14
+ exports.Cookie = _mod_6yx1gr.Cookie;;
15
+ const _mod_dyuwd6 = require('./core/hooks.cjs');
16
+ exports.createDefaultHooks = _mod_dyuwd6.createDefaultHooks;
17
+ exports.mergeHooks = _mod_dyuwd6.mergeHooks;;
18
+ const _mod_h49ine = require('./proxy/manager.cjs');
19
+ exports.ProxyManager = _mod_h49ine.ProxyManager;;
20
+ const _mod_psyc82 = require('./queue/index.cjs');
21
+ exports.RezoQueue = _mod_psyc82.RezoQueue;
22
+ exports.HttpQueue = _mod_psyc82.HttpQueue;
23
+ exports.Priority = _mod_psyc82.Priority;
24
+ exports.HttpMethodPriority = _mod_psyc82.HttpMethodPriority;;
25
25
  const { RezoError } = require('./errors/rezo-error.cjs');
26
26
  const isRezoError = exports.isRezoError = RezoError.isRezoError;
27
27
  const Cancel = exports.Cancel = RezoError;
package/dist/index.d.ts CHANGED
@@ -314,11 +314,19 @@ export declare class RezoFormData extends NodeFormData {
314
314
  toBuffer(): Buffer;
315
315
  /**
316
316
  * Create RezoFormData from object
317
+ * Properly handles nested objects by JSON.stringify-ing them
317
318
  * @param {Record<string, any>} obj - Object to convert
318
319
  * @param {Options} options - Optional RezoFormData options
319
320
  * @returns {RezoFormData}
320
321
  */
321
322
  static fromObject(obj: Record<string, any>, options?: Options): RezoFormData;
323
+ /**
324
+ * Helper to append a value to FormData with proper type handling
325
+ * @param {RezoFormData} formData - The form data to append to
326
+ * @param {string} key - The field name
327
+ * @param {any} value - The value to append
328
+ */
329
+ private static appendValue;
322
330
  /**
323
331
  * Convert to URL query string
324
332
  * Warning: File, Blob, and binary data will be omitted
@@ -314,11 +314,19 @@ export declare class RezoFormData extends NodeFormData {
314
314
  toBuffer(): Buffer;
315
315
  /**
316
316
  * Create RezoFormData from object
317
+ * Properly handles nested objects by JSON.stringify-ing them
317
318
  * @param {Record<string, any>} obj - Object to convert
318
319
  * @param {Options} options - Optional RezoFormData options
319
320
  * @returns {RezoFormData}
320
321
  */
321
322
  static fromObject(obj: Record<string, any>, options?: Options): RezoFormData;
323
+ /**
324
+ * Helper to append a value to FormData with proper type handling
325
+ * @param {RezoFormData} formData - The form data to append to
326
+ * @param {string} key - The field name
327
+ * @param {any} value - The value to append
328
+ */
329
+ private static appendValue;
322
330
  /**
323
331
  * Convert to URL query string
324
332
  * Warning: File, Blob, and binary data will be omitted
@@ -314,11 +314,19 @@ export declare class RezoFormData extends NodeFormData {
314
314
  toBuffer(): Buffer;
315
315
  /**
316
316
  * Create RezoFormData from object
317
+ * Properly handles nested objects by JSON.stringify-ing them
317
318
  * @param {Record<string, any>} obj - Object to convert
318
319
  * @param {Options} options - Optional RezoFormData options
319
320
  * @returns {RezoFormData}
320
321
  */
321
322
  static fromObject(obj: Record<string, any>, options?: Options): RezoFormData;
323
+ /**
324
+ * Helper to append a value to FormData with proper type handling
325
+ * @param {RezoFormData} formData - The form data to append to
326
+ * @param {string} key - The field name
327
+ * @param {any} value - The value to append
328
+ */
329
+ private static appendValue;
322
330
  /**
323
331
  * Convert to URL query string
324
332
  * Warning: File, Blob, and binary data will be omitted
@@ -314,11 +314,19 @@ export declare class RezoFormData extends NodeFormData {
314
314
  toBuffer(): Buffer;
315
315
  /**
316
316
  * Create RezoFormData from object
317
+ * Properly handles nested objects by JSON.stringify-ing them
317
318
  * @param {Record<string, any>} obj - Object to convert
318
319
  * @param {Options} options - Optional RezoFormData options
319
320
  * @returns {RezoFormData}
320
321
  */
321
322
  static fromObject(obj: Record<string, any>, options?: Options): RezoFormData;
323
+ /**
324
+ * Helper to append a value to FormData with proper type handling
325
+ * @param {RezoFormData} formData - The form data to append to
326
+ * @param {string} key - The field name
327
+ * @param {any} value - The value to append
328
+ */
329
+ private static appendValue;
322
330
  /**
323
331
  * Convert to URL query string
324
332
  * Warning: File, Blob, and binary data will be omitted
@@ -314,11 +314,19 @@ export declare class RezoFormData extends NodeFormData {
314
314
  toBuffer(): Buffer;
315
315
  /**
316
316
  * Create RezoFormData from object
317
+ * Properly handles nested objects by JSON.stringify-ing them
317
318
  * @param {Record<string, any>} obj - Object to convert
318
319
  * @param {Options} options - Optional RezoFormData options
319
320
  * @returns {RezoFormData}
320
321
  */
321
322
  static fromObject(obj: Record<string, any>, options?: Options): RezoFormData;
323
+ /**
324
+ * Helper to append a value to FormData with proper type handling
325
+ * @param {RezoFormData} formData - The form data to append to
326
+ * @param {string} key - The field name
327
+ * @param {any} value - The value to append
328
+ */
329
+ private static appendValue;
322
330
  /**
323
331
  * Convert to URL query string
324
332
  * Warning: File, Blob, and binary data will be omitted
@@ -314,11 +314,19 @@ export declare class RezoFormData extends NodeFormData {
314
314
  toBuffer(): Buffer;
315
315
  /**
316
316
  * Create RezoFormData from object
317
+ * Properly handles nested objects by JSON.stringify-ing them
317
318
  * @param {Record<string, any>} obj - Object to convert
318
319
  * @param {Options} options - Optional RezoFormData options
319
320
  * @returns {RezoFormData}
320
321
  */
321
322
  static fromObject(obj: Record<string, any>, options?: Options): RezoFormData;
323
+ /**
324
+ * Helper to append a value to FormData with proper type handling
325
+ * @param {RezoFormData} formData - The form data to append to
326
+ * @param {string} key - The field name
327
+ * @param {any} value - The value to append
328
+ */
329
+ private static appendValue;
322
330
  /**
323
331
  * Convert to URL query string
324
332
  * Warning: File, Blob, and binary data will be omitted
@@ -314,11 +314,19 @@ export declare class RezoFormData extends NodeFormData {
314
314
  toBuffer(): Buffer;
315
315
  /**
316
316
  * Create RezoFormData from object
317
+ * Properly handles nested objects by JSON.stringify-ing them
317
318
  * @param {Record<string, any>} obj - Object to convert
318
319
  * @param {Options} options - Optional RezoFormData options
319
320
  * @returns {RezoFormData}
320
321
  */
321
322
  static fromObject(obj: Record<string, any>, options?: Options): RezoFormData;
323
+ /**
324
+ * Helper to append a value to FormData with proper type handling
325
+ * @param {RezoFormData} formData - The form data to append to
326
+ * @param {string} key - The field name
327
+ * @param {any} value - The value to append
328
+ */
329
+ private static appendValue;
322
330
  /**
323
331
  * Convert to URL query string
324
332
  * Warning: File, Blob, and binary data will be omitted
@@ -1,36 +1,36 @@
1
- const _mod_dq9ozb = require('./crawler.cjs');
2
- exports.Crawler = _mod_dq9ozb.Crawler;;
3
- const _mod_d0jsak = require('./crawler-options.cjs');
4
- exports.CrawlerOptions = _mod_d0jsak.CrawlerOptions;;
5
- const _mod_wbhzam = require('../cache/file-cacher.cjs');
6
- exports.FileCacher = _mod_wbhzam.FileCacher;;
7
- const _mod_ic6xnp = require('../cache/url-store.cjs');
8
- exports.UrlStore = _mod_ic6xnp.UrlStore;;
9
- const _mod_u5fn2x = require('./addon/oxylabs/index.cjs');
10
- exports.Oxylabs = _mod_u5fn2x.Oxylabs;;
11
- const _mod_mc3i9t = require('./addon/oxylabs/options.cjs');
12
- exports.OXYLABS_BROWSER_TYPES = _mod_mc3i9t.OXYLABS_BROWSER_TYPES;
13
- exports.OXYLABS_COMMON_LOCALES = _mod_mc3i9t.OXYLABS_COMMON_LOCALES;
14
- exports.OXYLABS_COMMON_GEO_LOCATIONS = _mod_mc3i9t.OXYLABS_COMMON_GEO_LOCATIONS;
15
- exports.OXYLABS_US_STATES = _mod_mc3i9t.OXYLABS_US_STATES;
16
- exports.OXYLABS_EUROPEAN_COUNTRIES = _mod_mc3i9t.OXYLABS_EUROPEAN_COUNTRIES;
17
- exports.OXYLABS_ASIAN_COUNTRIES = _mod_mc3i9t.OXYLABS_ASIAN_COUNTRIES;
18
- exports.getRandomOxylabsBrowserType = _mod_mc3i9t.getRandomBrowserType;
19
- exports.getRandomOxylabsLocale = _mod_mc3i9t.getRandomLocale;
20
- exports.getRandomOxylabsGeoLocation = _mod_mc3i9t.getRandomGeoLocation;;
21
- const _mod_d70cyo = require('./addon/decodo/index.cjs');
22
- exports.Decodo = _mod_d70cyo.Decodo;;
23
- const _mod_cmnvxg = require('./addon/decodo/options.cjs');
24
- exports.DECODO_DEVICE_TYPES = _mod_cmnvxg.DECODO_DEVICE_TYPES;
25
- exports.DECODO_HEADLESS_MODES = _mod_cmnvxg.DECODO_HEADLESS_MODES;
26
- exports.DECODO_COMMON_LOCALES = _mod_cmnvxg.DECODO_COMMON_LOCALES;
27
- exports.DECODO_COMMON_COUNTRIES = _mod_cmnvxg.DECODO_COMMON_COUNTRIES;
28
- exports.DECODO_EUROPEAN_COUNTRIES = _mod_cmnvxg.DECODO_EUROPEAN_COUNTRIES;
29
- exports.DECODO_ASIAN_COUNTRIES = _mod_cmnvxg.DECODO_ASIAN_COUNTRIES;
30
- exports.DECODO_US_STATES = _mod_cmnvxg.DECODO_US_STATES;
31
- exports.DECODO_COMMON_CITIES = _mod_cmnvxg.DECODO_COMMON_CITIES;
32
- exports.getRandomDecodoDeviceType = _mod_cmnvxg.getRandomDeviceType;
33
- exports.getRandomDecodoLocale = _mod_cmnvxg.getRandomLocale;
34
- exports.getRandomDecodoCountry = _mod_cmnvxg.getRandomCountry;
35
- exports.getRandomDecodoCity = _mod_cmnvxg.getRandomCity;
36
- exports.generateDecodoSessionId = _mod_cmnvxg.generateSessionId;;
1
+ const _mod_61gqt8 = require('./crawler.cjs');
2
+ exports.Crawler = _mod_61gqt8.Crawler;;
3
+ const _mod_s20ywb = require('./crawler-options.cjs');
4
+ exports.CrawlerOptions = _mod_s20ywb.CrawlerOptions;;
5
+ const _mod_slgnf8 = require('../cache/file-cacher.cjs');
6
+ exports.FileCacher = _mod_slgnf8.FileCacher;;
7
+ const _mod_jvu3uj = require('../cache/url-store.cjs');
8
+ exports.UrlStore = _mod_jvu3uj.UrlStore;;
9
+ const _mod_v2pwhj = require('./addon/oxylabs/index.cjs');
10
+ exports.Oxylabs = _mod_v2pwhj.Oxylabs;;
11
+ const _mod_lxafyd = require('./addon/oxylabs/options.cjs');
12
+ exports.OXYLABS_BROWSER_TYPES = _mod_lxafyd.OXYLABS_BROWSER_TYPES;
13
+ exports.OXYLABS_COMMON_LOCALES = _mod_lxafyd.OXYLABS_COMMON_LOCALES;
14
+ exports.OXYLABS_COMMON_GEO_LOCATIONS = _mod_lxafyd.OXYLABS_COMMON_GEO_LOCATIONS;
15
+ exports.OXYLABS_US_STATES = _mod_lxafyd.OXYLABS_US_STATES;
16
+ exports.OXYLABS_EUROPEAN_COUNTRIES = _mod_lxafyd.OXYLABS_EUROPEAN_COUNTRIES;
17
+ exports.OXYLABS_ASIAN_COUNTRIES = _mod_lxafyd.OXYLABS_ASIAN_COUNTRIES;
18
+ exports.getRandomOxylabsBrowserType = _mod_lxafyd.getRandomBrowserType;
19
+ exports.getRandomOxylabsLocale = _mod_lxafyd.getRandomLocale;
20
+ exports.getRandomOxylabsGeoLocation = _mod_lxafyd.getRandomGeoLocation;;
21
+ const _mod_wknbgy = require('./addon/decodo/index.cjs');
22
+ exports.Decodo = _mod_wknbgy.Decodo;;
23
+ const _mod_wp7ex5 = require('./addon/decodo/options.cjs');
24
+ exports.DECODO_DEVICE_TYPES = _mod_wp7ex5.DECODO_DEVICE_TYPES;
25
+ exports.DECODO_HEADLESS_MODES = _mod_wp7ex5.DECODO_HEADLESS_MODES;
26
+ exports.DECODO_COMMON_LOCALES = _mod_wp7ex5.DECODO_COMMON_LOCALES;
27
+ exports.DECODO_COMMON_COUNTRIES = _mod_wp7ex5.DECODO_COMMON_COUNTRIES;
28
+ exports.DECODO_EUROPEAN_COUNTRIES = _mod_wp7ex5.DECODO_EUROPEAN_COUNTRIES;
29
+ exports.DECODO_ASIAN_COUNTRIES = _mod_wp7ex5.DECODO_ASIAN_COUNTRIES;
30
+ exports.DECODO_US_STATES = _mod_wp7ex5.DECODO_US_STATES;
31
+ exports.DECODO_COMMON_CITIES = _mod_wp7ex5.DECODO_COMMON_CITIES;
32
+ exports.getRandomDecodoDeviceType = _mod_wp7ex5.getRandomDeviceType;
33
+ exports.getRandomDecodoLocale = _mod_wp7ex5.getRandomLocale;
34
+ exports.getRandomDecodoCountry = _mod_wp7ex5.getRandomCountry;
35
+ exports.getRandomDecodoCity = _mod_wp7ex5.getRandomCity;
36
+ exports.generateDecodoSessionId = _mod_wp7ex5.generateSessionId;;
@@ -1,8 +1,8 @@
1
1
  const { SocksProxyAgent: RezoSocksProxy } = require("socks-proxy-agent");
2
2
  const { HttpsProxyAgent: RezoHttpsSocks } = require("https-proxy-agent");
3
3
  const { HttpProxyAgent: RezoHttpSocks } = require("http-proxy-agent");
4
- const _mod_p28kf5 = require('./manager.cjs');
5
- exports.ProxyManager = _mod_p28kf5.ProxyManager;;
4
+ const _mod_c6k1hi = require('./manager.cjs');
5
+ exports.ProxyManager = _mod_c6k1hi.ProxyManager;;
6
6
  function createOptions(uri, opts) {
7
7
  if (uri instanceof URL || typeof uri === "string") {
8
8
  return {
@@ -1,8 +1,8 @@
1
- const _mod_5bxokv = require('./queue.cjs');
2
- exports.RezoQueue = _mod_5bxokv.RezoQueue;;
3
- const _mod_12mknl = require('./http-queue.cjs');
4
- exports.HttpQueue = _mod_12mknl.HttpQueue;
5
- exports.extractDomain = _mod_12mknl.extractDomain;;
6
- const _mod_u9vq92 = require('./types.cjs');
7
- exports.Priority = _mod_u9vq92.Priority;
8
- exports.HttpMethodPriority = _mod_u9vq92.HttpMethodPriority;;
1
+ const _mod_ywac6g = require('./queue.cjs');
2
+ exports.RezoQueue = _mod_ywac6g.RezoQueue;;
3
+ const _mod_id4rdx = require('./http-queue.cjs');
4
+ exports.HttpQueue = _mod_id4rdx.HttpQueue;
5
+ exports.extractDomain = _mod_id4rdx.extractDomain;;
6
+ const _mod_dnemth = require('./types.cjs');
7
+ exports.Priority = _mod_dnemth.Priority;
8
+ exports.HttpMethodPriority = _mod_dnemth.HttpMethodPriority;;
@@ -71,16 +71,73 @@ class RezoFormData extends NodeFormData {
71
71
  static fromObject(obj, options) {
72
72
  const formData = new RezoFormData(options);
73
73
  for (const [key, value] of Object.entries(obj)) {
74
- if (Array.isArray(value)) {
75
- for (const item of value) {
76
- formData.append(key, item);
77
- }
78
- } else {
79
- formData.append(key, value);
80
- }
74
+ RezoFormData.appendValue(formData, key, value);
81
75
  }
82
76
  return formData;
83
77
  }
78
+ static appendValue(formData, key, value) {
79
+ if (value === null || value === undefined) {
80
+ return;
81
+ }
82
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
83
+ formData.append(key, String(value));
84
+ return;
85
+ }
86
+ if (Buffer.isBuffer(value)) {
87
+ formData.append(key, value, {
88
+ contentType: "application/octet-stream"
89
+ });
90
+ return;
91
+ }
92
+ if (value instanceof Uint8Array) {
93
+ formData.append(key, Buffer.from(value), {
94
+ contentType: "application/octet-stream"
95
+ });
96
+ return;
97
+ }
98
+ if (value instanceof Readable) {
99
+ formData.append(key, value);
100
+ return;
101
+ }
102
+ if (typeof File !== "undefined" && value instanceof File) {
103
+ formData.append(key, value, {
104
+ filename: value.name,
105
+ contentType: value.type || "application/octet-stream"
106
+ });
107
+ return;
108
+ }
109
+ if (typeof Blob !== "undefined" && value instanceof Blob) {
110
+ formData.append(key, value, {
111
+ contentType: value.type || "application/octet-stream"
112
+ });
113
+ return;
114
+ }
115
+ if (Array.isArray(value)) {
116
+ for (const item of value) {
117
+ RezoFormData.appendValue(formData, key, item);
118
+ }
119
+ return;
120
+ }
121
+ if (typeof value === "object" && value !== null && "value" in value && (value.filename || value.contentType)) {
122
+ const opts = {};
123
+ if (value.filename)
124
+ opts.filename = value.filename;
125
+ if (value.contentType)
126
+ opts.contentType = value.contentType;
127
+ formData.append(key, value.value, opts);
128
+ return;
129
+ }
130
+ if (typeof value === "object" && value !== null) {
131
+ const jsonString = JSON.stringify(value);
132
+ const jsonBuffer = Buffer.from(jsonString, "utf8");
133
+ formData.append(key, jsonBuffer, {
134
+ filename: `${key}.json`,
135
+ contentType: "application/json"
136
+ });
137
+ return;
138
+ }
139
+ formData.append(key, String(value));
140
+ }
84
141
  async toUrlQueryString(convertBinaryToBase64 = false) {
85
142
  const params = new URLSearchParams;
86
143
  let hasOmittedData = false;
@@ -71,16 +71,73 @@ export class RezoFormData extends NodeFormData {
71
71
  static fromObject(obj, options) {
72
72
  const formData = new RezoFormData(options);
73
73
  for (const [key, value] of Object.entries(obj)) {
74
- if (Array.isArray(value)) {
75
- for (const item of value) {
76
- formData.append(key, item);
77
- }
78
- } else {
79
- formData.append(key, value);
80
- }
74
+ RezoFormData.appendValue(formData, key, value);
81
75
  }
82
76
  return formData;
83
77
  }
78
+ static appendValue(formData, key, value) {
79
+ if (value === null || value === undefined) {
80
+ return;
81
+ }
82
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
83
+ formData.append(key, String(value));
84
+ return;
85
+ }
86
+ if (Buffer.isBuffer(value)) {
87
+ formData.append(key, value, {
88
+ contentType: "application/octet-stream"
89
+ });
90
+ return;
91
+ }
92
+ if (value instanceof Uint8Array) {
93
+ formData.append(key, Buffer.from(value), {
94
+ contentType: "application/octet-stream"
95
+ });
96
+ return;
97
+ }
98
+ if (value instanceof Readable) {
99
+ formData.append(key, value);
100
+ return;
101
+ }
102
+ if (typeof File !== "undefined" && value instanceof File) {
103
+ formData.append(key, value, {
104
+ filename: value.name,
105
+ contentType: value.type || "application/octet-stream"
106
+ });
107
+ return;
108
+ }
109
+ if (typeof Blob !== "undefined" && value instanceof Blob) {
110
+ formData.append(key, value, {
111
+ contentType: value.type || "application/octet-stream"
112
+ });
113
+ return;
114
+ }
115
+ if (Array.isArray(value)) {
116
+ for (const item of value) {
117
+ RezoFormData.appendValue(formData, key, item);
118
+ }
119
+ return;
120
+ }
121
+ if (typeof value === "object" && value !== null && "value" in value && (value.filename || value.contentType)) {
122
+ const opts = {};
123
+ if (value.filename)
124
+ opts.filename = value.filename;
125
+ if (value.contentType)
126
+ opts.contentType = value.contentType;
127
+ formData.append(key, value.value, opts);
128
+ return;
129
+ }
130
+ if (typeof value === "object" && value !== null) {
131
+ const jsonString = JSON.stringify(value);
132
+ const jsonBuffer = Buffer.from(jsonString, "utf8");
133
+ formData.append(key, jsonBuffer, {
134
+ filename: `${key}.json`,
135
+ contentType: "application/json"
136
+ });
137
+ return;
138
+ }
139
+ formData.append(key, String(value));
140
+ }
84
141
  async toUrlQueryString(convertBinaryToBase64 = false) {
85
142
  const params = new URLSearchParams;
86
143
  let hasOmittedData = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rezo",
3
- "version": "1.0.13",
3
+ "version": "1.0.14",
4
4
  "description": "Lightning-fast, enterprise-grade HTTP client for modern JavaScript. Full HTTP/2 support, intelligent cookie management, multiple adapters (HTTP, Fetch, cURL, XHR), streaming, proxy support (HTTP/HTTPS/SOCKS), and cross-environment compatibility.",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",