rezo 1.0.43 → 1.0.45

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 (79) hide show
  1. package/dist/adapters/entries/curl.d.ts +115 -0
  2. package/dist/adapters/entries/fetch.d.ts +115 -0
  3. package/dist/adapters/entries/http.d.ts +115 -0
  4. package/dist/adapters/entries/http2.d.ts +115 -0
  5. package/dist/adapters/entries/react-native.d.ts +115 -0
  6. package/dist/adapters/entries/xhr.d.ts +115 -0
  7. package/dist/adapters/fetch.cjs +18 -0
  8. package/dist/adapters/fetch.js +18 -0
  9. package/dist/adapters/http.cjs +18 -0
  10. package/dist/adapters/http.js +18 -0
  11. package/dist/adapters/http2.cjs +18 -0
  12. package/dist/adapters/http2.js +18 -0
  13. package/dist/adapters/index.cjs +6 -6
  14. package/dist/adapters/xhr.cjs +19 -0
  15. package/dist/adapters/xhr.js +19 -0
  16. package/dist/cache/index.cjs +9 -15
  17. package/dist/cache/index.js +0 -3
  18. package/dist/core/hooks.cjs +4 -2
  19. package/dist/core/hooks.js +4 -2
  20. package/dist/crawler/addon/decodo/index.cjs +1 -0
  21. package/dist/crawler/addon/decodo/index.js +1 -0
  22. package/dist/crawler/crawler-options.cjs +1 -0
  23. package/dist/crawler/crawler-options.js +1 -0
  24. package/dist/{plugin → crawler}/crawler.cjs +392 -32
  25. package/dist/{plugin → crawler}/crawler.js +392 -32
  26. package/dist/crawler/index.cjs +40 -0
  27. package/dist/{plugin → crawler}/index.js +4 -2
  28. package/dist/crawler/plugin/file-cacher.cjs +19 -0
  29. package/dist/crawler/plugin/file-cacher.js +19 -0
  30. package/dist/crawler/plugin/index.cjs +1 -0
  31. package/dist/crawler/plugin/index.js +1 -0
  32. package/dist/crawler/plugin/navigation-history.cjs +43 -0
  33. package/dist/crawler/plugin/navigation-history.js +43 -0
  34. package/dist/crawler/plugin/robots-txt.cjs +2 -0
  35. package/dist/crawler/plugin/robots-txt.js +2 -0
  36. package/dist/crawler/plugin/url-store.cjs +18 -0
  37. package/dist/crawler/plugin/url-store.js +18 -0
  38. package/dist/crawler.d.ts +430 -172
  39. package/dist/entries/crawler.cjs +5 -5
  40. package/dist/entries/crawler.js +2 -2
  41. package/dist/index.cjs +27 -27
  42. package/dist/index.d.ts +115 -0
  43. package/dist/internal/agents/index.cjs +10 -10
  44. package/dist/platform/browser.d.ts +115 -0
  45. package/dist/platform/bun.d.ts +115 -0
  46. package/dist/platform/deno.d.ts +115 -0
  47. package/dist/platform/node.d.ts +115 -0
  48. package/dist/platform/react-native.d.ts +115 -0
  49. package/dist/platform/worker.d.ts +115 -0
  50. package/dist/proxy/index.cjs +5 -5
  51. package/dist/proxy/index.js +1 -1
  52. package/dist/queue/index.cjs +8 -8
  53. package/dist/responses/universal/index.cjs +11 -11
  54. package/dist/utils/rate-limit-wait.cjs +217 -0
  55. package/dist/utils/rate-limit-wait.js +208 -0
  56. package/package.json +2 -6
  57. package/dist/cache/file-cacher.cjs +0 -270
  58. package/dist/cache/file-cacher.js +0 -267
  59. package/dist/cache/navigation-history.cjs +0 -298
  60. package/dist/cache/navigation-history.js +0 -296
  61. package/dist/cache/url-store.cjs +0 -294
  62. package/dist/cache/url-store.js +0 -291
  63. package/dist/plugin/addon/decodo/index.cjs +0 -1
  64. package/dist/plugin/addon/decodo/index.js +0 -1
  65. package/dist/plugin/crawler-options.cjs +0 -1
  66. package/dist/plugin/crawler-options.js +0 -1
  67. package/dist/plugin/index.cjs +0 -36
  68. /package/dist/{plugin → crawler}/addon/decodo/options.cjs +0 -0
  69. /package/dist/{plugin → crawler}/addon/decodo/options.js +0 -0
  70. /package/dist/{plugin → crawler}/addon/decodo/types.cjs +0 -0
  71. /package/dist/{plugin → crawler}/addon/decodo/types.js +0 -0
  72. /package/dist/{plugin → crawler}/addon/oxylabs/index.cjs +0 -0
  73. /package/dist/{plugin → crawler}/addon/oxylabs/index.js +0 -0
  74. /package/dist/{plugin → crawler}/addon/oxylabs/options.cjs +0 -0
  75. /package/dist/{plugin → crawler}/addon/oxylabs/options.js +0 -0
  76. /package/dist/{plugin → crawler}/addon/oxylabs/types.cjs +0 -0
  77. /package/dist/{plugin → crawler}/addon/oxylabs/types.js +0 -0
  78. /package/dist/{plugin → crawler}/scraper.cjs +0 -0
  79. /package/dist/{plugin → crawler}/scraper.js +0 -0
