rezo 1.0.122 → 1.0.124

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 (60) hide show
  1. package/README.md +110 -2080
  2. package/dist/adapters/curl.cjs +0 -1
  3. package/dist/adapters/curl.js +0 -1
  4. package/dist/adapters/entries/curl.d.ts +179 -2
  5. package/dist/adapters/entries/fetch.d.ts +179 -2
  6. package/dist/adapters/entries/http.d.ts +183 -6
  7. package/dist/adapters/entries/http2.d.ts +179 -2
  8. package/dist/adapters/entries/react-native.d.ts +179 -2
  9. package/dist/adapters/entries/xhr.d.ts +179 -2
  10. package/dist/adapters/fetch.cjs +0 -1
  11. package/dist/adapters/fetch.js +0 -1
  12. package/dist/adapters/http.cjs +0 -1
  13. package/dist/adapters/http.js +0 -1
  14. package/dist/adapters/http2.cjs +0 -1
  15. package/dist/adapters/http2.js +0 -1
  16. package/dist/adapters/index.cjs +6 -6
  17. package/dist/cache/index.cjs +9 -9
  18. package/dist/cookies/cookie-jar.cjs +4 -6
  19. package/dist/cookies/cookie-jar.js +0 -2
  20. package/dist/cookies/index.cjs +10 -10
  21. package/dist/core/rezo.cjs +128 -0
  22. package/dist/core/rezo.js +128 -0
  23. package/dist/crawler/index.cjs +42 -42
  24. package/dist/crawler/plugin/index.cjs +1 -1
  25. package/dist/crawler.d.ts +176 -1
  26. package/dist/entries/crawler.cjs +6 -6
  27. package/dist/index.cjs +48 -44
  28. package/dist/index.d.ts +195 -2
  29. package/dist/index.js +2 -0
  30. package/dist/internal/agents/index.cjs +14 -14
  31. package/dist/platform/browser.d.ts +179 -2
  32. package/dist/platform/bun.d.ts +179 -2
  33. package/dist/platform/deno.d.ts +179 -2
  34. package/dist/platform/node.d.ts +179 -2
  35. package/dist/platform/react-native.d.ts +179 -2
  36. package/dist/platform/worker.d.ts +179 -2
  37. package/dist/proxy/index.cjs +4 -4
  38. package/dist/queue/index.cjs +8 -8
  39. package/dist/responses/buildResponse.cjs +0 -1
  40. package/dist/responses/buildResponse.js +0 -1
  41. package/dist/responses/universal/index.cjs +11 -11
  42. package/dist/stealth/index.cjs +17 -17
  43. package/dist/stealth/profiles/index.cjs +10 -10
  44. package/dist/utils/http-config.cjs +0 -1
  45. package/dist/utils/http-config.js +0 -1
  46. package/dist/utils/link-header.cjs +16 -0
  47. package/dist/utils/link-header.js +14 -0
  48. package/dist/utils/uri.cjs +56 -0
  49. package/dist/utils/uri.js +54 -0
  50. package/dist/version.cjs +1 -1
  51. package/dist/version.js +1 -1
  52. package/dist/wget/downloader.cjs +11 -5
  53. package/dist/wget/downloader.js +11 -5
  54. package/dist/wget/index.cjs +51 -51
  55. package/dist/wget/index.d.ts +179 -3
  56. package/dist/wget/link-converter.cjs +14 -5
  57. package/dist/wget/link-converter.js +14 -5
  58. package/dist/wget/style-extractor.cjs +17 -0
  59. package/dist/wget/style-extractor.js +17 -0
  60. package/package.json +1 -1
package/README.md CHANGED
@@ -1,2149 +1,179 @@
1
1
  <p align="center">
2
- <img src="https://raw.githubusercontent.com/yuniqsolutions/rezo/main/assets/logo.svg" alt="Rezo HTTP Client" width="400">
2
+ <img src="https://raw.githubusercontent.com/yuniqsolutions/rezo/main/assets/logo.svg" alt="Rezo" width="300">
3
3
  </p>
4
4
 
5
- <h1 align="center">Rezo HTTP Client</h1>
6
-
7
5
  <p align="center">
8
- <strong>Lightning-fast, enterprise-grade HTTP client for modern JavaScript</strong>
6
+ <strong>The last HTTP client you'll ever need.</strong>
9
7
  </p>
10
8
 
11
9
  <p align="center">
12
- <a href="#installation">Installation</a> •
13
- <a href="#quick-start">Quick Start</a> •
14
- <a href="#features">Features</a> •
15
- <a href="#api-reference">API Reference</a>
16
- <a href="#adapters">Adapters</a> •
17
- <a href="#advanced-usage">Advanced Usage</a> •
18
- <a href="#migration-guide">Migration</a>
10
+ <a href="https://rezo-http.dev/docs">Documentation</a> •
11
+ <a href="https://rezo-http.dev/docs/getting-started/installation">Get Started</a> •
12
+ <a href="https://rezo-http.dev/docs/api/rezo-class">API Reference</a> •
13
+ <a href="https://rezo-http.dev/docs/switch/why-rezo">Why Rezo?</a>
19
14
  </p>
20
15
 
21
16
  <p align="center">
22
- <img src="https://img.shields.io/npm/v/rezo?style=flat-square&color=00D4FF" alt="npm version">
23
- <img src="https://img.shields.io/npm/dm/rezo?style=flat-square&color=0099FF" alt="npm downloads">
24
- <img src="https://img.shields.io/bundlephobia/minzip/rezo?style=flat-square&color=0066CC" alt="bundle size">
25
- <img src="https://img.shields.io/npm/l/rezo?style=flat-square&color=00D4FF" alt="license">
26
- <img src="https://img.shields.io/node/v/rezo?style=flat-square&color=0099FF" alt="node version">
17
+ <img src="https://img.shields.io/npm/v/rezo?style=flat-square&color=3080ff" alt="npm version">
18
+ <img src="https://img.shields.io/npm/dm/rezo?style=flat-square&color=3080ff" alt="npm downloads">
19
+ <img src="https://img.shields.io/bundlephobia/minzip/rezo?style=flat-square&color=3080ff" alt="bundle size">
20
+ <img src="https://img.shields.io/npm/l/rezo?style=flat-square&color=3080ff" alt="license">
21
+ <img src="https://img.shields.io/node/v/rezo?style=flat-square&color=3080ff" alt="node version">
27
22
  </p>
28
23
 
29
24
  ---
30
25
 