@@ -1,5 +1,5 @@
1
- const _mod_l31jyt = require('../plugin/crawler.cjs');
2
- exports.Crawler = _mod_l31jyt.Crawler;;
3
- const _mod_2ht78p = require('../plugin/crawler-options.cjs');
4
- exports.CrawlerOptions = _mod_2ht78p.CrawlerOptions;
5
- exports.Domain = _mod_2ht78p.Domain;;
1
+ const _mod_xbq6an = require('../crawler/crawler.cjs');
2
+ exports.Crawler = _mod_xbq6an.Crawler;;
3
+ const _mod_8a6dxq = require('../crawler/crawler-options.cjs');
4
+ exports.CrawlerOptions = _mod_8a6dxq.CrawlerOptions;
5
+ exports.Domain = _mod_8a6dxq.Domain;;
@@ -1,2 +1,2 @@
1
- export { Crawler } from '../plugin/crawler.js';
2
- export { CrawlerOptions, Domain } from '../plugin/crawler-options.js';
1
+ export { Crawler } from '../crawler/crawler.js';
2
+ export { CrawlerOptions, Domain } from '../crawler/crawler-options.js';
package/dist/index.cjs CHANGED
@@ -1,30 +1,30 @@
1
- const _mod_ez6b8t = require('./core/rezo.cjs');
2
- exports.Rezo = _mod_ez6b8t.Rezo;
3
- exports.createRezoInstance = _mod_ez6b8t.createRezoInstance;
4
- exports.createDefaultInstance = _mod_ez6b8t.createDefaultInstance;;
5
- const _mod_3tc7ap = require('./errors/rezo-error.cjs');
6
- exports.RezoError = _mod_3tc7ap.RezoError;
7
- exports.RezoErrorCode = _mod_3tc7ap.RezoErrorCode;;
8
- const _mod_43q7ms = require('./utils/headers.cjs');
9
- exports.RezoHeaders = _mod_43q7ms.RezoHeaders;;
10
- const _mod_g1j1lv = require('./utils/form-data.cjs');
11
- exports.RezoFormData = _mod_g1j1lv.RezoFormData;;
12
- const _mod_uvyhfd = require('./utils/cookies.cjs');
13
- exports.RezoCookieJar = _mod_uvyhfd.RezoCookieJar;
14
- exports.Cookie = _mod_uvyhfd.Cookie;;
15
- const _mod_u7n5iq = require('./utils/curl.cjs');
16
- exports.toCurl = _mod_u7n5iq.toCurl;
17
- exports.fromCurl = _mod_u7n5iq.fromCurl;;
18
- const _mod_dk9wem = require('./core/hooks.cjs');
19
- exports.createDefaultHooks = _mod_dk9wem.createDefaultHooks;
20
- exports.mergeHooks = _mod_dk9wem.mergeHooks;;
21
- const _mod_pe26um = require('./proxy/manager.cjs');
22
- exports.ProxyManager = _mod_pe26um.ProxyManager;;
23
- const _mod_zl76ch = require('./queue/index.cjs');
24
- exports.RezoQueue = _mod_zl76ch.RezoQueue;
25
- exports.HttpQueue = _mod_zl76ch.HttpQueue;
26
- exports.Priority = _mod_zl76ch.Priority;
27
- exports.HttpMethodPriority = _mod_zl76ch.HttpMethodPriority;;
1
+ const _mod_oop3nu = require('./core/rezo.cjs');
2
+ exports.Rezo = _mod_oop3nu.Rezo;
3
+ exports.createRezoInstance = _mod_oop3nu.createRezoInstance;
4
+ exports.createDefaultInstance = _mod_oop3nu.createDefaultInstance;;
5
+ const _mod_39unfu = require('./errors/rezo-error.cjs');
6
+ exports.RezoError = _mod_39unfu.RezoError;
7
+ exports.RezoErrorCode = _mod_39unfu.RezoErrorCode;;
8
+ const _mod_bkzmv4 = require('./utils/headers.cjs');
9
+ exports.RezoHeaders = _mod_bkzmv4.RezoHeaders;;
10
+ const _mod_3i5b1l = require('./utils/form-data.cjs');
11
+ exports.RezoFormData = _mod_3i5b1l.RezoFormData;;
12
+ const _mod_rrz4g7 = require('./utils/cookies.cjs');
13
+ exports.RezoCookieJar = _mod_rrz4g7.RezoCookieJar;
14
+ exports.Cookie = _mod_rrz4g7.Cookie;;
15
+ const _mod_zlh68v = require('./utils/curl.cjs');
16
+ exports.toCurl = _mod_zlh68v.toCurl;
17
+ exports.fromCurl = _mod_zlh68v.fromCurl;;
18
+ const _mod_excrbc = require('./core/hooks.cjs');
19
+ exports.createDefaultHooks = _mod_excrbc.createDefaultHooks;
20
+ exports.mergeHooks = _mod_excrbc.mergeHooks;;
21
+ const _mod_xgb0br = require('./proxy/manager.cjs');
22
+ exports.ProxyManager = _mod_xgb0br.ProxyManager;;
23
+ const _mod_9gi7fv = require('./queue/index.cjs');
24
+ exports.RezoQueue = _mod_9gi7fv.RezoQueue;
25
+ exports.HttpQueue = _mod_9gi7fv.HttpQueue;
26
+ exports.Priority = _mod_9gi7fv.Priority;
27
+ exports.HttpMethodPriority = _mod_9gi7fv.HttpMethodPriority;;
28
28
  const { RezoError } = require('./errors/rezo-error.cjs');
29
29
  const isRezoError = exports.isRezoError = RezoError.isRezoError;
30
30
  const Cancel = exports.Cancel = RezoError;
package/dist/index.d.ts CHANGED
@@ -1416,6 +1416,35 @@ export type OnTimeoutHook = (event: TimeoutEvent, config: RezoConfig) => void;
1416
1416
  * Use for cleanup, logging
1417
1417
  */
1418
1418
  export type OnAbortHook = (event: AbortEvent, config: RezoConfig) => void;
1419
+ /**
1420
+ * Rate limit wait event data - fired when waiting due to rate limiting
1421
+ */
1422
+ export interface RateLimitWaitEvent {
1423
+ /** HTTP status code that triggered the wait (e.g., 429, 503) */
1424
+ status: number;
1425
+ /** Time to wait in milliseconds */
1426
+ waitTime: number;
1427
+ /** Current wait attempt number (1-indexed) */
1428
+ attempt: number;
1429
+ /** Maximum wait attempts configured */
1430
+ maxAttempts: number;
1431
+ /** Where the wait time was extracted from */
1432
+ source: "header" | "body" | "function" | "default";
1433
+ /** The header or body path used (if applicable) */
1434
+ sourcePath?: string;
1435
+ /** URL being requested */
1436
+ url: string;
1437
+ /** HTTP method of the request */
1438
+ method: string;
1439
+ /** Timestamp when the wait started */
1440
+ timestamp: number;
1441
+ }
1442
+ /**
1443
+ * Hook called when rate limit wait occurs
1444
+ * Informational only - cannot abort the wait
1445
+ * Use for logging, monitoring, alerting
1446
+ */
1447
+ export type OnRateLimitWaitHook = (event: RateLimitWaitEvent, config: RezoConfig) => void | Promise<void>;
1419
1448
  /**
1420
1449
  * Hook called before a proxy is selected
1421
1450
  * Can return a specific proxy to override selection
@@ -1496,6 +1525,7 @@ export interface RezoHooks {
1496
1525
  onTls: OnTlsHook[];
1497
1526
  onTimeout: OnTimeoutHook[];
1498
1527
  onAbort: OnAbortHook[];
1528
+ onRateLimitWait: OnRateLimitWaitHook[];
1499
1529
  }
1500
1530
  /**
1501
1531
  * Create empty hooks object with all arrays initialized
@@ -2552,6 +2582,91 @@ export interface RezoRequestConfig<D = any> {
2552
2582
  /** Weather to stop or continue retry when certain condition is met*/
2553
2583
  condition?: (error: RezoError) => boolean | Promise<boolean>;
2554
2584
  };