31
- ## Overview
32
-
33
- Rezo is a production-ready HTTP client library engineered for Node.js 22+ and universal JavaScript runtimes. Built from the ground up with TypeScript, Rezo delivers exceptional performance, comprehensive feature coverage, and seamless cross-environment compatibility.
34
-
35
- **Why Rezo?**
36
-
37
- - **Lightning Fast**: Native HTTP/2 multiplexing, connection pooling, and optimized stream handling
38
- - **Universal**: Works seamlessly across Node.js, Bun, Deno, browsers, React Native, and edge runtimes
39
- - **Type-Safe**: First-class TypeScript support with comprehensive type definitions
40
- - **Enterprise Ready**: Advanced cookie management, proxy support, retry logic, and error handling
41
- - **Tree-Shakeable**: Modular architecture enables optimal bundle sizes
42
- - **Production Proven**: Battle-tested in high-throughput enterprise applications
43
-
44
- ---
45
-
46
- ## Table of Contents
47
-
48
- - [Installation](#installation)
49
- - [Quick Start](#quick-start)
50
- - [Features](#features)
51
- - [Adapters](#adapters)
52
- - [HTTP Adapter](#http-adapter)
53
- - [HTTP/2 Adapter](#http2-adapter)
54
- - [Fetch Adapter](#fetch-adapter)
55
- - [cURL Adapter](#curl-adapter)
56
- - [XHR Adapter](#xhr-adapter)
57
- - [React Native Adapter](#react-native-adapter)
58
- - [API Reference](#api-reference)
59
- - [Request Methods](#request-methods)
60
- - [Request Configuration](#request-configuration)
61
- - [Response Schema](#response-schema)
62
- - [Instance Methods](#instance-methods)
63
- - [Advanced Usage](#advanced-usage)
64
- - [Cookie Management](#cookie-management)
65
- - [Proxy Configuration](#proxy-configuration)
66
- - [Proxy Manager](#proxy-manager)
67
- - [Request Queue](#request-queue)
68
- - [Streaming](#streaming)
69
- - [File Downloads](#file-downloads)
70
- - [File Uploads](#file-uploads)
71
- - [Hooks & Interceptors](#hooks--interceptors)
72
- - [Retry Logic](#retry-logic)
73
- - [Error Handling](#error-handling)
74
- - [Performance Metrics](#performance-metrics)
75
- - [Platform Support](#platform-support)
76
- - [Migration Guide](#migration-guide)
77
- - [TypeScript](#typescript)
78
- - [Crawler Module](#crawler-module)
79
- - [DOM Module](#dom-module)
80
- - [Troubleshooting](#troubleshooting)
81
- - [Contributing](#contributing)
82
- - [License](#license)
83
-
84
- ---
85
-
86
- ## Installation
26
+ Enterprise-grade HTTP client for Node.js 22+, Bun, Deno, browsers, React Native, and edge runtimes. One API everywhere — HTTP/2, cookies, proxy rotation, stealth mode, web crawling, and 70+ structured error codes out of the box.
87
27
 
88
- ### npm
28
+ ## Install
89
29
 
90
30
  ```bash
91
31
  npm install rezo
92
32
  ```
93
33
 
94
- ### Yarn
95
-
96
- ```bash
97
- yarn add rezo
98
- ```
99
-
100
- ### pnpm
101
-
102
- ```bash
103
- pnpm add rezo
104
- ```
105
-
106
- ### Bun
107
-
108
34
  ```bash
35
+ yarn add rezo # or
36
+ pnpm add rezo # or
109
37
  bun add rezo
110
38
  ```
111
39
 
112
- ### Requirements
113
-
114
- - **Node.js**: 22.0.0 or higher
115
- - **Bun**: 1.0.0 or higher
116
- - **Deno**: 1.40.0 or higher (with Node.js compatibility)
117
-
118
- ---
119
-
120
40
  ## Quick Start
121
41
 
122
- ### Basic GET Request
123
-
124
42
  ```typescript
125
43
  import rezo from 'rezo';
126
44
 
127
- // Simple GET request with destructured response
128
- const { data, status, headers } = await rezo.get('https://api.example.com/users');
129
- console.log(data); // Response body (auto-parsed JSON)
130
- console.log(status); // 200
131
- console.log(headers); // Response headers
132
-
133
- // With query parameters
134
- const { data: users } = await rezo.get('https://api.example.com/users', {
135
- params: { page: 1, limit: 10 }
136
- });
137
- console.log(users);
138
- ```
139
-
140
- ### POST Request with JSON
141
-
142
- ```typescript
143
- import rezo from 'rezo';
45
+ // GET
46
+ const { data } = await rezo('https://api.example.com/users');
144
47
 
145
- // Destructure the response for cleaner code
146
- const { data, status, headers, config } = await rezo.post('https://api.example.com/users', {
147
- name: 'John Doe',
148
- email: 'john@example.com'
48
+ // POST with JSON
49
+ const { data: user } = await rezo.postJson('https://api.example.com/users', {
50
+ name: 'Ada Lovelace',
51
+ email: 'ada@example.com'
149
52
  });
150
53
 
151
- console.log(data); // Created user object
152
- console.log(status); // 201
153
- ```
154
-
155
- ### Creating an Instance
156
-
157
- ```typescript
158
- import rezo from 'rezo';
159
-
160
- const api = rezo.create({
54
+ // Create an instance
55
+ const client = rezo.create({
161
56
  baseURL: 'https://api.example.com',
162
- timeout: 30000,
163
- headers: {
164
- 'Authorization': 'Bearer your-token',
165
- 'Content-Type': 'application/json'
166
- }
167
- });
168
-
169
- // All requests will use the base configuration
170
- const users = await api.get('/users');
171
- const user = await api.post('/users', { name: 'Jane Doe' });
172
- ```
173
-
174
- ### CommonJS Usage
175
-
176
- ```javascript
177
- const rezo = require('rezo').default;
178
-
179
- // Using default instance
180
- rezo.get('https://api.example.com/data')
181
- .then(response => console.log(response.data))
182
- .catch(error => console.error(error));
183
-
184
- // Creating custom instance
185
- const client = rezo.create({ baseURL: 'https://api.example.com' });
186
- ```
187
-
188
- ---
189
-
190
- ## Features
191
-
192
- ### Core Capabilities
193
-
194
- | Feature | Description |
195
- |---------|-------------|
196
- | **HTTP/1.1 & HTTP/2** | Full support for both protocols with automatic negotiation |
197
- | **All HTTP Methods** | GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS, TRACE |
198
- | **Request Body Types** | JSON, FormData, URLSearchParams, Streams, Buffers |
199
- | **Response Types** | JSON, Text, ArrayBuffer, Blob, Streams |
200
- | **Automatic Transforms** | JSON parsing, content-type detection, compression handling |
201
- | **Query Parameters** | Automatic URL encoding and serialization |
202
- | **Request Cancellation** | AbortController support for request cancellation |
203
-
204
- ### Network Features
205
-
206
- | Feature | Description |
207
- |---------|-------------|
208
- | **Cookie Management** | RFC 6265 compliant cookie jar with persistence |
209
- | **Proxy Support** | HTTP, HTTPS, SOCKS4, and SOCKS5 proxies |
210
- | **TLS/SSL** | Custom certificates, client certs, certificate pinning |
211
- | **Compression** | Automatic gzip, deflate, brotli, and zstd handling |
212
- | **Connection Pooling** | Reusable connections for improved performance |
213
- | **Keep-Alive** | Persistent connections with configurable timeouts |
214
-
215
- ### Enterprise Features
216
-
217
- | Feature | Description |
218
- |---------|-------------|
219
- | **Retry Logic** | Configurable retry with exponential backoff |
220
- | **Timeout Control** | Connection, request, and total timeout options |
221
- | **Rate Limiting** | Built-in request queue with priority, concurrency, and domain-based rate limiting |
222
- | **Hooks System** | Lifecycle hooks for request/response interception |
223
- | **Error Handling** | Structured errors with actionable suggestions |
224
- | **Performance Metrics** | Detailed timing data for monitoring |
225
-
226
- ### Developer Experience
227
-
228
- | Feature | Description |
229
- |---------|-------------|
230
- | **TypeScript First** | Comprehensive type definitions and generics |
231
- | **Tree-Shakeable** | Modular exports for optimal bundle size |
232
- | **Zero Config** | Works out of the box with sensible defaults |
233
- | **Extensive Logging** | Debug mode for troubleshooting |
234
- | **Cross-Platform** | Node.js, Bun, Deno, browsers, React Native, edge |
235
-
236
- ---
57
+ timeout: 5000,
58
+ headers: { 'Authorization': 'Bearer token' }
59
+ });
60
+
61
+ const { data: posts } = await client.get('/posts');
62
+ ```
63
+
64
+ ## What's Included
65
+
66
+ <table>
67
+ <tr>
68
+ <td width="140"><strong>6 Adapters</strong></td>
69
+ <td>HTTP &middot; HTTP/2 &middot; cURL (200+ options) &middot; Fetch &middot; XHR &middot; React Native</td>
70
+ </tr>
71
+ <tr>
72
+ <td><strong>26 Hooks</strong></td>
73
+ <td>Full request lifecycle — DNS, TLS, redirects, retries, cookies, proxies</td>
74
+ </tr>
75
+ <tr>
76
+ <td><strong>70+ Error Codes</strong></td>
77
+ <td>Structured errors with boolean flags and recovery suggestions</td>
78
+ </tr>
79
+ </table>
80
+
81
+ <br>
82
+
83
+ - **Cookie Jar** — Auto-persistence in JSON and Netscape formats
84
+ - **Proxy Rotation** — HTTP, HTTPS, SOCKS4, SOCKS5 with health monitoring
85
+ - **Stealth Mode** — 18 browser profiles with TLS fingerprinting
86
+ - **Web Crawler** — SQLite persistence, robots.txt, auto-throttle, resumable
87
+ - **Request Queue** — Priority, per-domain concurrency, rate limiting
88
+ - **Streaming** — EventEmitter with progress and lifecycle events
89
+ - **Downloads & Uploads** — Progress, speed, and ETA tracking
90
+ - **Retry** — Exponential/linear backoff with custom conditions
91
+ - **Staged Timeouts** Separate connect, headers, body, and total phases
92
+ - **Response & DNS Cache** ETag/Last-Modified revalidation
93
+ - **Site Cloning** Wget-style mirroring with link conversion
94
+ - **TypeScript** Strict types, generics, overloads from the ground up
237
95
 
238
96
  ## Adapters
239
97
 
240
- Rezo uses a pluggable adapter architecture, allowing you to choose the optimal HTTP implementation for your environment and requirements.
241
-
242
- ### Automatic Adapter Selection
243
-
244
- By default, Rezo automatically selects the best adapter based on your runtime environment:
245
-
246
- | Environment | Default Adapter |
247
- |-------------|-----------------|
248
- | Node.js | HTTP Adapter |
249
- | Bun | HTTP Adapter |
250
- | Deno | HTTP Adapter |
251
- | Browser | Fetch Adapter |
252
- | Cloudflare Workers | Fetch Adapter |
253
- | React Native | React Native Adapter |
254
-
255
- ### HTTP Adapter
256
-
257
- The full-featured adapter for Node.js environments with complete cookie, proxy, and streaming support.
258
-
259
- ```typescript
260
- import rezo from 'rezo/adapters/http';
261
-
262
- const response = await rezo.get('https://api.example.com/data');
263
- ```
264
-
265
- **Features:**
266
- - Full cookie jar support with persistence
267
- - HTTP/HTTPS/SOCKS proxy support
268
- - Streaming request and response bodies
269
- - All compression algorithms
270
- - Custom TLS configuration
271
- - Connection keep-alive
272
-
273
- ### HTTP/2 Adapter
274
-
275
- Native HTTP/2 support with session multiplexing for maximum performance.
276
-
277
- ```typescript
278
- import rezo from 'rezo/adapters/http2';
279
-
280
- const response = await rezo.get('https://api.example.com/data');
281
- ```
282
-
283
- **Features:**
284
- - HTTP/2 multiplexing (multiple requests over single connection)
285
- - Automatic session pooling and reuse
286
- - ALPN protocol negotiation
287
- - Falls back to HTTP/1.1 when needed
288
- - Server push support
289
- - Header compression (HPACK)
290
-
291
- ### Fetch Adapter
292
-
293
- Lightweight adapter using the native Fetch API, ideal for browsers and edge runtimes.
294
-
295
- ```typescript
296
- import rezo from 'rezo/adapters/fetch';
297
-
298
- const response = await rezo.get('https://api.example.com/data');
299
- ```
300
-
301
- **Features:**
302
- - Minimal bundle size
303
- - Native browser support
304
- - Edge runtime compatible (Cloudflare Workers, Vercel Edge)
305
- - Streaming response bodies
306
- - AbortController integration
307
-
308
- ### cURL Adapter
309
-
310
- Advanced adapter wrapping the cURL command-line tool with **120+ configuration options** for maximum compatibility, debugging, and fine-grained control.
311
-
312
- ```typescript
313
- import rezo from 'rezo/adapters/curl';
314
-
315
- const response = await rezo.get('https://api.example.com/data', {
316
- curl: {
317
- connectTimeout: 10,
318
- limitRate: '500K',
319
- retry: { attempts: 3, allErrors: true },
320
- verbose: true
321
- }
322
- });
323
- ```
324
-
325
- **Features:**
326
- - 120+ cURL command-line options via `curl` property
327
- - HTTP/1.0, 1.1, 2.0, 3.0 protocol support
328
- - Advanced authentication (Basic, Digest, NTLM, Negotiate, AWS SigV4, OAuth2)
329
- - Comprehensive TLS/SSL configuration
330
- - FTP, SSH, SMTP, and TFTP protocol support
331
- - Connection pooling and reuse
332
- - Detailed timing and debugging information
333
- - Proxy authentication and chaining
334
-
335
- **Important**: The `curl` property is **only available** when importing from `rezo/adapters/curl`. It does not appear in the base `RezoRequestConfig` type.
336
-
337
- #### cURL Options Categories
338
-
339
- The cURL adapter provides options across the following categories:
340
-
341
- | Category | Example Options | Description |
342
- |----------|----------------|-------------|
343
- | **Connection** | `connectTimeout`, `maxTime`, `tcpFastOpen`, `tcpNodelay` | Connection timing and TCP settings |
344
- | **Rate Limiting** | `limitRate`, `speedLimit`, `maxFilesize` | Bandwidth and transfer limits |
345
- | **Retry** | `retry.attempts`, `retry.delay`, `retry.allErrors` | Automatic retry configuration |
346
- | **Network** | `interface`, `localPort`, `ipVersion`, `resolve` | Network interface and routing |
347
- | **HTTP** | `httpVersion`, `pathAsIs`, `maxRedirs`, `referer` | HTTP protocol settings |
348
- | **TLS/SSL** | `tls.min`, `tls.ciphers`, `tls.cert`, `insecure` | Comprehensive TLS configuration |
349
- | **Proxy** | `proxyHeaders`, `proxyTls`, `proxyTunnel` | Proxy-specific settings |
350
- | **DNS** | `dns.servers`, `dns.dohUrl`, `dns.dohInsecure` | DNS resolution and DoH |
351
- | **Authentication** | `negotiate`, `awsSigv4`, `oauth2Bearer`, `kerberos` | Advanced auth methods |
352
- | **FTP** | `ftp.pasv`, `ftp.createDirs`, `ftp.method` | FTP protocol options |
353
- | **SSH** | `ssh.privateKey`, `ssh.knownHosts`, `ssh.compression` | SSH/SCP/SFTP settings |
354
- | **SMTP** | `smtp.mailFrom`, `smtp.mailRcpt` | Email sending configuration |
355
- | **Debug** | `verbose`, `trace`, `traceTime`, `dumpHeader` | Debugging and tracing |
356
-
357
- #### cURL Options Examples
358
-
359
- ##### Connection & Timeout
360
-
361
- ```typescript
362
- import rezo from 'rezo/adapters/curl';
363
-
364
- await rezo.get('https://api.example.com/data', {
365
- curl: {
366
- connectTimeout: 10, // 10 seconds for TCP connection
367
- maxTime: 300, // 5 minutes max for entire request
368
- keepaliveTime: 60, // Send keepalive after 60s idle
369
- tcpFastOpen: true, // Enable TCP Fast Open
370
- tcpNodelay: true, // Disable Nagle algorithm
371
- happyEyeballsTimeout: 200 // IPv6/IPv4 fallback timeout
372
- }
373
- });
374
- ```
375
-
376
- ##### Rate Limiting & Bandwidth
377
-
378
- ```typescript
379
- import rezo from 'rezo/adapters/curl';
380
-
381
- await rezo.get('https://example.com/large-file.zip', {
382
- curl: {
383
- limitRate: '1M', // Limit to 1 MB/s
384
- speedLimit: { limit: 1000, time: 30 }, // Abort if <1KB/s for 30s
385
- maxFilesize: 100 * 1024 * 1024 // Max 100MB response
386
- }
387
- });
388
- ```
389
-
390
- ##### Retry Configuration
391
-
392
- ```typescript
393
- import rezo from 'rezo/adapters/curl';
394
-
395
- await rezo.get('https://unreliable-api.com/data', {
396
- curl: {
397
- retry: {
398
- attempts: 5, // Retry up to 5 times
399
- delay: 2, // 2 seconds between retries
400
- maxTime: 60, // Max 60 seconds total for retries
401
- allErrors: true, // Retry on all errors (not just transient)
402
- connRefused: true // Retry on connection refused
403
- }
404
- }
405
- });
406
- ```
407
-
408
- ##### Custom DNS Resolution
409
-
410
- ```typescript
411
- import rezo from 'rezo/adapters/curl';
412
-
413
- await rezo.get('https://api.example.com/data', {
414
- curl: {
415
- resolve: [
416
- { host: 'api.example.com', port: 443, address: '10.0.0.1' }
417
- ],
418
- dns: {
419
- servers: '8.8.8.8,8.8.4.4',
420
- dohUrl: 'https://dns.google/dns-query'
421
- }
422
- }
423
- });
424
- ```
425
-
426
- ##### Comprehensive TLS Configuration
98
+ Rezo selects the optimal adapter for your runtime automatically.
427
99
 
428
- ```typescript
429
- import rezo from 'rezo/adapters/curl';
430
-
431
- await rezo.get('https://secure.example.com/api', {
432
- curl: {
433
- tls: {
434
- min: 'tlsv1.2', // Minimum TLS 1.2
435
- tls13Ciphers: 'TLS_AES_256_GCM_SHA384', // TLS 1.3 ciphers
436
- ciphers: 'ECDHE-RSA-AES256-GCM-SHA384', // TLS 1.2 ciphers
437
- certStatus: true, // OCSP stapling
438
- pinnedPubKey: 'sha256//base64hash=', // Certificate pinning
439
- cert: '/path/to/client.crt', // Client certificate
440
- key: '/path/to/client.key', // Client key
441
- cacert: '/path/to/ca-bundle.crt' // CA certificate
442
- }
443
- }
444
- });
445
- ```
446
-
447
- ##### Advanced Authentication
448
-
449
- ```typescript
450
- import rezo from 'rezo/adapters/curl';
451
-
452
- // AWS Signature Version 4
453
- await rezo.get('https://s3.amazonaws.com/bucket/object', {
454
- curl: {
455
- awsSigv4: {
456
- provider: 'aws:amz',
457
- region: 'us-east-1',
458
- service: 's3'
459
- }
460
- }
461
- });
462
-
463
- // Kerberos/SPNEGO
464
- await rezo.get('https://internal.company.com/api', {
465
- curl: {
466
- negotiate: true,
467
- delegation: 'policy'
468
- }
469
- });
470
-
471
- // OAuth 2.0 Bearer Token
472
- await rezo.get('https://api.example.com/protected', {
473
- curl: {
474
- oauth2Bearer: 'your-access-token'
475
- }
476
- });
477
- ```
478
-
479
- ##### FTP Operations
480
-
481
- ```typescript
482
- import rezo from 'rezo/adapters/curl';
483
-
484
- await rezo.get('ftp://ftp.example.com/file.txt', {
485
- curl: {
486
- ftp: {
487
- pasv: true,
488
- createDirs: true,
489
- method: 'singlecwd',
490
- sslControl: true
491
- }
492
- }
493
- });
494
- ```
495
-
496
- ##### SSH/SFTP Configuration
497
-
498
- ```typescript
499
- import rezo from 'rezo/adapters/curl';
100
+ | Adapter | Runtime | Cookies | Proxy | HTTP/2 | Streaming |
101
+ |---|---|---|---|---|---|
102
+ | **HTTP** | Node.js, Bun | &#9679; | &#9679; | | &#9679; |
103
+ | **HTTP/2** | Node.js, Bun | &#9679; | &#9679; | &#9679; | &#9679; |
104
+ | **cURL** | Node.js | &#9679; | &#9679; | &#9679; | &#9679; |
105
+ | **Fetch** | Browsers, Deno, Edge | | | | &#9679; |
106
+ | **XHR** | Browsers | | | | |
107
+ | **React Native** | iOS, Android | | | | &#9679; |
500
108
 
501
- await rezo.get('sftp://server.example.com/path/file.txt', {
502
- curl: {
503
- ssh: {
504
- privateKey: '/home/user/.ssh/id_rsa',
505
- publicKey: '/home/user/.ssh/id_rsa.pub',
506
- knownHosts: '/home/user/.ssh/known_hosts',
507
- compression: true
508
- }
509
- }
510
- });
511
- ```
109
+ ## Examples
512
110
 
513
- ##### Debugging & Tracing
111
+ **Proxy rotation with stealth:**
514
112
 
515
113
  ```typescript
516
- import rezo from 'rezo/adapters/curl';
114
+ import rezo, { RezoStealth } from 'rezo';
517
115
 
518
- await rezo.get('https://api.example.com/debug', {
519
- curl: {
520
- verbose: true, // Show detailed output
521
- trace: '/tmp/curl-trace.log', // Write full trace to file
522
- traceTime: true, // Include timestamps
523
- dumpHeader: '/tmp/headers.txt' // Dump headers to file
116
+ const client = rezo.create({
117
+ stealth: RezoStealth.chrome(),
118
+ proxyManager: {
119
+ proxies: ['socks5://proxy1:1080', 'http://proxy2:8080'],
120
+ rotation: { strategy: 'random' },
121
+ autoDisableDeadProxies: true
524
122
  }
525
123
  });
526
- ```
527
-
528
- #### CurlRequestConfig Type
529
-
530
- When using the cURL adapter, the request configuration type extends the base with cURL-specific options:
531
-
532
- ```typescript
533
- import rezo, { CurlRequestConfig } from 'rezo/adapters/curl';
534
-
535
- const config: CurlRequestConfig = {
536
- url: 'https://api.example.com/data',
537
- method: 'GET',
538
- headers: { 'Accept': 'application/json' },
539
- curl: {
540
- connectTimeout: 10,
541
- retry: { attempts: 3 }
542
- }
543
- };
544
-
545
- const response = await rezo.request(config);
546
- ```
547
-
548
- #### Available cURL Option Types
549
-
550
- The cURL adapter exports all option types for TypeScript users:
551
-
552
- ```typescript
553
- import type {
554
- CurlOptions,
555
- CurlRequestConfig,
556
- CurlTlsOptions,
557
- CurlFtpOptions,
558
- CurlSshOptions,
559
- CurlSmtpOptions,
560
- CurlDnsOptions,
561
- CurlRetryOptions,
562
- CurlProxyTlsOptions,
563
- CurlResolveEntry,
564
- CurlConnectToEntry,
565
- CurlSpeedLimit,
566
- CurlParallelOptions,
567
- CurlHttpVersion,
568
- CurlSslVersion,
569
- CurlIpVersion,
570
- CurlAuthMethod,
571
- CurlDelegation
572
- } from 'rezo/adapters/curl';
573
- ```
574
-
575
- ### XHR Adapter
576
-
577
- Legacy browser support using XMLHttpRequest for maximum compatibility.
578
-
579
- ```typescript
580
- import rezo from 'rezo/adapters/xhr';
581
-
582
- const response = await rezo.get('https://api.example.com/data');
583
- ```
584
-
585
- **Features:**
586
- - Legacy browser support (IE11+)
587
- - Upload progress events
588
- - Download progress events
589
- - Synchronous request option
590
- - Cross-origin request handling
591
-
592
- ### React Native Adapter
593
-
594
- Optimized adapter for React Native mobile applications.
595
-
596
- ```typescript
597
- import rezo from 'rezo/adapters/react-native';
598
-
599
- const response = await rezo.get('https://api.example.com/data');
600
- ```
601
-
602
- **Features:**
603
- - Optimized for mobile networks
604
- - File download support (react-native-fs)
605
- - Manual cookie header management
606
- - Background fetch support
607
- - Network state awareness
608
-
609
- ---
610
-
611
- ## API Reference
612
-
613
- ### Request Methods
614
124
 
615
- Rezo provides convenient methods for all standard HTTP verbs:
616
-
617
- ```typescript
618
- // GET request
619
- rezo.get(url[, config])
620
-
621
- // POST request
622
- rezo.post(url[, data[, config]])
623
-
624
- // PUT request
625
- rezo.put(url[, data[, config]])
626
-
627
- // PATCH request
628
- rezo.patch(url[, data[, config]])
629
-
630
- // DELETE request
631
- rezo.delete(url[, config])
632
-
633
- // HEAD request
634
- rezo.head(url[, config])
635
-
636
- // OPTIONS request
637
- rezo.options(url[, config])
638
-
639
- // Generic request
640
- rezo.request(config)
641
- ```
642
-
643
- ### Convenience Methods
644
-
645
- Rezo provides specialized methods for common content types:
646
-
647
- ```typescript
648
- // JSON POST with automatic Content-Type header
649
- rezo.postJson(url, data[, config])
650
-
651
- // Form-encoded POST
652
- rezo.postForm(url, data[, config])
653
-
654
- // Multipart form data POST
655
- rezo.postMultipart(url, data[, config])
656
-
657
- // Same patterns available for PUT and PATCH
658
- rezo.putJson(url, data[, config])
659
- rezo.patchJson(url, data[, config])
660
- ```
661
-
662
- ### Request Configuration
663
-
664
- ```typescript
665
- interface RezoConfig {
666
- // URL and Method
667
- url?: string;
668
- method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS';
669
- baseURL?: string;
670
-
671
- // Request Data
672
- params?: Record<string, any>;
673
- data?: any;
674
- headers?: RezoHeaders | Record<string, string>;
675
-
676
- // Timeouts (in milliseconds)
677
- timeout?: number;
678
- connectTimeout?: number;
679
- requestTimeout?: number;
680
-
681
- // Response Handling
682
- responseType?: 'json' | 'text' | 'arraybuffer' | 'blob' | 'stream';
683
- responseEncoding?: string;
684
- validateStatus?: (status: number) => boolean;
685
- maxContentLength?: number;
686
- maxBodyLength?: number;
687
-
688
- // Redirects
689
- maxRedirects?: number;
690
- followRedirect?: boolean;
691
-
692
- // Authentication
693
- auth?: {
694
- username: string;
695
- password: string;
696
- };
697
-
698
- // Proxy Configuration
699
- proxy?: {
700
- protocol?: 'http' | 'https' | 'socks4' | 'socks5';
701
- host: string;
702
- port: number;
703
- auth?: {
704
- username: string;
705
- password: string;
706
- };
707
- };
708
-
709
- // TLS/SSL
710
- httpsAgent?: any;
711
- rejectUnauthorized?: boolean;
712
- ca?: string | Buffer;
713
- cert?: string | Buffer;
714
- key?: string | Buffer;
715
-
716
- // Advanced
717
- decompress?: boolean;
718
- signal?: AbortSignal;
719
- onUploadProgress?: (progressEvent: ProgressEvent) => void;
720
- onDownloadProgress?: (progressEvent: ProgressEvent) => void;
721
-
722
- // Retry Configuration
723
- retry?: {
724
- limit?: number;
725
- delay?: number;
726
- maxDelay?: number;
727
- backoff?: number;
728
- retryOn?: number[] | ((error: Error, attempt: number) => boolean);
729
- };
730
-
731
- // Cookies
732
- jar?: CookieJar;
733
- withCredentials?: boolean;
734
- }
735
- ```
736
-
737
- ### Response Schema
738
-
739
- ```typescript
740
- interface RezoResponse<T = any> {
741
- // Response data (automatically parsed based on content-type)
742
- data: T;
743
-
744
- // HTTP status
745
- status: number;
746
- statusText: string;
747
-
748
- // Response headers (case-insensitive access)
749
- headers: RezoHeaders;
750
-
751
- // Request configuration used
752
- config: RezoConfig;
753
-
754
- // The request that generated this response
755
- request: any;
756
-
757
- // Timing metrics (when available)
758
- timing?: {
759
- start: number;
760
- dns: number;
761
- connect: number;
762
- tls: number;
763
- firstByte: number;
764
- download: number;
765
- total: number;
766
- };
767
- }
125
+ const { data } = await client.get('https://protected-site.com');
768
126
  ```
769
127
 
770
- ### Instance Methods
128
+ **Download with progress:**
771
129
 
772
130
  ```typescript
773
- const instance = rezo.create(config);
774
-
775
- // Request methods
776
- instance.get(url, config?)
777
- instance.post(url, data?, config?)
778
- instance.put(url, data?, config?)
779
- instance.patch(url, data?, config?)
780
- instance.delete(url, config?)
781
- instance.head(url, config?)
782
- instance.options(url, config?)
783
- instance.request(config)
784
-
785
- // Instance configuration
786
- instance.defaults // Access default configuration
787
- instance.getUri(config) // Get the full URL
788
-
789
- // Cookie management
790
- instance.jar // Access the cookie jar
791
- instance.getCookies(url)
792
- instance.setCookie(cookie, url)
793
- instance.clearCookies()
794
-
795
- // Hooks
796
- instance.hooks.beforeRequest.push(handler)
797
- instance.hooks.afterResponse.push(handler)
798
- instance.hooks.beforeRetry.push(handler)
799
- instance.hooks.beforeError.push(handler)
131
+ const download = await rezo.download(
132
+ 'https://example.com/file.zip',
133
+ './file.zip'
134
+ );
135
+ download.on('progress', (p) => console.log(`${p.percentage}%`));
800
136
  ```
801
137
 
802
- ---
803
-
804
- ## Advanced Usage
805
-
806
- ### Cookie Management
807
-
808
- Rezo provides RFC 6265 compliant cookie management with automatic persistence. The default instance already has a built-in cookie jar - no configuration required.
138
+ **Streaming:**
809
139
 
810
140
  ```typescript
811
- import rezo from 'rezo';
812
-
813
- // Cookies work automatically with the default instance
814
- await rezo.post('https://api.example.com/login', { username: 'user', password: 'pass' });
815
-
816
- // Subsequent requests automatically include session cookies
817
- const profile = await rezo.get('https://api.example.com/profile');
818
-
819
- // Access cookies directly from the default instance
820
- const cookies = rezo.getCookies('https://api.example.com');
821
- console.log(cookies);
822
-
823
- // Set cookies manually
824
- rezo.setCookie('custom=value; Path=/; HttpOnly', 'https://api.example.com');
825
-
826
- // Clear all cookies
827
- rezo.clearCookies();
141
+ const stream = await rezo.stream('https://api.example.com/events');
142
+ stream.on('data', (chunk) => process.stdout.write(chunk));
828
143
  ```
829
144
 
830
- #### Custom Cookie Jar (Optional)
831
-
832
- Only create your own CookieJar if you need to manage cookies externally or use multiple isolated jars:
145
+ **26 lifecycle hooks:**
833
146
 
834
147
  ```typescript
835
- import rezo, { CookieJar } from 'rezo';
836
-
837
- // Custom jar for isolated cookie management
838
- const myJar = new CookieJar();
839
-
840
148
  const client = rezo.create({
841
- baseURL: 'https://api.example.com',
842
- jar: myJar
843
- });
844
-
845
- // Export cookies to different formats
846
- const netscapeFormat = myJar.toNetscapeString();
847
- const setCookieHeaders = myJar.toSetCookieStrings();
848
- const jsonFormat = myJar.toJSON();
849
- ```
850
-
851
- ### Proxy Configuration
852
-
853
- Rezo provides comprehensive proxy support for HTTP, HTTPS, SOCKS4, and SOCKS5 protocols, enabling secure and anonymous web requests through proxy servers.
854
-
855
- #### Quick Usage (Per-Request)
856
-
857
- You can use a proxy directly in any request without creating an instance:
858
-
859
- ```typescript
860
- import rezo from 'rezo';
861
-
862
- // Use proxy for a single request
863
- const response = await rezo.get('https://api.example.com/data', {
864
- proxy: {
865
- protocol: 'http',
866
- host: 'proxy.example.com',
867
- port: 8080
149
+ hooks: {
150
+ beforeRequest: [(config) => { /* modify config */ }],
151
+ afterResponse: [(response) => response],
152
+ onDns: [(event) => { /* DNS resolved */ }],
153
+ onTls: [(event) => { /* TLS handshake done */ }],
154
+ beforeRetry: [(config, error) => { /* about to retry */ }],
868
155
  }
869
156
  });
870
157
  ```
871
158
 
872
- #### Proxy Protocols
159
+ ## Documentation
873
160
 
874
- | Protocol | Description | Use Case |
875
- |----------|-------------|----------|
876
- | `http` | HTTP proxy (CONNECT method for HTTPS targets) | General-purpose web proxy |
877
- | `https` | HTTPS proxy (encrypted proxy connection) | Secure corporate proxies |
878
- | `socks4` | SOCKS4 proxy (TCP connections only) | Legacy proxy servers |
879
- | `socks5` | SOCKS5 proxy (TCP + UDP, authentication) | Anonymous browsing, Tor |
161
+ Full documentation at **[rezo-http.dev](https://rezo-http.dev/docs)**
880
162
 
881
- #### Basic HTTP Proxy
163
+ - [Installation](https://rezo-http.dev/docs/getting-started/installation)
164
+ - [Quick Start](https://rezo-http.dev/docs/getting-started/quick-start)
165
+ - [API Reference](https://rezo-http.dev/docs/api/rezo-class)
166
+ - [Adapters](https://rezo-http.dev/docs/adapters/overview)
167
+ - [Stealth Mode](https://rezo-http.dev/docs/stealth/overview)
168
+ - [Web Crawler](https://rezo-http.dev/docs/crawler/overview)
169
+ - [Error Handling](https://rezo-http.dev/docs/core/error-handling)
170
+ - [Hooks](https://rezo-http.dev/docs/features/hooks)
171
+ - [Switching from another library?](https://rezo-http.dev/docs/switch/why-rezo)
882
172
 
883
- ```typescript
884
- import rezo from 'rezo';
885
-
886
- // HTTP Proxy - routes all traffic through the proxy
887
- const client = rezo.create({
888
- proxy: {
889
- protocol: 'http',
890
- host: 'proxy.example.com',
891
- port: 8080
892
- }
893
- });
173
+ ## License
894
174
 
895
- const response = await client.get('https://api.example.com/data');
896
- ```
897
-
898
- #### HTTPS Proxy
899
-
900
- ```typescript
901
- import rezo from 'rezo';
902
-
903
- // HTTPS Proxy - encrypted connection to proxy server
904
- const client = rezo.create({
905
- proxy: {
906
- protocol: 'https',
907
- host: 'secure-proxy.example.com',
908
- port: 443
909
- }
910
- });
911
- ```
912
-
913
- #### Authenticated Proxy
914
-
915
- ```typescript
916
- import rezo from 'rezo';
917
-
918
- // Proxy with username/password authentication
919
- const client = rezo.create({
920
- proxy: {
921
- protocol: 'http',
922
- host: 'proxy.example.com',
923
- port: 8080,
924
- auth: {
925
- username: 'proxyuser',
926
- password: 'proxypass'
927
- }
928
- }
929
- });
930
- ```
931
-
932
- #### SOCKS4 Proxy
933
-
934
- ```typescript
935
- import rezo from 'rezo';
936
-
937
- // SOCKS4 Proxy - TCP connections only, no authentication
938
- const client = rezo.create({
939
- proxy: {
940
- protocol: 'socks4',
941
- host: 'socks4.example.com',
942
- port: 1080
943
- }
944
- });
945
- ```
946
-
947
- #### SOCKS5 Proxy
948
-
949
- ```typescript
950
- import rezo from 'rezo';
951
-
952
- // SOCKS5 Proxy - supports TCP, UDP, and authentication
953
- const client = rezo.create({
954
- proxy: {
955
- protocol: 'socks5',
956
- host: 'socks5.example.com',
957
- port: 1080
958
- }
959
- });
960
-
961
- // SOCKS5 with authentication
962
- const authenticatedSocks = rezo.create({
963
- proxy: {
964
- protocol: 'socks5',
965
- host: 'socks5.example.com',
966
- port: 1080,
967
- auth: {
968
- username: 'socksuser',
969
- password: 'sockspass'
970
- }
971
- }
972
- });
973
-
974
- // Using Tor network (typically SOCKS5 on port 9050)
975
- const torClient = rezo.create({
976
- proxy: {
977
- protocol: 'socks5',
978
- host: '127.0.0.1',
979
- port: 9050
980
- }
981
- });
982
- ```
983
-
984
- #### Per-Request Proxy Override
985
-
986
- ```typescript
987
- import rezo from 'rezo';
988
-
989
- const client = rezo.create({
990
- proxy: {
991
- protocol: 'http',
992
- host: 'default-proxy.example.com',
993
- port: 8080
994
- }
995
- });
996
-
997
- // Use a different proxy for this specific request
998
- await client.get('https://api.example.com/data', {
999
- proxy: {
1000
- protocol: 'https',
1001
- host: 'different-proxy.example.com',
1002
- port: 443
1003
- }
1004
- });
1005
-
1006
- // Disable proxy for specific request (direct connection)
1007
- await client.get('https://internal.example.com/data', {
1008
- proxy: false
1009
- });
1010
- ```
1011
-
1012
- #### Proxy Configuration Interface
1013
-
1014
- ```typescript
1015
- interface ProxyConfig {
1016
- protocol: 'http' | 'https' | 'socks4' | 'socks5';
1017
- host: string;
1018
- port: number;
1019
- auth?: {
1020
- username: string;
1021
- password: string;
1022
- };
1023
- }
1024
- ```
1025
-
1026
- ### Proxy Manager
1027
-
1028
- Rezo includes a powerful Proxy Manager for enterprise scenarios requiring proxy rotation, health monitoring, and intelligent failover. The Proxy Manager automatically rotates through a pool of proxies, tracks their health, and removes failing proxies from circulation.
1029
-
1030
- #### Basic Usage
1031
-
1032
- ```typescript
1033
- import rezo, { ProxyManager } from 'rezo';
1034
-
1035
- // Create a proxy manager with a pool of proxies
1036
- const proxyManager = new ProxyManager({
1037
- proxies: [
1038
- { protocol: 'http', host: 'proxy1.example.com', port: 8080 },
1039
- { protocol: 'http', host: 'proxy2.example.com', port: 8080 },
1040
- { protocol: 'socks5', host: 'proxy3.example.com', port: 1080 }
1041
- ]
1042
- });
1043
-
1044
- // Create client with proxy manager
1045
- const client = rezo.create({
1046
- proxyManager
1047
- });
1048
-
1049
- // Requests automatically rotate through available proxies
1050
- await client.get('https://api.example.com/data');
1051
- ```
1052
-
1053
- #### Rotation Strategies
1054
-
1055
- ```typescript
1056
- import { ProxyManager } from 'rezo';
1057
-
1058
- // Random rotation (default) - randomly selects from available proxies
1059
- const randomManager = new ProxyManager({
1060
- proxies: [...],
1061
- rotationStrategy: 'random'
1062
- });
1063
-
1064
- // Sequential rotation - cycles through proxies in order
1065
- const sequentialManager = new ProxyManager({
1066
- proxies: [...],
1067
- rotationStrategy: 'sequential'
1068
- });
1069
-
1070
- // Per-proxy limit - switches after N requests per proxy
1071
- const limitManager = new ProxyManager({
1072
- proxies: [...],
1073
- rotationStrategy: 'per-proxy-limit',
1074
- perProxyLimit: 100 // Switch after 100 requests
1075
- });
1076
- ```
1077
-
1078
- #### URL Filtering (Whitelist/Blacklist)
1079
-
1080
- Control which URLs use the proxy manager with glob patterns or regular expressions:
1081
-
1082
- ```typescript
1083
- import { ProxyManager } from 'rezo';
1084
-
1085
- const proxyManager = new ProxyManager({
1086
- proxies: [...],
1087
-
1088
- // Only use proxies for these URL patterns (glob or regex)
1089
- whitelist: [
1090
- '*.example.com', // Glob pattern
1091
- 'https://api.service.io/*',
1092
- /^https:\/\/secure\./ // Regex pattern
1093
- ],
1094
-
1095
- // Never use proxies for these URLs
1096
- blacklist: [
1097
- '*.internal.company.com',
1098
- 'https://localhost/*'
1099
- ]
1100
- });
1101
-
1102
- const client = rezo.create({ proxyManager });
1103
-
1104
- // Uses proxy (matches whitelist)
1105
- await client.get('https://api.example.com/data');
1106
-
1107
- // Direct connection (matches blacklist)
1108
- await client.get('https://app.internal.company.com/status');
1109
- ```
1110
-
1111
- #### Health Monitoring & Failover
1112
-
1113
- The Proxy Manager automatically tracks proxy health and removes failing proxies:
1114
-
1115
- ```typescript
1116
- import { ProxyManager } from 'rezo';
1117
-
1118
- const proxyManager = new ProxyManager({
1119
- proxies: [...],
1120
-
1121
- // Mark proxy as dead after 5 consecutive failures
1122
- maxFailures: 5,
1123
-
1124
- // Re-enable dead proxies after 5 minutes cooldown
1125
- cooldownPeriod: 5 * 60 * 1000,
1126
-
1127
- // Fail request if no proxies available (vs direct connection)
1128
- failWithoutProxy: true
1129
- });
1130
-
1131
- // Check proxy pool status
1132
- const status = proxyManager.getStatus();
1133
- console.log('Active proxies:', status.active);
1134
- console.log('Disabled proxies:', status.disabled);
1135
- console.log('Total proxies:', status.total);
1136
-
1137
- // Check if proxies are available
1138
- if (proxyManager.hasAvailableProxies()) {
1139
- await client.get('https://api.example.com/data');
1140
- }
1141
-
1142
- // Reset all proxy states (re-enable all)
1143
- proxyManager.reset();
1144
- ```
1145
-
1146
- #### Lifecycle Hooks
1147
-
1148
- Monitor and react to proxy events with lifecycle hooks:
1149
-
1150
- ```typescript
1151
- import { ProxyManager } from 'rezo';
1152
-
1153
- const proxyManager = new ProxyManager({
1154
- proxies: [...],
1155
-
1156
- hooks: {
1157
- // Called before selecting a proxy
1158
- beforeProxySelect: (url) => {
1159
- console.log('Selecting proxy for:', url);
1160
- },
1161
-
1162
- // Called after proxy selection
1163
- afterProxySelect: (proxy, url) => {
1164
- console.log('Selected:', proxy.host);
1165
- },
1166
-
1167
- // Called before reporting a proxy error
1168
- beforeProxyError: (proxy, error) => {
1169
- console.log('Proxy failed:', proxy.host, error.message);
1170
- },
1171
-
1172
- // Called after error is recorded
1173
- afterProxyError: (proxy, error, failureCount) => {
1174
- console.log('Failure count:', failureCount);
1175
- },
1176
-
1177
- // Called when proxy is disabled
1178
- afterProxyDisable: (proxy, reason) => {
1179
- console.log('Proxy disabled:', proxy.host, reason);
1180
- },
1181
-
1182
- // Called when proxy is re-enabled
1183
- afterProxyEnable: (proxy) => {
1184
- console.log('Proxy re-enabled:', proxy.host);
1185
- },
1186
-
1187
- // Called after rotation occurs
1188
- afterProxyRotate: (oldProxy, newProxy) => {
1189
- console.log('Rotated from', oldProxy?.host, 'to', newProxy.host);
1190
- }
1191
- }
1192
- });
1193
- ```
1194
-
1195
- #### Instance-Level Hooks
1196
-
1197
- You can also add proxy hooks at the instance level:
1198
-
1199
- ```typescript
1200
- import rezo, { ProxyManager } from 'rezo';
1201
-
1202
- const proxyManager = new ProxyManager({ proxies: [...] });
1203
-
1204
- const client = rezo.create({
1205
- proxyManager,
1206
- hooks: {
1207
- afterProxySelect: (proxy, url) => {
1208
- console.log('Request will use proxy:', proxy.host);
1209
- },
1210
- afterProxyDisable: (proxy) => {
1211
- // Alert monitoring system
1212
- alertMonitoring('Proxy disabled', proxy.host);
1213
- }
1214
- }
1215
- });
1216
- ```
1217
-
1218
- #### Manual Proxy Control
1219
-
1220
- Override Proxy Manager for specific requests:
1221
-
1222
- ```typescript
1223
- import rezo, { ProxyManager } from 'rezo';
1224
-
1225
- const proxyManager = new ProxyManager({ proxies: [...] });
1226
- const client = rezo.create({ proxyManager });
1227
-
1228
- // Use a specific proxy (bypasses Proxy Manager)
1229
- await client.get('https://api.example.com/data', {
1230
- proxy: {
1231
- protocol: 'http',
1232
- host: 'specific-proxy.example.com',
1233
- port: 8080
1234
- }
1235
- });
1236
-
1237
- // Direct connection (bypasses Proxy Manager)
1238
- await client.get('https://api.example.com/data', {
1239
- useProxyManager: false
1240
- });
1241
- ```
1242
-
1243
- #### Proxy Manager Configuration
1244
-
1245
- ```typescript
1246
- interface ProxyManagerConfig {
1247
- // Array of proxy configurations
1248
- proxies: ProxyConfig[];
1249
-
1250
- // Rotation strategy: 'random' | 'sequential' | 'per-proxy-limit'
1251
- rotationStrategy?: string;
1252
-
1253
- // Requests per proxy before rotation (for 'per-proxy-limit')
1254
- perProxyLimit?: number;
1255
-
1256
- // URL patterns to use with proxies (glob or regex)
1257
- whitelist?: (string | RegExp)[];
1258
-
1259
- // URL patterns to bypass proxies (glob or regex)
1260
- blacklist?: (string | RegExp)[];
1261
-
1262
- // Consecutive failures before disabling proxy
1263
- maxFailures?: number;
1264
-
1265
- // Milliseconds before re-enabling disabled proxy
1266
- cooldownPeriod?: number;
1267
-
1268
- // Throw error if no proxy available (vs direct connection)
1269
- failWithoutProxy?: boolean;
1270
-
1271
- // Lifecycle hooks
1272
- hooks?: ProxyManagerHooks;
1273
- }
1274
- ```
1275
-
1276
- #### Adapter Support
1277
-
1278
- | Adapter | Proxy Manager Support |
1279
- |---------|----------------------|
1280
- | HTTP | Full support |
1281
- | HTTP/2 | Full support |
1282
- | cURL | Full support |
1283
- | Fetch | Not supported (browser security) |
1284
- | React Native | Not supported (platform limitations) |
1285
-
1286
- ### Request Queue
1287
-
1288
- Rezo includes a built-in zero-dependency request queue system for rate limiting, priority management, and concurrency control.
1289
-
1290
- #### RezoQueue - General Purpose Queue
1291
-
1292
- ```typescript
1293
- import { RezoQueue, Priority } from 'rezo';
1294
-
1295
- const queue = new RezoQueue({
1296
- concurrency: 5, // Max concurrent tasks
1297
- interval: 1000, // Rate limit interval (ms)
1298
- intervalCap: 10, // Max tasks per interval
1299
- timeout: 30000, // Task timeout (ms)
1300
- autoStart: true // Start processing immediately
1301
- });
1302
-
1303
- // Add tasks with priority
1304
- queue.add(async () => {
1305
- return await fetch('https://api.example.com/data');
1306
- }, { priority: Priority.HIGH });
1307
-
1308
- // Priority constants: LOWEST (0), LOW (25), NORMAL (50), HIGH (75), HIGHEST (100), CRITICAL (1000)
1309
-
1310
- // Event handling
1311
- queue.on('completed', ({ id, result, duration }) => {
1312
- console.log(`Task ${id} completed in ${duration}ms`);
1313
- });
1314
-
1315
- queue.on('error', ({ id, error }) => {
1316
- console.error(`Task ${id} failed:`, error);
1317
- });
1318
-
1319
- // Queue control
1320
- queue.pause();
1321
- queue.resume();
1322
- queue.cancel(taskId);
1323
- queue.clear();
1324
-
1325
- // Statistics
1326
- const stats = queue.stats();
1327
- console.log(`Completed: ${stats.completed}, Failed: ${stats.failed}`);
1328
- ```
1329
-
1330
- #### HttpQueue - HTTP-Aware Queue
1331
-
1332
- ```typescript
1333
- import { HttpQueue, HttpMethodPriority } from 'rezo';
1334
-
1335
- const httpQueue = new HttpQueue({
1336
- concurrency: 10,
1337
- perDomainConcurrency: 2, // Limit concurrent requests per domain
1338
- retryOnRateLimit: true, // Auto-retry on 429 responses
1339
- maxRetries: 3,
1340
- retryDelay: 1000
1341
- });
1342
-
1343
- // Add HTTP requests
1344
- const result = await httpQueue.addHttp(
1345
- 'https://api.example.com/users',
1346
- async () => fetch('https://api.example.com/users'),
1347
- {
1348
- priority: HttpMethodPriority.GET, // GET=75, POST=50, DELETE=25
1349
- timeout: 10000
1350
- }
1351
- );
1352
-
1353
- // Domain-specific control
1354
- httpQueue.pauseDomain('api.example.com');
1355
- httpQueue.resumeDomain('api.example.com');
1356
-
1357
- // Rate limit handling
1358
- httpQueue.onHttp('rateLimited', ({ domain, retryAfter }) => {
1359
- console.log(`Rate limited on ${domain}, retry in ${retryAfter}s`);
1360
- });
1361
-
1362
- // Per-domain statistics
1363
- const domainStats = httpQueue.httpStats();
1364
- console.log(domainStats.byDomain['api.example.com']);
1365
- ```
1366
-
1367
- #### Queue Events
1368
-
1369
- | Event | Description |
1370
- |-------|-------------|
1371
- | `add` | Task added to queue |
1372
- | `start` | Task started processing |
1373
- | `completed` | Task completed successfully |
1374
- | `error` | Task failed with error |
1375
- | `timeout` | Task timed out |
1376
- | `cancelled` | Task was cancelled |
1377
- | `active` | Queue became active |
1378
- | `idle` | Queue became idle |
1379
- | `empty` | Queue is empty |
1380
- | `rateLimited` | Rate limit detected (HttpQueue) |
1381
- | `retry` | Task being retried (HttpQueue) |
1382
-
1383
- ### Streaming
1384
-
1385
- Rezo provides powerful streaming capabilities for handling large data efficiently.
1386
-
1387
- ```typescript
1388
- import rezo from 'rezo';
1389
- import { createWriteStream } from 'fs';
1390
-
1391
- const client = rezo.create();
1392
-
1393
- // Stream response to file
1394
- const response = await client.get('https://example.com/large-file.zip', {
1395
- responseType: 'stream'
1396
- });
1397
-
1398
- const writer = createWriteStream('./download.zip');
1399
- response.data.pipe(writer);
1400
-
1401
- await new Promise((resolve, reject) => {
1402
- writer.on('finish', resolve);
1403
- writer.on('error', reject);
1404
- });
1405
-
1406
- // Stream request body
1407
- import { createReadStream } from 'fs';
1408
-
1409
- await client.post('https://api.example.com/upload', createReadStream('./file.txt'), {
1410
- headers: {
1411
- 'Content-Type': 'application/octet-stream'
1412
- }
1413
- });
1414
- ```
1415
-
1416
- ### File Downloads
1417
-
1418
- Rezo provides a dedicated download API with progress tracking.
1419
-
1420
- ```typescript
1421
- import rezo, { DownloadResponse } from 'rezo';
1422
-
1423
- const client = rezo.create();
1424
-
1425
- // Download with progress
1426
- const download = await client.download('https://example.com/file.zip', {
1427
- outputPath: './downloads/file.zip'
1428
- });
1429
-
1430
- download.on('progress', (progress) => {
1431
- console.log(`Downloaded: ${progress.percent}%`);
1432
- console.log(`Speed: ${progress.speed} bytes/sec`);
1433
- console.log(`ETA: ${progress.eta} seconds`);
1434
- });
1435
-
1436
- download.on('complete', (result) => {
1437
- console.log('Download complete:', result.path);
1438
- console.log('Total size:', result.size);
1439
- console.log('Duration:', result.duration);
1440
- });
1441
-
1442
- download.on('error', (error) => {
1443
- console.error('Download failed:', error.message);
1444
- });
1445
-
1446
- // Wait for completion
1447
- await download.finished();
1448
- ```
1449
-
1450
- ### File Uploads
1451
-
1452
- Upload files with progress tracking and multipart support.
1453
-
1454
- ```typescript
1455
- import rezo, { FormData } from 'rezo';
1456
- import { createReadStream } from 'fs';
1457
-
1458
- const client = rezo.create();
1459
-
1460
- // Simple file upload
1461
- const formData = new FormData();
1462
- formData.append('file', createReadStream('./document.pdf'));
1463
- formData.append('name', 'My Document');
1464
-
1465
- const response = await client.post('https://api.example.com/upload', formData, {
1466
- onUploadProgress: (progress) => {
1467
- console.log(`Uploaded: ${Math.round(progress.loaded / progress.total * 100)}%`);
1468
- }
1469
- });
1470
-
1471
- // Upload with detailed progress
1472
- const upload = await client.upload('https://api.example.com/upload', {
1473
- file: createReadStream('./large-file.zip'),
1474
- filename: 'archive.zip'
1475
- });
1476
-
1477
- upload.on('progress', (progress) => {
1478
- console.log(`Uploaded: ${progress.percent}%`);
1479
- });
1480
-
1481
- await upload.finished();
1482
- console.log('Upload complete:', upload.response.data);
1483
- ```
1484
-
1485
- ### Hooks & Interceptors
1486
-
1487
- Rezo provides a powerful hooks system for request/response interception.
1488
-
1489
- ```typescript
1490
- import rezo from 'rezo';
1491
-
1492
- const client = rezo.create({
1493
- baseURL: 'https://api.example.com'
1494
- });
1495
-
1496
- // Before request hook
1497
- client.hooks.beforeRequest.push((options) => {
1498
- // Add timestamp to all requests
1499
- options.headers['X-Request-Time'] = Date.now().toString();
1500
-
1501
- // Log outgoing requests
1502
- console.log(`-> ${options.method} ${options.url}`);
1503
-
1504
- return options;
1505
- });
1506
-
1507
- // After response hook
1508
- client.hooks.afterResponse.push((response, options) => {
1509
- // Log responses
1510
- console.log(`<- ${response.status} ${options.url}`);
1511
-
1512
- // Transform response data
1513
- if (response.data && typeof response.data === 'object') {
1514
- response.data._receivedAt = new Date().toISOString();
1515
- }
1516
-
1517
- return response;
1518
- });
1519
-
1520
- // Before retry hook
1521
- client.hooks.beforeRetry.push((error, retryCount) => {
1522
- console.log(`Retry attempt ${retryCount} for ${error.config.url}`);
1523
-
1524
- // Optionally modify the request before retry
1525
- error.config.headers['X-Retry-Count'] = retryCount.toString();
1526
- });
1527
-
1528
- // Before error hook (transform errors)
1529
- client.hooks.beforeError.push((error) => {
1530
- // Add additional context to errors
1531
- error.timestamp = new Date().toISOString();
1532
- error.requestId = error.config?.headers?.['X-Request-ID'];
1533
-
1534
- return error;
1535
- });
1536
-
1537
- // Authentication refresh example
1538
- client.hooks.afterResponse.push(async (response, options, client) => {
1539
- if (response.status === 401 && !options._retry) {
1540
- // Refresh token
1541
- const refreshResponse = await client.post('/auth/refresh', {
1542
- refreshToken: getRefreshToken()
1543
- });
1544
-
1545
- // Update authorization header
1546
- const newToken = refreshResponse.data.accessToken;
1547
- client.defaults.headers['Authorization'] = `Bearer ${newToken}`;
1548
-
1549
- // Retry original request
1550
- options._retry = true;
1551
- return client.request(options);
1552
- }
1553
-
1554
- return response;
1555
- });
1556
- ```
1557
-
1558
- ### Retry Logic
1559
-
1560
- Configure automatic retry with exponential backoff.
1561
-
1562
- ```typescript
1563
- import rezo from 'rezo';
1564
-
1565
- const client = rezo.create({
1566
- retry: {
1567
- limit: 3, // Maximum retry attempts
1568
- delay: 1000, // Initial delay (ms)
1569
- maxDelay: 30000, // Maximum delay (ms)
1570
- backoff: 2, // Exponential backoff multiplier
1571
- retryOn: [408, 429, 500, 502, 503, 504] // Status codes to retry
1572
- }
1573
- });
1574
-
1575
- // Custom retry logic
1576
- const customClient = rezo.create({
1577
- retry: {
1578
- limit: 5,
1579
- retryOn: (error, attemptNumber) => {
1580
- // Retry on network errors
1581
- if (error.code === 'ECONNRESET' || error.code === 'ETIMEDOUT') {
1582
- return true;
1583
- }
1584
-
1585
- // Retry on specific status codes
1586
- if (error.response?.status >= 500) {
1587
- return true;
1588
- }
1589
-
1590
- // Don't retry on 4xx errors (except 429)
1591
- if (error.response?.status === 429) {
1592
- return true;
1593
- }
1594
-
1595
- return false;
1596
- }
1597
- }
1598
- });
1599
-
1600
- // Per-request retry configuration
1601
- await client.get('https://api.example.com/data', {
1602
- retry: {
1603
- limit: 10,
1604
- delay: 500
1605
- }
1606
- });
1607
-
1608
- // Disable retry for specific request
1609
- await client.get('https://api.example.com/critical', {
1610
- retry: false
1611
- });
1612
- ```
1613
-
1614
- ### Error Handling
1615
-
1616
- Rezo provides structured errors with actionable information.
1617
-
1618
- ```typescript
1619
- import rezo, { RezoError, isRezoError, RezoErrorCode } from 'rezo';
1620
-
1621
- const client = rezo.create();
1622
-
1623
- try {
1624
- await client.get('https://api.example.com/data');
1625
- } catch (error) {
1626
- if (isRezoError(error)) {
1627
- // Access structured error information
1628
- console.log('Error Code:', error.code);
1629
- console.log('Message:', error.message);
1630
- console.log('Details:', error.details);
1631
- console.log('Suggestion:', error.suggestion);
1632
-
1633
- // Check error type
1634
- if (error.isTimeout) {
1635
- console.log('Request timed out');
1636
- }
1637
-
1638
- if (error.isNetworkError) {
1639
- console.log('Network error occurred');
1640
- }
1641
-
1642
- if (error.isHttpError) {
1643
- console.log('HTTP error:', error.status, error.statusText);
1644
- console.log('Response data:', error.response?.data);
1645
- }
1646
-
1647
- if (error.isProxyError) {
1648
- console.log('Proxy connection failed');
1649
- }
1650
-
1651
- if (error.isTlsError) {
1652
- console.log('TLS/SSL error');
1653
- }
1654
-
1655
- // Check if error is retryable
1656
- if (error.isRetryable) {
1657
- console.log('This error can be retried');
1658
- }
1659
-
1660
- // Access original request configuration
1661
- console.log('Request URL:', error.config?.url);
1662
- console.log('Request Method:', error.config?.method);
1663
-
1664
- // Serialize error (hides sensitive data)
1665
- console.log('Error JSON:', JSON.stringify(error));
1666
- }
1667
- }
1668
-
1669
- // Error code enumeration
1670
- switch (error.code) {
1671
- case RezoErrorCode.TIMEOUT:
1672
- // Handle timeout
1673
- break;
1674
- case RezoErrorCode.NETWORK_ERROR:
1675
- // Handle network error
1676
- break;
1677
- case RezoErrorCode.PROXY_ERROR:
1678
- // Handle proxy error
1679
- break;
1680
- case RezoErrorCode.TLS_ERROR:
1681
- // Handle TLS error
1682
- break;
1683
- case RezoErrorCode.HTTP_ERROR:
1684
- // Handle HTTP error
1685
- break;
1686
- }
1687
- ```
1688
-
1689
- ### Performance Metrics
1690
-
1691
- Track detailed timing information for performance monitoring.
1692
-
1693
- ```typescript
1694
- import rezo, { RezoPerformance } from 'rezo';
1695
-
1696
- const client = rezo.create({
1697
- timing: true // Enable timing collection
1698
- });
1699
-
1700
- const response = await client.get('https://api.example.com/data');
1701
-
1702
- // Access timing metrics
1703
- const timing = response.timing;
1704
- console.log('DNS Lookup:', timing.dns, 'ms');
1705
- console.log('TCP Connect:', timing.connect, 'ms');
1706
- console.log('TLS Handshake:', timing.tls, 'ms');
1707
- console.log('Time to First Byte:', timing.firstByte, 'ms');
1708
- console.log('Download Time:', timing.download, 'ms');
1709
- console.log('Total Time:', timing.total, 'ms');
1710
-
1711
- // Using RezoPerformance utility
1712
- const perf = new RezoPerformance();
1713
-
1714
- perf.mark('start');
1715
- await client.get('https://api.example.com/data');
1716
- perf.mark('end');
1717
-
1718
- const metrics = perf.measure('request', 'start', 'end');
1719
- console.log('Request Duration:', metrics.duration, 'ms');
1720
- ```
1721
-
1722
- ---
1723
-
1724
- ## Platform Support
1725
-
1726
- Rezo is designed for universal JavaScript environments with platform-specific optimizations.
1727
-
1728
- ### Node.js
1729
-
1730
- Full feature support including all adapters, cookie management, proxy, and streaming.
1731
-
1732
- ```typescript
1733
- import rezo from 'rezo';
1734
- // or
1735
- import rezo from 'rezo/platform/node';
1736
- ```
1737
-
1738
- ### Bun
1739
-
1740
- Optimized for Bun runtime with native performance.
1741
-
1742
- ```typescript
1743
- import rezo from 'rezo';
1744
- // or
1745
- import rezo from 'rezo/platform/bun';
1746
- ```
1747
-
1748
- ### Deno
1749
-
1750
- Compatible with Deno's Node.js compatibility layer.
1751
-
1752
- ```typescript
1753
- import rezo from 'npm:rezo';
1754
- // or
1755
- import rezo from 'npm:rezo/platform/deno';
1756
- ```
1757
-
1758
- ### Browser
1759
-
1760
- Lightweight Fetch-based implementation for browsers.
1761
-
1762
- ```typescript
1763
- import rezo from 'rezo';
1764
- // or
1765
- import rezo from 'rezo/platform/browser';
1766
- ```
1767
-
1768
- ### Cloudflare Workers & Edge Runtimes
1769
-
1770
- Edge-compatible Fetch adapter with minimal footprint.
1771
-
1772
- ```typescript
1773
- import rezo from 'rezo';
1774
- // or
1775
- import rezo from 'rezo/platform/worker';
1776
- ```
1777
-
1778
- ### React Native
1779
-
1780
- Mobile-optimized adapter with file system integration.
1781
-
1782
- ```typescript
1783
- import rezo from 'rezo';
1784
- // or
1785
- import rezo from 'rezo/platform/react-native';
1786
- ```
1787
-
1788
- ---
1789
-
1790
- ## Migration Guide
1791
-
1792
- ### Migrating from Fetch API
1793
-
1794
- ```typescript
1795
- // Before (Fetch)
1796
- const response = await fetch('https://api.example.com/data', {
1797
- method: 'POST',
1798
- headers: { 'Content-Type': 'application/json' },
1799
- body: JSON.stringify({ name: 'John' })
1800
- });
1801
- const data = await response.json();
1802
-
1803
- // After (Rezo)
1804
- const response = await rezo.post('https://api.example.com/data', {
1805
- name: 'John'
1806
- });
1807
- const data = response.data; // Automatically parsed
1808
- ```
1809
-
1810
- ### Migrating from Got
1811
-
1812
- ```typescript
1813
- // Before (Got)
1814
- import got from 'got';
1815
- const response = await got.post('https://api.example.com/data', {
1816
- json: { name: 'John' },
1817
- responseType: 'json',
1818
- retry: { limit: 3 }
1819
- });
1820
-
1821
- // After (Rezo)
1822
- import rezo from 'rezo';
1823
- const response = await rezo.post('https://api.example.com/data',
1824
- { name: 'John' },
1825
- { retry: { limit: 3 } }
1826
- );
1827
- ```
1828
-
1829
- ### Migrating from Node-Fetch
1830
-
1831
- ```typescript
1832
- // Before (node-fetch)
1833
- import fetch from 'node-fetch';
1834
- const response = await fetch('https://api.example.com/data');
1835
- const data = await response.json();
1836
-
1837
- // After (Rezo)
1838
- import rezo from 'rezo';
1839
- const { data } = await rezo.get('https://api.example.com/data');
1840
- ```
1841
-
1842
- ---
1843
-
1844
- ## TypeScript
1845
-
1846
- Rezo is written in TypeScript and provides comprehensive type definitions.
1847
-
1848
- ### Generic Response Types
1849
-
1850
- ```typescript
1851
- import rezo from 'rezo';
1852
-
1853
- interface User {
1854
- id: number;
1855
- name: string;
1856
- email: string;
1857
- }
1858
-
1859
- interface ApiResponse<T> {
1860
- data: T;
1861
- meta: { total: number; page: number };
1862
- }
1863
-
1864
- const client = rezo.create({ baseURL: 'https://api.example.com' });
1865
-
1866
- // Typed response
1867
- const response = await client.get<User>('/users/1');
1868
- const user: User = response.data;
1869
-
1870
- // Nested generic types
1871
- const listResponse = await client.get<ApiResponse<User[]>>('/users');
1872
- const users: User[] = listResponse.data.data;
1873
- const total: number = listResponse.data.meta.total;
1874
- ```
1875
-
1876
- ### Request Configuration Types
1877
-
1878
- ```typescript
1879
- import { RezoConfig, RezoResponse, RezoError } from 'rezo';
1880
-
1881
- // Type-safe configuration
1882
- const config: RezoConfig = {
1883
- baseURL: 'https://api.example.com',
1884
- timeout: 30000,
1885
- headers: {
1886
- 'Authorization': 'Bearer token'
1887
- }
1888
- };
1889
-
1890
- // Type-safe error handling
1891
- function handleError(error: RezoError): void {
1892
- if (error.isHttpError) {
1893
- console.log('Status:', error.status);
1894
- }
1895
- }
1896
- ```
1897
-
1898
- ### Custom Type Guards
1899
-
1900
- ```typescript
1901
- import { isRezoError, RezoError } from 'rezo';
1902
-
1903
- try {
1904
- await rezo.get('/data');
1905
- } catch (error) {
1906
- if (isRezoError(error)) {
1907
- // TypeScript knows error is RezoError here
1908
- console.log(error.code);
1909
- console.log(error.details);
1910
- }
1911
- }
1912
- ```
1913
-
1914
- ---
1915
-
1916
- ## Crawler Module
1917
-
1918
- Rezo includes a powerful web crawler module for web scraping scenarios.
1919
-
1920
- ```typescript
1921
- import { Crawler, CrawlerOptions } from 'rezo/crawler';
1922
-
1923
- const options = new CrawlerOptions()
1924
- .setGlobalProxy({ host: 'proxy.example.com', port: 8080 })
1925
- .setGlobalHeaders({ 'User-Agent': 'Mozilla/5.0...' })
1926
- .addLimiter({ domain: 'example.com', concurrency: 2, interval: 1000 });
1927
-
1928
- const crawler = new Crawler(options);
1929
-
1930
- crawler.onDocument(async (doc, url) => {
1931
- const title = doc.querySelector('title')?.textContent;
1932
- console.log(`Title: ${title}`);
1933
- });
1934
-
1935
- crawler.onAnchor((href, anchor) => {
1936
- console.log(`Found link: ${href}`);
1937
- });
1938
-
1939
- await crawler.crawl('https://example.com');
1940
- ```
1941
-
1942
- ---
1943
-
1944
- ## DOM Module
1945
-
1946
- Rezo provides a lightweight DOM parsing module for server-side HTML manipulation. Built on [linkedom](https://github.com/WebReflection/linkedom), it enables fast, standards-compliant DOM operations in Node, Bun, Deno or Edge environments - perfect for web scraping, HTML transformation, and testing.
1947
-
1948
- ### Parsing HTML
1949
-
1950
- ```typescript
1951
- import { parseHTML } from 'rezo/dom';
1952
-
1953
- // Parse HTML and work with the document
1954
- const { document, window } = parseHTML(`
1955
- <html>
1956
- <body>
1957
- <h1>Hello World</h1>
1958
- <ul id="items">
1959
- <li>Item 1</li>
1960
- <li>Item 2</li>
1961
- </ul>
1962
- </body>
1963
- </html>
1964
- `);
1965
-
1966
- // Use familiar DOM APIs
1967
- console.log(document.querySelector('h1')?.textContent); // 'Hello World'
1968
- console.log(document.querySelectorAll('li').length); // 2
1969
- ```
1970
-
1971
- ### Using with Rezo HTTP Client
1972
-
1973
- ```typescript
1974
- import rezo from 'rezo';
1975
- import { parseHTML } from 'rezo/dom';
1976
-
1977
- // Fetch and parse a webpage
1978
- const { data: html } = await rezo.get('https://example.com');
1979
- const { document } = parseHTML(html);
1980
-
1981
- // Extract data from the page
1982
- const title = document.querySelector('title')?.textContent;
1983
- const links = [...document.querySelectorAll('a')].map(a => a.getAttribute('href'));
1984
- ```
1985
-
1986
- ### DOMParser Interface
1987
-
1988
- ```typescript
1989
- import { DOMParser } from 'rezo/dom';
1990
-
1991
- const parser = new DOMParser();
1992
- const doc = parser.parseFromString('<div class="content">Text</div>', 'text/html');
1993
- console.log(doc.querySelector('.content')?.textContent); // 'Text'
1994
- ```
1995
-
1996
- ### Available APIs
1997
-
1998
- | Export | Description |
1999
- |--------|-------------|
2000
- | `parseHTML` | Parse HTML string into window/document objects |
2001
- | `DOMParser` | Standard W3C DOMParser interface |
2002
- | `Document` | Document constructor for creating new documents |
2003
- | `Event` / `CustomEvent` | DOM Event interfaces |
2004
- | `EventTarget` | Event handling interface |
2005
- | `NodeList` | Standard NodeList interface |
2006
-
2007
- ---
2008
-
2009
- ## Troubleshooting
2010
-
2011
- ### Common Issues
2012
-
2013
- #### Request Timeout
2014
-
2015
- ```typescript
2016
- // Increase timeout
2017
- const client = rezo.create({
2018
- timeout: 60000, // 60 seconds
2019
- connectTimeout: 10000 // 10 seconds for connection
2020
- });
2021
- ```
2022
-
2023
- #### SSL Certificate Errors
2024
-
2025
- ```typescript
2026
- // For development only - not recommended for production
2027
- const client = rezo.create({
2028
- rejectUnauthorized: false
2029
- });
2030
-
2031
- // Better: provide custom CA
2032
- const client = rezo.create({
2033
- ca: fs.readFileSync('./custom-ca.pem')
2034
- });
2035
- ```
2036
-
2037
- #### Proxy Connection Issues
2038
-
2039
- ```typescript
2040
- // Verify proxy settings
2041
- const client = rezo.create({
2042
- proxy: {
2043
- protocol: 'http', // Ensure correct protocol
2044
- host: 'proxy.example.com',
2045
- port: 8080
2046
- }
2047
- });
2048
-
2049
- // Test proxy connection
2050
- try {
2051
- await client.get('https://httpbin.org/ip');
2052
- } catch (error) {
2053
- if (error.isProxyError) {
2054
- console.log('Proxy connection failed:', error.details);
2055
- }
2056
- }
2057
- ```
2058
-
2059
- #### Memory Issues with Large Files
2060
-
2061
- ```typescript
2062
- // Use streaming for large files
2063
- const response = await client.get('https://example.com/large-file', {
2064
- responseType: 'stream'
2065
- });
2066
-
2067
- // Or use download API
2068
- const download = await client.download('https://example.com/large-file', {
2069
- outputPath: './large-file.zip'
2070
- });
2071
- ```
2072
-
2073
- ### Debug Mode
2074
-
2075
- ```typescript
2076
- // Enable debug logging
2077
- const client = rezo.create({
2078
- debug: true
2079
- });
2080
-
2081
- // Or set environment variable
2082
- process.env.REZO_DEBUG = 'true';
2083
- ```
2084
-
2085
- ---
2086
-
2087
- ## Contributing
2088
-
2089
- We welcome contributions to Rezo! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
2090
-
2091
- ### Development Setup
2092
-
2093
- ```bash
2094
- # Clone repository
2095
- git clone https://github.com/yuniqsolutions/rezo.git
2096
- cd rezo
2097
-
2098
- # Install dependencies
2099
- bun install
2100
-
2101
- # Run tests
2102
- bun test
2103
-
2104
- # Build
2105
- bun run bundle
2106
-
2107
- # Lint
2108
- bun run lint
2109
- ```
2110
-
2111
- ### Running Tests
2112
-
2113
- ```bash
2114
- # Run all tests
2115
- bun test
2116
-
2117
- # Run with coverage
2118
- bun run test:coverage
2119
-
2120
- # Run specific test file
2121
- bun test src/adapters/http.test.ts
2122
- ```
2123
-
2124
- ---
2125
-
2126
- ## Acknowledgments
2127
-
2128
- Rezo was built with inspiration from the JavaScript HTTP client ecosystem, including the excellent work done by the teams behind Got, Ky, Undici, and other HTTP client libraries. We thank the open-source community for their contributions to the JavaScript ecosystem.
2129
-
2130
- ---
2131
-
2132
- ## License
2133
-
2134
- Rezo is open source software licensed under the [MIT License](LICENSE).
2135
-
2136
- Copyright (c) 2024-2025 Yuniq Solutions Tech
2137
-
2138
- See the [LICENSE](LICENSE) file for the complete license text.
2139
-
2140
- ---
2141
-
2142
- <p align="center">
2143
- <img src="https://raw.githubusercontent.com/yuniqsolutions/rezo/main/assets/icon.svg" alt="Rezo Icon" width="60">
2144
- </p>
175
+ MIT Made with care by [Yuniq Solutions Tech](https://yuniq.solutions). Built by developers, for developers.
2145
176
 
2146
177
  <p align="center">
2147
- <strong>Built with lightning speed in mind</strong><br>
2148
- <sub>Made by <a href="https://yuniq.solutions">Yuniq Solutions Tech</a></sub>
178
+ <img src="https://raw.githubusercontent.com/yuniqsolutions/rezo/main/assets/icon.svg" alt="Rezo" width="40">
2149
179
  </p>