2585
+ /**
2586
+ * Rate limit wait configuration - wait and retry when receiving rate limit responses.
2587
+ *
2588
+ * This feature runs BEFORE the retry system. When a rate-limiting status code is received,
2589
+ * the client will wait for the specified time and automatically retry the request.
2590
+ *
2591
+ * **Basic Usage:**
2592
+ * - `waitOnStatus: true` - Enable waiting on 429 status (default behavior)
2593
+ * - `waitOnStatus: [429, 503]` - Enable waiting on specific status codes
2594
+ *
2595
+ * **Wait Time Sources:**
2596
+ * - `'retry-after'` - Use standard Retry-After header (default)
2597
+ * - `{ header: 'X-RateLimit-Reset' }` - Use custom header
2598
+ * - `{ body: 'retry_after' }` - Extract from JSON response body
2599
+ * - Custom function for complex logic
2600
+ *
2601
+ * @example
2602
+ * ```typescript
2603
+ * // Wait on 429 using Retry-After header
2604
+ * await rezo.get(url, { waitOnStatus: true });
2605
+ *
2606
+ * // Wait on 429 using custom header
2607
+ * await rezo.get(url, {
2608
+ * waitOnStatus: true,
2609
+ * waitTimeSource: { header: 'X-RateLimit-Reset' }
2610
+ * });
2611
+ *
2612
+ * // Wait on 429 extracting time from JSON body
2613
+ * await rezo.get(url, {
2614
+ * waitOnStatus: true,
2615
+ * waitTimeSource: { body: 'data.retry_after' }
2616
+ * });
2617
+ *
2618
+ * // Custom function for complex APIs
2619
+ * await rezo.get(url, {
2620
+ * waitOnStatus: [429, 503],
2621
+ * waitTimeSource: (response) => {
2622
+ * const reset = response.headers.get('x-ratelimit-reset');
2623
+ * return reset ? parseInt(reset) - Math.floor(Date.now() / 1000) : null;
2624
+ * }
2625
+ * });
2626
+ * ```
2627
+ */
2628
+ waitOnStatus?: boolean | number[];
2629
+ /**
2630
+ * Where to extract the wait time from when rate-limited.
2631
+ *
2632
+ * - `'retry-after'` - Standard Retry-After header (default)
2633
+ * - `{ header: string }` - Custom header name (e.g., 'X-RateLimit-Reset')
2634
+ * - `{ body: string }` - JSON path in response body (e.g., 'data.retry_after', 'wait_seconds')
2635
+ * - Function - Custom logic receiving the response, return seconds to wait or null
2636
+ *
2637
+ * @default 'retry-after'
2638
+ */
2639
+ waitTimeSource?: "retry-after" | {
2640
+ header: string;
2641
+ } | {
2642
+ body: string;
2643
+ } | ((response: {
2644
+ status: number;
2645
+ headers: RezoHeaders;
2646
+ data?: any;
2647
+ }) => number | null);
2648
+ /**
2649
+ * Maximum time to wait for rate limit in milliseconds.
2650
+ * If the extracted wait time exceeds this, the request will fail instead of waiting.
2651
+ * Set to 0 for unlimited wait time.
2652
+ *
2653
+ * @default 60000 (60 seconds)
2654
+ */
2655
+ maxWaitTime?: number;
2656
+ /**
2657
+ * Default wait time in milliseconds if the wait time source returns nothing.
2658
+ * Used as fallback when Retry-After header or body path is not present.
2659
+ *
2660
+ * @default 1000 (1 second)
2661
+ */
2662
+ defaultWaitTime?: number;
2663
+ /**
2664
+ * Maximum number of wait attempts before giving up.
2665
+ * After this many waits, the request will proceed to retry logic or fail.
2666
+ *
2667
+ * @default 3
2668
+ */
2669
+ maxWaitAttempts?: number;
2555
2670
  /** Whether to use a secure context for HTTPS requests */
2556
2671
  useSecureContext?: boolean;
2557
2672
  /** Custom secure context for TLS connections */
@@ -1,10 +1,10 @@
1
- const _mod_7qp1aa = require('./base.cjs');
2
- exports.Agent = _mod_7qp1aa.Agent;;
3
- const _mod_p65m0p = require('./http-proxy.cjs');
4
- exports.HttpProxyAgent = _mod_p65m0p.HttpProxyAgent;;
5
- const _mod_vvhz9m = require('./https-proxy.cjs');
6
- exports.HttpsProxyAgent = _mod_vvhz9m.HttpsProxyAgent;;
7
- const _mod_jsl1v1 = require('./socks-proxy.cjs');
8
- exports.SocksProxyAgent = _mod_jsl1v1.SocksProxyAgent;;
9
- const _mod_xeq0c5 = require('./socks-client.cjs');
10
- exports.SocksClient = _mod_xeq0c5.SocksClient;;
1
+ const _mod_ii5t0u = require('./base.cjs');
2
+ exports.Agent = _mod_ii5t0u.Agent;;
3
+ const _mod_ul6g5e = require('./http-proxy.cjs');
4
+ exports.HttpProxyAgent = _mod_ul6g5e.HttpProxyAgent;;
5
+ const _mod_nwv5nl = require('./https-proxy.cjs');
6
+ exports.HttpsProxyAgent = _mod_nwv5nl.HttpsProxyAgent;;
7
+ const _mod_rcnb54 = require('./socks-proxy.cjs');
8
+ exports.SocksProxyAgent = _mod_rcnb54.SocksProxyAgent;;
9
+ const _mod_g5wt9x = require('./socks-client.cjs');
10
+ exports.SocksClient = _mod_g5wt9x.SocksClient;;
@@ -1416,6 +1416,35 @@ export type OnTimeoutHook = (event: TimeoutEvent, config: RezoConfig) => void;
1416
1416
  * Use for cleanup, logging
1417
1417
  */
1418
1418
  export type OnAbortHook = (event: AbortEvent, config: RezoConfig) => void;
1419
+ /**
1420
+ * Rate limit wait event data - fired when waiting due to rate limiting
1421
+ */
1422
+ export interface RateLimitWaitEvent {
1423
+ /** HTTP status code that triggered the wait (e.g., 429, 503) */
1424
+ status: number;
1425
+ /** Time to wait in milliseconds */
1426
+ waitTime: number;
1427
+ /** Current wait attempt number (1-indexed) */
1428
+ attempt: number;
1429
+ /** Maximum wait attempts configured */
1430
+ maxAttempts: number;
1431
+ /** Where the wait time was extracted from */
1432
+ source: "header" | "body" | "function" | "default";
1433
+ /** The header or body path used (if applicable) */
1434
+ sourcePath?: string;
1435
+ /** URL being requested */
1436
+ url: string;
1437
+ /** HTTP method of the request */
1438
+ method: string;
1439
+ /** Timestamp when the wait started */
1440
+ timestamp: number;
1441
+ }
1442
+ /**
1443
+ * Hook called when rate limit wait occurs
1444
+ * Informational only - cannot abort the wait
1445
+ * Use for logging, monitoring, alerting
1446
+ */
1447
+ export type OnRateLimitWaitHook = (event: RateLimitWaitEvent, config: RezoConfig) => void | Promise<void>;
1419
1448
  /**
1420
1449
  * Hook called before a proxy is selected
1421
1450
  * Can return a specific proxy to override selection
@@ -1496,6 +1525,7 @@ export interface RezoHooks {
1496
1525
  onTls: OnTlsHook[];
1497
1526
  onTimeout: OnTimeoutHook[];
1498
1527
  onAbort: OnAbortHook[];
1528
+ onRateLimitWait: OnRateLimitWaitHook[];
1499
1529
  }
1500
1530
  /**
1501
1531
  * Create empty hooks object with all arrays initialized
@@ -2426,6 +2456,91 @@ export interface RezoRequestConfig<D = any> {
2426
2456
  /** Weather to stop or continue retry when certain condition is met*/
2427
2457
  condition?: (error: RezoError) => boolean | Promise<boolean>;
2428
2458
  };
2459
+ /**
2460
+ * Rate limit wait configuration - wait and retry when receiving rate limit responses.
2461
+ *
2462
+ * This feature runs BEFORE the retry system. When a rate-limiting status code is received,
2463
+ * the client will wait for the specified time and automatically retry the request.
2464
+ *
2465
+ * **Basic Usage:**
2466
+ * - `waitOnStatus: true` - Enable waiting on 429 status (default behavior)
2467
+ * - `waitOnStatus: [429, 503]` - Enable waiting on specific status codes
2468
+ *
2469
+ * **Wait Time Sources:**
2470
+ * - `'retry-after'` - Use standard Retry-After header (default)
2471
+ * - `{ header: 'X-RateLimit-Reset' }` - Use custom header
2472
+ * - `{ body: 'retry_after' }` - Extract from JSON response body
2473
+ * - Custom function for complex logic
2474
+ *
2475
+ * @example
2476
+ * ```typescript
2477
+ * // Wait on 429 using Retry-After header
2478
+ * await rezo.get(url, { waitOnStatus: true });
2479
+ *
2480
+ * // Wait on 429 using custom header
2481
+ * await rezo.get(url, {
2482
+ * waitOnStatus: true,
2483
+ * waitTimeSource: { header: 'X-RateLimit-Reset' }
2484
+ * });
2485
+ *
2486
+ * // Wait on 429 extracting time from JSON body
2487
+ * await rezo.get(url, {
2488
+ * waitOnStatus: true,
2489
+ * waitTimeSource: { body: 'data.retry_after' }
2490
+ * });
2491
+ *
2492
+ * // Custom function for complex APIs
2493
+ * await rezo.get(url, {
2494
+ * waitOnStatus: [429, 503],
2495
+ * waitTimeSource: (response) => {
2496
+ * const reset = response.headers.get('x-ratelimit-reset');
2497
+ * return reset ? parseInt(reset) - Math.floor(Date.now() / 1000) : null;
2498
+ * }
2499
+ * });
2500
+ * ```
2501
+ */
2502
+ waitOnStatus?: boolean | number[];
2503
+ /**
2504
+ * Where to extract the wait time from when rate-limited.
2505
+ *
2506
+ * - `'retry-after'` - Standard Retry-After header (default)
2507
+ * - `{ header: string }` - Custom header name (e.g., 'X-RateLimit-Reset')
2508
+ * - `{ body: string }` - JSON path in response body (e.g., 'data.retry_after', 'wait_seconds')
2509
+ * - Function - Custom logic receiving the response, return seconds to wait or null
2510
+ *
2511
+ * @default 'retry-after'
2512
+ */
2513
+ waitTimeSource?: "retry-after" | {
2514
+ header: string;
2515
+ } | {
2516
+ body: string;
2517
+ } | ((response: {
2518
+ status: number;
2519
+ headers: RezoHeaders;
2520
+ data?: any;
2521
+ }) => number | null);
2522
+ /**
2523
+ * Maximum time to wait for rate limit in milliseconds.
2524
+ * If the extracted wait time exceeds this, the request will fail instead of waiting.
2525
+ * Set to 0 for unlimited wait time.
2526
+ *
2527
+ * @default 60000 (60 seconds)
2528
+ */
2529
+ maxWaitTime?: number;
2530
+ /**
2531
+ * Default wait time in milliseconds if the wait time source returns nothing.
2532
+ * Used as fallback when Retry-After header or body path is not present.
2533
+ *
2534
+ * @default 1000 (1 second)
2535
+ */
2536
+ defaultWaitTime?: number;
2537
+ /**
2538
+ * Maximum number of wait attempts before giving up.
2539
+ * After this many waits, the request will proceed to retry logic or fail.
2540
+ *
2541
+ * @default 3
2542
+ */
2543
+ maxWaitAttempts?: number;
2429
2544
  /** Whether to use a secure context for HTTPS requests */
2430
2545
  useSecureContext?: boolean;
2431
2546
  /** Custom secure context for TLS connections */
@@ -1416,6 +1416,35 @@ export type OnTimeoutHook = (event: TimeoutEvent, config: RezoConfig) => void;
1416
1416
  * Use for cleanup, logging
1417
1417
  */
1418
1418
  export type OnAbortHook = (event: AbortEvent, config: RezoConfig) => void;
1419
+ /**
1420
+ * Rate limit wait event data - fired when waiting due to rate limiting
1421
+ */
1422
+ export interface RateLimitWaitEvent {
1423
+ /** HTTP status code that triggered the wait (e.g., 429, 503) */
1424
+ status: number;
1425
+ /** Time to wait in milliseconds */
1426
+ waitTime: number;
1427
+ /** Current wait attempt number (1-indexed) */
1428
+ attempt: number;
1429
+ /** Maximum wait attempts configured */
1430
+ maxAttempts: number;
1431
+ /** Where the wait time was extracted from */
1432
+ source: "header" | "body" | "function" | "default";
1433
+ /** The header or body path used (if applicable) */
1434
+ sourcePath?: string;
1435
+ /** URL being requested */
1436
+ url: string;
1437
+ /** HTTP method of the request */
1438
+ method: string;
1439
+ /** Timestamp when the wait started */
1440
+ timestamp: number;
1441
+ }
1442
+ /**
1443
+ * Hook called when rate limit wait occurs
1444
+ * Informational only - cannot abort the wait
1445
+ * Use for logging, monitoring, alerting
1446
+ */
1447
+ export type OnRateLimitWaitHook = (event: RateLimitWaitEvent, config: RezoConfig) => void | Promise<void>;
1419
1448
  /**
1420
1449
  * Hook called before a proxy is selected
1421
1450
  * Can return a specific proxy to override selection
@@ -1496,6 +1525,7 @@ export interface RezoHooks {
1496
1525
  onTls: OnTlsHook[];
1497
1526
  onTimeout: OnTimeoutHook[];
1498
1527
  onAbort: OnAbortHook[];
1528
+ onRateLimitWait: OnRateLimitWaitHook[];
1499
1529
  }
1500
1530
  /**
1501
1531
  * Create empty hooks object with all arrays initialized
@@ -2426,6 +2456,91 @@ export interface RezoRequestConfig<D = any> {
2426
2456
  /** Weather to stop or continue retry when certain condition is met*/
2427
2457
  condition?: (error: RezoError) => boolean | Promise<boolean>;
2428
2458
  };
2459
+ /**
2460
+ * Rate limit wait configuration - wait and retry when receiving rate limit responses.
2461
+ *
2462
+ * This feature runs BEFORE the retry system. When a rate-limiting status code is received,
2463
+ * the client will wait for the specified time and automatically retry the request.
2464
+ *
2465
+ * **Basic Usage:**
2466
+ * - `waitOnStatus: true` - Enable waiting on 429 status (default behavior)
2467
+ * - `waitOnStatus: [429, 503]` - Enable waiting on specific status codes
2468
+ *
2469
+ * **Wait Time Sources:**
2470
+ * - `'retry-after'` - Use standard Retry-After header (default)
2471
+ * - `{ header: 'X-RateLimit-Reset' }` - Use custom header
2472
+ * - `{ body: 'retry_after' }` - Extract from JSON response body
2473
+ * - Custom function for complex logic
2474
+ *
2475
+ * @example
2476
+ * ```typescript
2477
+ * // Wait on 429 using Retry-After header
2478
+ * await rezo.get(url, { waitOnStatus: true });
2479
+ *
2480
+ * // Wait on 429 using custom header
2481
+ * await rezo.get(url, {
2482
+ * waitOnStatus: true,
2483
+ * waitTimeSource: { header: 'X-RateLimit-Reset' }
2484
+ * });
2485
+ *
2486
+ * // Wait on 429 extracting time from JSON body
2487
+ * await rezo.get(url, {
2488
+ * waitOnStatus: true,
2489
+ * waitTimeSource: { body: 'data.retry_after' }
2490
+ * });
2491
+ *
2492
+ * // Custom function for complex APIs
2493
+ * await rezo.get(url, {
2494
+ * waitOnStatus: [429, 503],
2495
+ * waitTimeSource: (response) => {
2496
+ * const reset = response.headers.get('x-ratelimit-reset');
2497
+ * return reset ? parseInt(reset) - Math.floor(Date.now() / 1000) : null;
2498
+ * }
2499
+ * });
2500
+ * ```
2501
+ */
2502
+ waitOnStatus?: boolean | number[];
2503
+ /**
2504
+ * Where to extract the wait time from when rate-limited.
2505
+ *
2506
+ * - `'retry-after'` - Standard Retry-After header (default)
2507
+ * - `{ header: string }` - Custom header name (e.g., 'X-RateLimit-Reset')
2508
+ * - `{ body: string }` - JSON path in response body (e.g., 'data.retry_after', 'wait_seconds')
2509
+ * - Function - Custom logic receiving the response, return seconds to wait or null
2510
+ *
2511
+ * @default 'retry-after'
2512
+ */
2513
+ waitTimeSource?: "retry-after" | {
2514
+ header: string;
2515
+ } | {
2516
+ body: string;
2517
+ } | ((response: {
2518
+ status: number;
2519
+ headers: RezoHeaders;
2520
+ data?: any;
2521
+ }) => number | null);
2522
+ /**
2523
+ * Maximum time to wait for rate limit in milliseconds.
2524
+ * If the extracted wait time exceeds this, the request will fail instead of waiting.
2525
+ * Set to 0 for unlimited wait time.
2526
+ *
2527
+ * @default 60000 (60 seconds)
2528
+ */
2529
+ maxWaitTime?: number;
2530
+ /**
2531
+ * Default wait time in milliseconds if the wait time source returns nothing.
2532
+ * Used as fallback when Retry-After header or body path is not present.
2533
+ *
2534
+ * @default 1000 (1 second)
2535
+ */
2536
+ defaultWaitTime?: number;
2537
+ /**
2538
+ * Maximum number of wait attempts before giving up.
2539
+ * After this many waits, the request will proceed to retry logic or fail.
2540
+ *
2541
+ * @default 3
2542
+ */
2543
+ maxWaitAttempts?: number;
2429
2544
  /** Whether to use a secure context for HTTPS requests */
2430
2545
  useSecureContext?: boolean;
2431
2546
  /** Custom secure context for TLS connections */
@@ -1416,6 +1416,35 @@ export type OnTimeoutHook = (event: TimeoutEvent, config: RezoConfig) => void;
1416
1416
  * Use for cleanup, logging
1417
1417
  */
1418
1418
  export type OnAbortHook = (event: AbortEvent, config: RezoConfig) => void;
1419
+ /**
1420
+ * Rate limit wait event data - fired when waiting due to rate limiting
1421
+ */
1422
+ export interface RateLimitWaitEvent {
1423
+ /** HTTP status code that triggered the wait (e.g., 429, 503) */
1424
+ status: number;
1425
+ /** Time to wait in milliseconds */
1426
+ waitTime: number;
1427
+ /** Current wait attempt number (1-indexed) */
1428
+ attempt: number;
1429
+ /** Maximum wait attempts configured */
1430
+ maxAttempts: number;
1431
+ /** Where the wait time was extracted from */
1432
+ source: "header" | "body" | "function" | "default";
1433
+ /** The header or body path used (if applicable) */
1434
+ sourcePath?: string;
1435
+ /** URL being requested */
1436
+ url: string;
1437
+ /** HTTP method of the request */
1438
+ method: string;
1439
+ /** Timestamp when the wait started */
1440
+ timestamp: number;
1441
+ }
1442
+ /**
1443
+ * Hook called when rate limit wait occurs
1444
+ * Informational only - cannot abort the wait
1445
+ * Use for logging, monitoring, alerting
1446
+ */
1447
+ export type OnRateLimitWaitHook = (event: RateLimitWaitEvent, config: RezoConfig) => void | Promise<void>;
1419
1448
  /**
1420
1449
  * Hook called before a proxy is selected
1421
1450
  * Can return a specific proxy to override selection
@@ -1496,6 +1525,7 @@ export interface RezoHooks {
1496
1525
  onTls: OnTlsHook[];
1497
1526
  onTimeout: OnTimeoutHook[];
1498
1527
  onAbort: OnAbortHook[];
1528
+ onRateLimitWait: OnRateLimitWaitHook[];
1499
1529
  }
1500
1530
  /**
1501
1531
  * Create empty hooks object with all arrays initialized
@@ -2426,6 +2456,91 @@ export interface RezoRequestConfig<D = any> {
2426
2456
  /** Weather to stop or continue retry when certain condition is met*/
2427
2457
  condition?: (error: RezoError) => boolean | Promise<boolean>;
2428
2458
  };
2459
+ /**
2460
+ * Rate limit wait configuration - wait and retry when receiving rate limit responses.
2461
+ *
2462
+ * This feature runs BEFORE the retry system. When a rate-limiting status code is received,
2463
+ * the client will wait for the specified time and automatically retry the request.
2464
+ *
2465
+ * **Basic Usage:**
2466
+ * - `waitOnStatus: true` - Enable waiting on 429 status (default behavior)
2467
+ * - `waitOnStatus: [429, 503]` - Enable waiting on specific status codes
2468
+ *
2469
+ * **Wait Time Sources:**
2470
+ * - `'retry-after'` - Use standard Retry-After header (default)
2471
+ * - `{ header: 'X-RateLimit-Reset' }` - Use custom header
2472
+ * - `{ body: 'retry_after' }` - Extract from JSON response body
2473
+ * - Custom function for complex logic
2474
+ *
2475
+ * @example
2476
+ * ```typescript
2477
+ * // Wait on 429 using Retry-After header
2478
+ * await rezo.get(url, { waitOnStatus: true });
2479
+ *
2480
+ * // Wait on 429 using custom header
2481
+ * await rezo.get(url, {
2482
+ * waitOnStatus: true,
2483
+ * waitTimeSource: { header: 'X-RateLimit-Reset' }
2484
+ * });
2485
+ *
2486
+ * // Wait on 429 extracting time from JSON body
2487
+ * await rezo.get(url, {
2488
+ * waitOnStatus: true,
2489
+ * waitTimeSource: { body: 'data.retry_after' }
2490
+ * });
2491
+ *
2492
+ * // Custom function for complex APIs
2493
+ * await rezo.get(url, {
2494
+ * waitOnStatus: [429, 503],
2495
+ * waitTimeSource: (response) => {
2496
+ * const reset = response.headers.get('x-ratelimit-reset');
2497
+ * return reset ? parseInt(reset) - Math.floor(Date.now() / 1000) : null;
2498
+ * }
2499
+ * });
2500
+ * ```
2501
+ */
2502
+ waitOnStatus?: boolean | number[];
2503
+ /**
2504
+ * Where to extract the wait time from when rate-limited.
2505
+ *
2506
+ * - `'retry-after'` - Standard Retry-After header (default)
2507
+ * - `{ header: string }` - Custom header name (e.g., 'X-RateLimit-Reset')
2508
+ * - `{ body: string }` - JSON path in response body (e.g., 'data.retry_after', 'wait_seconds')
2509
+ * - Function - Custom logic receiving the response, return seconds to wait or null
2510
+ *
2511
+ * @default 'retry-after'
2512
+ */
2513
+ waitTimeSource?: "retry-after" | {
2514
+ header: string;
2515
+ } | {
2516
+ body: string;
2517
+ } | ((response: {
2518
+ status: number;
2519
+ headers: RezoHeaders;
2520
+ data?: any;
2521
+ }) => number | null);
2522
+ /**
2523
+ * Maximum time to wait for rate limit in milliseconds.
2524
+ * If the extracted wait time exceeds this, the request will fail instead of waiting.
2525
+ * Set to 0 for unlimited wait time.
2526
+ *
2527
+ * @default 60000 (60 seconds)
2528
+ */
2529
+ maxWaitTime?: number;
2530
+ /**
2531
+ * Default wait time in milliseconds if the wait time source returns nothing.
2532
+ * Used as fallback when Retry-After header or body path is not present.
2533
+ *
2534
+ * @default 1000 (1 second)
2535
+ */
2536
+ defaultWaitTime?: number;
2537
+ /**
2538
+ * Maximum number of wait attempts before giving up.
2539
+ * After this many waits, the request will proceed to retry logic or fail.
2540
+ *
2541
+ * @default 3
2542
+ */
2543
+ maxWaitAttempts?: number;
2429
2544
  /** Whether to use a secure context for HTTPS requests */
2430
2545
  useSecureContext?: boolean;
2431
2546
  /** Custom secure context for TLS connections */