@scirexs/fetchy 0.4.2 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +302 -172
- package/esm/main.js +1 -1
- package/esm/mod.js +1 -1
- package/package.json +7 -1
- package/types/main.d.ts +194 -60
- package/types/main.d.ts.map +1 -1
- package/types/mod.d.ts +2 -2
- package/types/mod.d.ts.map +1 -1
- package/types/types.d.ts +2 -12
- package/types/types.d.ts.map +1 -1
package/README.md
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
[](https://jsr.io/@scirexs/fetchy)
|
|
5
5
|
[](https://github.com/scirexs/fetchy/blob/main/LICENSE)
|
|
6
6
|
|
|
7
|
-
A lightweight, type-safe fetch wrapper with built-in retry logic, timeout handling, and automatic body parsing.
|
|
7
|
+
A lightweight, type-safe fetch wrapper with built-in retry logic, timeout handling, and automatic body parsing. Works in Deno, Node.js, and modern browsers.
|
|
8
8
|
|
|
9
9
|
## Features
|
|
10
10
|
|
|
11
|
-
- **Lightweight** -
|
|
11
|
+
- **Lightweight** - Bundle size is ~6KB uncompressed, ~3KB gzipped, zero dependencies
|
|
12
12
|
- **Simple API** - Drop-in replacement for native fetch with enhanced capabilities
|
|
13
13
|
- **Timeout Support** - Configurable request timeouts with automatic cancellation
|
|
14
14
|
- **Retry Logic** - Exponential backoff with Retry-After header support
|
|
@@ -16,6 +16,7 @@ A lightweight, type-safe fetch wrapper with built-in retry logic, timeout handli
|
|
|
16
16
|
- **Bearer Token Helper** - Built-in Authorization header management
|
|
17
17
|
- **Jitter Support** - Prevent thundering herd with randomized delays
|
|
18
18
|
- **Automatic Body Parsing** - Automatic JSON serialization and Content-Type detection
|
|
19
|
+
- **Fluent Interface** - Class-based API with both instance and static methods
|
|
19
20
|
|
|
20
21
|
## Installation
|
|
21
22
|
|
|
@@ -30,130 +31,190 @@ deno add jsr:@scirexs/fetchy
|
|
|
30
31
|
## Quick Start
|
|
31
32
|
|
|
32
33
|
```ts
|
|
33
|
-
import { fetchy,
|
|
34
|
+
import { fetchy, sfetchy, Fetchy } from "@scirexs/fetchy";
|
|
34
35
|
|
|
35
|
-
// Simple GET request with timeout
|
|
36
|
-
const response = await fetchy("https://api.example.com/data"
|
|
37
|
-
timeout: 10
|
|
38
|
-
});
|
|
36
|
+
// Simple GET request with timeout and retry
|
|
37
|
+
const response = await fetchy("https://api.example.com/data");
|
|
39
38
|
|
|
40
|
-
// Auto-parsed JSON response
|
|
39
|
+
// Auto-parsed JSON response with safe error handling
|
|
41
40
|
interface User {
|
|
42
41
|
id: number;
|
|
43
42
|
name: string;
|
|
44
43
|
}
|
|
45
44
|
|
|
46
|
-
const user = await
|
|
47
|
-
console.log(user
|
|
45
|
+
const user = await sfetchy<User>("https://api.example.com/user/1", { timeout: 10 }, "json");
|
|
46
|
+
console.log(user.name);
|
|
47
|
+
|
|
48
|
+
// Fluent API with reusable configuration
|
|
49
|
+
const client = new Fetchy({
|
|
50
|
+
bearer: "token",
|
|
51
|
+
timeout: 10,
|
|
52
|
+
retry: { maxAttempts: 5 }
|
|
53
|
+
});
|
|
54
|
+
const data = await client.json<User>("https://api.example.com/user/1");
|
|
48
55
|
```
|
|
49
56
|
|
|
50
57
|
## API Reference
|
|
51
58
|
|
|
52
|
-
### `fetchy(url, options?)`
|
|
59
|
+
### `fetchy(url, options?, parse?)`
|
|
53
60
|
|
|
54
|
-
Performs an HTTP request
|
|
61
|
+
Performs an HTTP request with enhanced features. Throws errors on failure by default.
|
|
55
62
|
|
|
56
63
|
#### Parameters
|
|
57
64
|
|
|
58
65
|
- `url`: `string | URL | Request | null` - The request URL
|
|
59
66
|
- `options`: `FetchyOptions` (optional) - Configuration options
|
|
67
|
+
- `parse`: `"json" | "text" | "bytes" | "blob" | "buffer"` (optional) - Response parsing method
|
|
60
68
|
|
|
61
69
|
#### Returns
|
|
62
70
|
|
|
63
|
-
|
|
71
|
+
- Without `parse`: `Promise<Response>`
|
|
72
|
+
- With `parse="json"`: `Promise<T>`
|
|
73
|
+
- With `parse="text"`: `Promise<string>`
|
|
74
|
+
- With `parse="bytes"`: `Promise<Uint8Array>`
|
|
75
|
+
- With `parse="blob"`: `Promise<Blob>`
|
|
76
|
+
- With `parse="buffer"`: `Promise<ArrayBuffer>`
|
|
64
77
|
|
|
65
78
|
#### Example
|
|
66
79
|
|
|
67
80
|
```ts
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
body: { key: "value" },
|
|
71
|
-
timeout: 10,
|
|
72
|
-
retry: { maxAttempts: 3, interval: 2 },
|
|
73
|
-
bearer: "your-token-here"
|
|
74
|
-
});
|
|
81
|
+
// Get Response object
|
|
82
|
+
const response = await fetchy("https://api.example.com/data");
|
|
75
83
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
84
|
+
// Direct JSON parsing
|
|
85
|
+
const user = await fetchy<User>("https://api.example.com/user", {}, "json");
|
|
86
|
+
|
|
87
|
+
// POST with automatic body serialization
|
|
88
|
+
const result = await fetchy("https://api.example.com/create", {
|
|
89
|
+
body: { name: "John", age: 30 },
|
|
90
|
+
bearer: "token"
|
|
91
|
+
}, "json");
|
|
92
|
+
|
|
93
|
+
// Binary data
|
|
94
|
+
const image = await fetchy("https://api.example.com/image.png", {}, "bytes");
|
|
79
95
|
```
|
|
80
96
|
|
|
81
|
-
### `
|
|
97
|
+
### `sfetchy(url, options?, parse?)`
|
|
82
98
|
|
|
83
|
-
Performs an HTTP request
|
|
99
|
+
Performs an HTTP request with safe error handling. Returns `null` on any failure instead of throwing.
|
|
84
100
|
|
|
85
101
|
#### Parameters
|
|
86
102
|
|
|
87
|
-
|
|
88
|
-
- `type`: `"text" | "json" | "bytes" | "auto"` (default: `"auto"`) - Response parsing type
|
|
89
|
-
- `options`: `FetchyOptions` (optional) - Configuration options
|
|
103
|
+
Same as `fetchy()`.
|
|
90
104
|
|
|
91
105
|
#### Returns
|
|
92
106
|
|
|
93
|
-
|
|
107
|
+
Same as `fetchy()` but with `| null` added to each return type.
|
|
94
108
|
|
|
95
109
|
#### Example
|
|
96
110
|
|
|
97
111
|
```ts
|
|
98
|
-
//
|
|
99
|
-
const data = await
|
|
112
|
+
// Returns null instead of throwing
|
|
113
|
+
const data = await sfetchy("https://api.example.com/data", {}, "json");
|
|
114
|
+
if (data === null) {
|
|
115
|
+
console.log("Request failed gracefully");
|
|
116
|
+
}
|
|
100
117
|
|
|
101
|
-
//
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
price: number;
|
|
118
|
+
// Safe Response retrieval
|
|
119
|
+
const response = await sfetchy("https://api.example.com/data");
|
|
120
|
+
if (response?.ok) {
|
|
121
|
+
const json = await response.json();
|
|
106
122
|
}
|
|
107
|
-
|
|
123
|
+
```
|
|
108
124
|
|
|
109
|
-
|
|
110
|
-
const html = await fetchyb("https://example.com", "text");
|
|
125
|
+
### `Fetchy` Class
|
|
111
126
|
|
|
112
|
-
|
|
113
|
-
|
|
127
|
+
A fluent HTTP client class that provides both instance and static methods.
|
|
128
|
+
|
|
129
|
+
#### Instance Methods
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
const client = new Fetchy(options);
|
|
133
|
+
|
|
134
|
+
// Parsing methods
|
|
135
|
+
await client.fetch(url?) // Returns Response
|
|
136
|
+
await client.json<T>(url?) // Returns T
|
|
137
|
+
await client.text(url?) // Returns string
|
|
138
|
+
await client.bytes(url?) // Returns Uint8Array
|
|
139
|
+
await client.blob(url?) // Returns Blob
|
|
140
|
+
await client.buffer(url?) // Returns ArrayBuffer
|
|
141
|
+
await client.safe(url?) // Returns Response | null
|
|
142
|
+
await client.sjson<T>(url?) // Returns T | null
|
|
143
|
+
await client.stext(url?) // Returns string | null
|
|
144
|
+
await client.sbytes(url?) // Returns Uint8Array | null
|
|
145
|
+
await client.sblob(url?) // Returns Blob | null
|
|
146
|
+
await client.sbuffer(url?) // Returns ArrayBuffer | null
|
|
114
147
|
```
|
|
115
148
|
|
|
116
|
-
|
|
149
|
+
#### Static Methods
|
|
117
150
|
|
|
118
|
-
|
|
151
|
+
```ts
|
|
152
|
+
// Same methods available as static
|
|
153
|
+
await Fetchy.fetch(url, options?)
|
|
154
|
+
await Fetchy.json<T>(url, options?)
|
|
155
|
+
await Fetchy.text(url, options?)
|
|
156
|
+
await Fetchy.bytes(url, options?)
|
|
157
|
+
await Fetchy.blob(url, options?)
|
|
158
|
+
await Fetchy.buffer(url, options?)
|
|
159
|
+
await Fetchy.safe(url, options?)
|
|
160
|
+
await Fetchy.sjson<T>(url, options?)
|
|
161
|
+
await Fetchy.stext(url, options?)
|
|
162
|
+
await Fetchy.sbytes(url, options?)
|
|
163
|
+
await Fetchy.sblob(url, options?)
|
|
164
|
+
await Fetchy.sbuffer(url, options?)
|
|
165
|
+
```
|
|
119
166
|
|
|
120
|
-
####
|
|
167
|
+
#### Example
|
|
121
168
|
|
|
122
169
|
```ts
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
170
|
+
// Instance usage - reuse configuration
|
|
171
|
+
const client = new Fetchy({
|
|
172
|
+
bearer: "token123",
|
|
173
|
+
timeout: 10,
|
|
174
|
+
retry: { maxAttempts: 3 }
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
const user = await client.json<User>("https://api.example.com/user");
|
|
178
|
+
const posts = await client.json<Post[]>("https://api.example.com/posts");
|
|
179
|
+
|
|
180
|
+
// Static usage - one-off requests
|
|
181
|
+
const data = await Fetchy.json("https://api.example.com/data");
|
|
182
|
+
|
|
183
|
+
// Safe mode
|
|
184
|
+
const result = await Fetchy.sjson("https://api.example.com/data");
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Configuration
|
|
188
|
+
|
|
189
|
+
### `FetchyOptions`
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
interface FetchyOptions extends Omit<RequestInit, "body"> {
|
|
193
|
+
// Request URL (allows null url parameter with this option)
|
|
194
|
+
url?: string | URL;
|
|
127
195
|
|
|
128
196
|
// Request body (auto-serializes JSON; ReadableStream is NOT supported)
|
|
129
|
-
// type JSONValue = string | number | boolean | null | JSONValue[] | { [key: string]: JSONValue };
|
|
130
197
|
body?: JSONValue | FormData | URLSearchParams | Blob | ArrayBuffer | string;
|
|
131
198
|
|
|
132
|
-
// Timeout in seconds (default: 15)
|
|
133
|
-
timeout?: number;
|
|
199
|
+
// Timeout in seconds (default: 15, set to 0 to disable)
|
|
200
|
+
timeout?: number;
|
|
134
201
|
|
|
135
|
-
// Retry configuration
|
|
202
|
+
// Retry configuration (set to false to disable)
|
|
136
203
|
retry?: {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
retryAfter?: boolean;
|
|
141
|
-
} | false;
|
|
204
|
+
interval?: number; // Base interval in seconds (default: 3)
|
|
205
|
+
maxInterval?: number; // Maximum interval cap (default: 30)
|
|
206
|
+
maxAttempts?: number; // Maximum retry attempts (default: 3)
|
|
207
|
+
retryAfter?: boolean; // Respect Retry-After header (default: true)
|
|
208
|
+
} | false;
|
|
142
209
|
|
|
143
210
|
// Bearer token (automatically adds "Bearer " prefix)
|
|
144
211
|
bearer?: string;
|
|
145
212
|
|
|
146
|
-
//
|
|
147
|
-
onError?: {
|
|
148
|
-
onNative?: boolean; // Throw on native errors (default: true)
|
|
149
|
-
onStatus?: boolean; // Throw on 4xx/5xx status (default: false)
|
|
150
|
-
} | boolean; // Set to true to throw on all errors
|
|
151
|
-
|
|
152
|
-
// Initial jitter delay in seconds
|
|
213
|
+
// Initial jitter delay in seconds before request (default: 0)
|
|
153
214
|
delay?: number;
|
|
154
|
-
|
|
155
|
-
//
|
|
156
|
-
|
|
215
|
+
|
|
216
|
+
// Use native fetch error behavior (no HTTPStatusError on 4xx/5xx)
|
|
217
|
+
native?: true;
|
|
157
218
|
}
|
|
158
219
|
```
|
|
159
220
|
|
|
@@ -169,10 +230,7 @@ interface FetchyOptions extends RequestInit {
|
|
|
169
230
|
maxInterval: 30, // 30 seconds maximum interval
|
|
170
231
|
retryAfter: true // Respect Retry-After header
|
|
171
232
|
},
|
|
172
|
-
|
|
173
|
-
onNative: true, // Throw native errors
|
|
174
|
-
onStatus: false // Don't throw on HTTP errors
|
|
175
|
-
},
|
|
233
|
+
native: undefined // Throws HTTPStatusError on non-OK status (4xx, 5xx)
|
|
176
234
|
}
|
|
177
235
|
```
|
|
178
236
|
|
|
@@ -180,66 +238,111 @@ interface FetchyOptions extends RequestInit {
|
|
|
180
238
|
|
|
181
239
|
#### Method
|
|
182
240
|
|
|
183
|
-
If
|
|
241
|
+
- If body is provided without method: defaults to `"POST"`
|
|
242
|
+
- If Request object is passed: uses its method
|
|
243
|
+
- Otherwise: defaults to `"GET"`
|
|
184
244
|
|
|
185
245
|
#### Headers
|
|
186
246
|
|
|
187
247
|
The following headers are automatically set if not specified:
|
|
188
248
|
|
|
189
249
|
- **Accept**: `application/json, text/plain`
|
|
190
|
-
- **Content-Type**: Automatically determined based on
|
|
191
|
-
- `string`, `URLSearchParams`, `FormData`, `Blob` with type: Not set
|
|
250
|
+
- **Content-Type**: Automatically determined based on body type:
|
|
251
|
+
- `string`, `URLSearchParams`, `FormData`, `Blob` with type: Not set (native fetch handles it)
|
|
192
252
|
- `JSONValue`: `application/json`
|
|
193
|
-
- `Blob` without type
|
|
194
|
-
|
|
195
|
-
- **Authorization**: Set to `Bearer ${options.bearer}` if `options.bearer` is provided.
|
|
253
|
+
- `Blob` without type, `ArrayBuffer`: `application/octet-stream`
|
|
254
|
+
- **Authorization**: `Bearer ${options.bearer}` if bearer is provided
|
|
196
255
|
|
|
197
|
-
**Note
|
|
198
|
-
|
|
199
|
-
**Note 2:** If you pass a body through a Request object, Content-Type will NOT be set automatically by this package.
|
|
256
|
+
**Note:** If you pass a body through a Request object, Content-Type is NOT set automatically by this package.
|
|
200
257
|
|
|
201
258
|
## Error Handling
|
|
202
259
|
|
|
203
|
-
### Timeout
|
|
204
|
-
|
|
205
|
-
If the timeout duration specified in the `timeout` option is exceeded, the request is aborted using the standard `AbortSignal.timeout()` method. Note that there is no specific error class for timeout errors; they will be thrown as standard `AbortError`s.
|
|
206
|
-
|
|
207
260
|
### HTTPStatusError
|
|
208
261
|
|
|
209
|
-
|
|
262
|
+
Thrown when response status is not OK (4xx, 5xx) unless `native: true` is set.
|
|
263
|
+
|
|
264
|
+
```ts
|
|
265
|
+
try {
|
|
266
|
+
await fetchy("https://api.example.com/data");
|
|
267
|
+
} catch (error) {
|
|
268
|
+
if (error instanceof HTTPStatusError) {
|
|
269
|
+
console.error(error.status); // 404
|
|
270
|
+
console.error(error.body); // Response body text
|
|
271
|
+
console.error(error.message); // "404 Not Found: (no response body)"
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
```
|
|
210
275
|
|
|
211
276
|
### RedirectError
|
|
212
277
|
|
|
213
|
-
|
|
278
|
+
Thrown when `redirect: "error"` is set and a redirect response (3xx) is received.
|
|
279
|
+
|
|
280
|
+
```ts
|
|
281
|
+
try {
|
|
282
|
+
await fetchy("https://example.com/redirect", {
|
|
283
|
+
redirect: "error"
|
|
284
|
+
});
|
|
285
|
+
} catch (error) {
|
|
286
|
+
if (error instanceof RedirectError) {
|
|
287
|
+
console.error(error.status); // 301
|
|
288
|
+
console.error(error.message); // "301 Moved Permanently"
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### Native Errors
|
|
294
|
+
|
|
295
|
+
Other errors (network failures, timeout, abort) are thrown as standard errors:
|
|
296
|
+
- `TypeError`: Network error, DNS resolution failure
|
|
297
|
+
- `DOMException`: Timeout or abort via AbortSignal
|
|
214
298
|
|
|
215
|
-
###
|
|
299
|
+
### Safe Error Handling
|
|
216
300
|
|
|
217
|
-
|
|
301
|
+
Use `sfetchy()` or `Fetchy.safe()` to return `null` instead of throwing:
|
|
302
|
+
|
|
303
|
+
```ts
|
|
304
|
+
const data = await sfetchy("https://api.example.com/data", {}, "json");
|
|
305
|
+
if (data === null) {
|
|
306
|
+
// Handle error gracefully
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### Native Mode
|
|
311
|
+
|
|
312
|
+
Set `native: true` to disable HTTPStatusError and get native fetch behavior:
|
|
313
|
+
|
|
314
|
+
```ts
|
|
315
|
+
const response = await fetchy("https://api.example.com/data", {
|
|
316
|
+
native: true
|
|
317
|
+
});
|
|
318
|
+
// Returns Response even for 4xx/5xx status codes
|
|
319
|
+
```
|
|
218
320
|
|
|
219
321
|
## Usage Examples
|
|
220
322
|
|
|
221
323
|
### Basic Requests
|
|
222
324
|
|
|
223
325
|
```ts
|
|
224
|
-
import { fetchy,
|
|
326
|
+
import { fetchy, sfetchy } from "@scirexs/fetchy";
|
|
225
327
|
|
|
226
|
-
// GET
|
|
227
|
-
const data = await
|
|
328
|
+
// GET with automatic JSON parsing
|
|
329
|
+
const data = await fetchy<User[]>("https://api.example.com/users", {}, "json");
|
|
228
330
|
|
|
229
331
|
// POST with JSON body
|
|
230
|
-
const result = await
|
|
332
|
+
const result = await fetchy("https://api.example.com/create", {
|
|
231
333
|
body: { name: "John", email: "john@example.com" }
|
|
232
|
-
});
|
|
334
|
+
}, "json");
|
|
233
335
|
|
|
234
336
|
// Custom headers
|
|
235
337
|
const response = await fetchy("https://api.example.com/data", {
|
|
236
|
-
headers: {
|
|
237
|
-
"X-Custom-Header": "value"
|
|
238
|
-
}
|
|
338
|
+
headers: { "X-Custom-Header": "value" }
|
|
239
339
|
});
|
|
240
340
|
|
|
241
|
-
// Reuse options as preset configuration
|
|
242
|
-
const options = {
|
|
341
|
+
// Reuse options as preset configuration
|
|
342
|
+
const options: FetchyOptions = {
|
|
343
|
+
url: "https://api.example.com/data",
|
|
344
|
+
retry: false
|
|
345
|
+
};
|
|
243
346
|
await fetchy(null, options);
|
|
244
347
|
await fetchy(null, options);
|
|
245
348
|
```
|
|
@@ -248,16 +351,14 @@ await fetchy(null, options);
|
|
|
248
351
|
|
|
249
352
|
```ts
|
|
250
353
|
// Bearer token authentication
|
|
251
|
-
const user = await
|
|
354
|
+
const user = await fetchy<User>("https://api.example.com/me", {
|
|
252
355
|
bearer: "your-access-token"
|
|
253
|
-
});
|
|
356
|
+
}, "json");
|
|
254
357
|
|
|
255
358
|
// Custom authorization
|
|
256
|
-
const data = await
|
|
257
|
-
headers: {
|
|
258
|
-
|
|
259
|
-
}
|
|
260
|
-
});
|
|
359
|
+
const data = await fetchy("https://api.example.com/data", {
|
|
360
|
+
headers: { "Authorization": "Basic " + btoa("user:pass") }
|
|
361
|
+
}, "json");
|
|
261
362
|
```
|
|
262
363
|
|
|
263
364
|
### Timeout and Retry
|
|
@@ -269,15 +370,15 @@ const response = await fetchy("https://slow-api.example.com", {
|
|
|
269
370
|
});
|
|
270
371
|
|
|
271
372
|
// Retry with exponential backoff
|
|
272
|
-
//
|
|
273
|
-
const data = await
|
|
373
|
+
// Intervals: 1s (3^0), 3s (3^1), 9s (3^2), 27s (3^3), capped at maxInterval
|
|
374
|
+
const data = await fetchy("https://api.example.com/data", {
|
|
274
375
|
retry: {
|
|
275
|
-
maxAttempts: 5,
|
|
276
|
-
interval: 3,
|
|
277
|
-
maxInterval: 60,
|
|
278
|
-
retryAfter: true
|
|
376
|
+
maxAttempts: 5,
|
|
377
|
+
interval: 3,
|
|
378
|
+
maxInterval: 60,
|
|
379
|
+
retryAfter: true
|
|
279
380
|
}
|
|
280
|
-
});
|
|
381
|
+
}, "json");
|
|
281
382
|
|
|
282
383
|
// Disable retry
|
|
283
384
|
const response = await fetchy("https://api.example.com/data", {
|
|
@@ -285,92 +386,125 @@ const response = await fetchy("https://api.example.com/data", {
|
|
|
285
386
|
});
|
|
286
387
|
```
|
|
287
388
|
|
|
288
|
-
### Error Handling
|
|
389
|
+
### Error Handling Patterns
|
|
289
390
|
|
|
290
391
|
```ts
|
|
291
|
-
import { fetchy, HTTPStatusError, RedirectError } from "@scirexs/fetchy";
|
|
392
|
+
import { fetchy, sfetchy, HTTPStatusError, RedirectError } from "@scirexs/fetchy";
|
|
292
393
|
|
|
293
|
-
//
|
|
394
|
+
// Default: throws on error
|
|
294
395
|
try {
|
|
295
|
-
const
|
|
396
|
+
const data = await fetchy("https://api.example.com/data", {}, "json");
|
|
296
397
|
} catch (error) {
|
|
297
|
-
|
|
398
|
+
if (error instanceof HTTPStatusError) {
|
|
399
|
+
console.error(`HTTP ${error.status}: ${error.body}`);
|
|
400
|
+
}
|
|
298
401
|
}
|
|
299
402
|
|
|
300
|
-
//
|
|
403
|
+
// Safe mode: returns null
|
|
404
|
+
const data = await sfetchy("https://api.example.com/data", {}, "json");
|
|
405
|
+
if (data === null) {
|
|
406
|
+
console.log("Request failed, using default");
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// Native mode: no HTTPStatusError
|
|
301
410
|
const response = await fetchy("https://api.example.com/data", {
|
|
302
|
-
|
|
411
|
+
native: true
|
|
303
412
|
});
|
|
304
|
-
if (response
|
|
305
|
-
console.
|
|
413
|
+
if (!response.ok) {
|
|
414
|
+
console.error("Request failed with status", response.status);
|
|
306
415
|
}
|
|
416
|
+
```
|
|
307
417
|
|
|
308
|
-
|
|
309
|
-
try {
|
|
310
|
-
const response = await fetchy("https://api.example.com/data", {
|
|
311
|
-
onError: { onNative: false, onStatus: true }
|
|
312
|
-
});
|
|
313
|
-
} catch (error) {
|
|
314
|
-
if (error instanceof HTTPStatusError) {
|
|
315
|
-
console.error("HTTP error:", error.message); // e.g., "404 Not Found: (no response body)"
|
|
316
|
-
console.error("Status:", error.status);
|
|
317
|
-
console.error("Body:", error.body);
|
|
318
|
-
}
|
|
319
|
-
}
|
|
418
|
+
### Fluent API
|
|
320
419
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
420
|
+
```ts
|
|
421
|
+
// Create reusable client
|
|
422
|
+
const api = new Fetchy({
|
|
423
|
+
url: "https://api.example.com",
|
|
424
|
+
bearer: "token",
|
|
425
|
+
timeout: 10,
|
|
426
|
+
retry: { maxAttempts: 3 }
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
// Instance methods
|
|
430
|
+
const users = await api.json<User[]>("/users");
|
|
431
|
+
const post = await api.json<Post>("/posts/1");
|
|
432
|
+
const text = await api.text("/readme.txt");
|
|
433
|
+
|
|
434
|
+
// Safe methods
|
|
435
|
+
const data = await api.sjson("/maybe-fails");
|
|
436
|
+
if (data !== null) {
|
|
437
|
+
// Process data
|
|
331
438
|
}
|
|
439
|
+
|
|
440
|
+
// Static methods for one-off requests
|
|
441
|
+
const response = await Fetchy.fetch("https://example.com");
|
|
442
|
+
const json = await Fetchy.json("https://api.example.com/data");
|
|
332
443
|
```
|
|
333
444
|
|
|
334
445
|
### Advanced Usage
|
|
335
446
|
|
|
447
|
+
#### Jitter and Delays
|
|
336
448
|
```ts
|
|
337
449
|
// Jitter to prevent thundering herd
|
|
338
450
|
const response = await fetchy("https://api.example.com/data", {
|
|
339
|
-
delay: 2, // Random delay up to 2 seconds
|
|
451
|
+
delay: 2, // Random delay up to 2 seconds
|
|
340
452
|
retry: { maxAttempts: 3 }
|
|
341
453
|
});
|
|
454
|
+
```
|
|
342
455
|
|
|
456
|
+
#### Abort Signals
|
|
457
|
+
```ts
|
|
343
458
|
// Combined abort signals
|
|
344
|
-
const
|
|
345
|
-
const controller2 = new AbortController();
|
|
459
|
+
const controller = new AbortController();
|
|
346
460
|
const request = new Request("https://api.example.com/data", {
|
|
347
|
-
signal:
|
|
461
|
+
signal: controller.signal
|
|
348
462
|
});
|
|
349
463
|
|
|
350
|
-
setTimeout(() =>
|
|
464
|
+
setTimeout(() => controller.abort(), 5000);
|
|
351
465
|
|
|
352
466
|
const response = await fetchy(request, {
|
|
353
|
-
signal:
|
|
467
|
+
signal: AbortSignal.timeout(10000)
|
|
354
468
|
});
|
|
469
|
+
```
|
|
355
470
|
|
|
471
|
+
#### Form Data
|
|
472
|
+
```ts
|
|
356
473
|
// Form data upload
|
|
357
474
|
const formData = new FormData();
|
|
358
475
|
formData.append("file", blob);
|
|
359
476
|
formData.append("name", "example");
|
|
360
477
|
|
|
361
|
-
|
|
478
|
+
await fetchy("https://api.example.com/upload", {
|
|
362
479
|
body: formData
|
|
363
480
|
});
|
|
364
481
|
|
|
365
482
|
// URL-encoded form
|
|
366
|
-
const params = new URLSearchParams();
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
const response = await fetchy("https://api.example.com/form", {
|
|
483
|
+
const params = new URLSearchParams({ key: "value" });
|
|
484
|
+
await fetchy("https://api.example.com/form", {
|
|
370
485
|
body: params
|
|
371
486
|
});
|
|
372
487
|
```
|
|
373
488
|
|
|
489
|
+
#### Testing Utilities
|
|
490
|
+
|
|
491
|
+
When writing tests for code that uses `fetchy`, you may need to simulate immediate failures without triggering retry logic. Use the `NO_RETRY_ERROR` constant to bypass all retry attempts:
|
|
492
|
+
```ts
|
|
493
|
+
import { fetchy, NO_RETRY_ERROR } from "@scirexs/fetchy";
|
|
494
|
+
|
|
495
|
+
const originalFetch = globalThis.fetch;
|
|
496
|
+
globalThis.fetch = () => Promise.reject(new Error(NO_RETRY_ERROR));
|
|
497
|
+
|
|
498
|
+
try {
|
|
499
|
+
await fetchy("https://api.example.com/data");
|
|
500
|
+
} catch (error) {
|
|
501
|
+
// Error is thrown immediately without retries
|
|
502
|
+
console.error(error);
|
|
503
|
+
} finally {
|
|
504
|
+
globalThis.fetch = originalFetch;
|
|
505
|
+
}
|
|
506
|
+
```
|
|
507
|
+
|
|
374
508
|
### Type-Safe API Responses
|
|
375
509
|
|
|
376
510
|
```ts
|
|
@@ -386,8 +520,9 @@ interface Todo {
|
|
|
386
520
|
completed: boolean;
|
|
387
521
|
}
|
|
388
522
|
|
|
389
|
-
const response = await
|
|
523
|
+
const response = await fetchy<ApiResponse<Todo>>(
|
|
390
524
|
"https://api.example.com/todos/1",
|
|
525
|
+
{},
|
|
391
526
|
"json"
|
|
392
527
|
);
|
|
393
528
|
|
|
@@ -398,34 +533,29 @@ if (response.success) {
|
|
|
398
533
|
|
|
399
534
|
## Limitations
|
|
400
535
|
|
|
401
|
-
###
|
|
536
|
+
### Content-Type Header with Request Objects
|
|
402
537
|
|
|
403
|
-
When
|
|
538
|
+
When a body is set in a Request object, the Content-Type header is NOT set automatically by this package. Use the `url` property in `FetchyOptions` instead to benefit from automatic header configuration:
|
|
404
539
|
|
|
405
540
|
```ts
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
541
|
+
// Instead of this:
|
|
542
|
+
const request = new Request("https://api.example.com", { body: jsonData });
|
|
543
|
+
await fetchy(request);
|
|
544
|
+
|
|
545
|
+
// Do this:
|
|
546
|
+
await fetchy(null, {
|
|
547
|
+
url: "https://api.example.com",
|
|
548
|
+
body: jsonData
|
|
549
|
+
});
|
|
414
550
|
```
|
|
415
551
|
|
|
416
|
-
### Content-Type Header with Request Objects
|
|
417
|
-
|
|
418
|
-
When a body is set in a Request object, the Content-Type header is NOT set automatically by this package. Therefore, when using Request objects, you must explicitly set the Content-Type header for any body types other than those automatically handled by the native `fetch` API.
|
|
419
|
-
|
|
420
|
-
This limitation can be avoided by using the `url` property in `FetchyOptions` instead of Request objects. This approach allows you to benefit from all automatic header configuration features while still maintaining reusable preset configurations. See the "Reuse options as preset configuration" example in the [Basic Requests](#basic-requests) section.
|
|
421
|
-
|
|
422
552
|
### ReadableStream as Body
|
|
423
553
|
|
|
424
554
|
`FetchyOptions` does not accept ReadableStream as a body. If you need to use ReadableStream, create a Request object with the stream and pass it to `fetchy()`.
|
|
425
555
|
|
|
426
556
|
### Redirect Error Handling
|
|
427
557
|
|
|
428
|
-
When `redirect` is set to `"error"`, this package throws a custom `RedirectError` (instead of
|
|
558
|
+
When `redirect` is set to `"error"`, this package throws a custom `RedirectError` (instead of native TypeError) to enable proper retry handling for redirect responses.
|
|
429
559
|
|
|
430
560
|
## License
|
|
431
561
|
|
package/esm/main.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export{
|
|
1
|
+
export{v as Fetchy,i as fetchy,h as HTTPStatusError,l as NO_RETRY_ERROR,b as RedirectError,s as sfetchy};const l="$$_NO_RETRY_$$",u={timeout:15,delay:0,interval:3,maxInterval:30,maxAttempts:3,retryAfter:!0,native:!1,redirect:"follow"};class h extends Error{static#t=80;status;body;constructor(t,r,n){super(t),this.name="HTTPStatusError",this.status=r,this.body=n}static async fromResponse(t){const r=await t.text(),n=r.length>this.#t?`${r.slice(0,this.#t)}... (more ${r.length-this.#t} chars)`:r||"(no response body)",a=`${t.status} ${t.statusText}: ${n}`;return new this(a,t.status,r)}}class b extends Error{status;constructor(t,r){super(t),this.name="RedirectError",this.status=r}static fromResponse(t){const r=`${t.status} ${t.statusText}`.trim();return new this(r,t.status)}}class v{url;body;timeout;retry;bearer;delay;native;constructor(t){Object.assign(this,t)}async fetch(t){return await i(t??null,this)}async text(t){return await i(t??null,this,"text")}async json(t){return await i(t??null,this,"json")}async bytes(t){return await i(t??null,this,"bytes")}async blob(t){return await i(t??null,this,"blob")}async buffer(t){return await i(t??null,this,"buffer")}async safe(t){return await s(t??null,this)}async stext(t){return await i(t??null,this,"text")}async sjson(t){return await i(t??null,this,"json")}async sbytes(t){return await i(t??null,this,"bytes")}async sblob(t){return await i(t??null,this,"blob")}async sbuffer(t){return await i(t??null,this,"buffer")}static async fetch(t,r){return await i(t,r)}static async text(t,r){return await i(t,r,"text")}static async json(t,r){return await i(t,r,"json")}static async bytes(t,r){return await i(t,r,"bytes")}static async blob(t,r){return await i(t,r,"blob")}static async buffer(t,r){return await i(t,r,"buffer")}static async safe(t,r){return await s(t,r)}static async stext(t,r){return await s(t,r,"text")}static async sjson(t,r){return await s(t,r,"json")}static async sbytes(t,r){return await s(t,r,"bytes")}static async sblob(t,r){return await s(t,r,"blob")}static async sbuffer(t,r){return await s(t,r,"buffer")}}async function s(e,t,r){try{return await m(e,t,r)}catch{return null}}async function i(e,t,r){try{return await m(e,t,r)}catch(n){throw n}}async function m(e,t,r){e||(e=t?.url??"");const n=N(t),a=await F(e,O(e,n,t),n);if(!a.ok&&!n.native)throw await h.fromResponse(a);return r?S(a,r):a}function j(e){return typeof e=="string"}function w(e){return typeof e=="number"}function d(e){return typeof e=="boolean"}function T(e){return!!(e&&typeof e=="object"&&Object.getPrototypeOf(e)===Object.prototype)}function y(e,t,r=!1){return t===void 0||t<0?e:r?Math.trunc(t):t}function f(e,t,r){return d(r)?t:r===void 0||r[e]===void 0?u[e]:w(r[e])?y(u[e],r[e],e==="maxAttempts"):r[e]}function N(e){return{timeout:y(u.timeout,e?.timeout),delay:y(u.delay,e?.delay),interval:f("interval",0,e?.retry),maxInterval:f("maxInterval",0,e?.retry),maxAttempts:f("maxAttempts",0,e?.retry),retryAfter:f("retryAfter",!1,e?.retry),native:e?.native??u.native,redirect:e?.redirect??u.redirect}}function O(e,t,r){const{method:n,body:a,timeout:c,retry:J,bearer:L,native:Y,delay:k,redirect:o,signal:G,...A}=r??{};return{headers:$(r),method:n||(e instanceof Request?e.method:a==null?"GET":"POST"),signal:M(e,t.timeout,r?.signal),...o&&{redirect:o=="error"?"manual":o},...a&&{body:E(a)},...A}}function E(e){return x(e)?JSON.stringify(e):e}function x(e){return!!(e===null||w(e)||d(e)||Array.isArray(e)||T(e))}function $(e){const t=new Headers(e?.headers);if(t.has("Accept")||t.set("Accept","application/json, text/plain"),!t.has("Content-Type")){const r=I(e?.body);r&&t.append("Content-Type",r)}return e?.bearer&&t.set("Authorization",`Bearer ${e.bearer}`),t}function I(e){if(!(e==null||j(e)||e instanceof FormData||e instanceof URLSearchParams)&&!(e instanceof Blob&&e.type))return x(e)?"application/json":"application/octet-stream"}function M(e,t,r){const n=[];return e instanceof Request&&e.signal&&n.push(e.signal),r&&n.push(r),t>0&&n.push(AbortSignal.timeout(t*1e3+1)),n.length?AbortSignal.any(n):void 0}async function S(e,t){switch(t){case"json":return await e.json();case"text":return await e.text();case"bytes":return await e.bytes();case"blob":return await e.blob();case"buffer":return await e.arrayBuffer()}}async function _(e,t=!0){if(e<=0)return;const r=Math.trunc((t?Math.random():1)*e*1e3);await new Promise(n=>setTimeout(n,r))}function B(e){return e.status<400&&e.status>=300}function q(e){return e.status<500&&e.status>=400}async function R(e,t,r,n){if(e>=r.maxAttempts-1||t.signal?.aborted)return!0;if(n){if(n.ok||q(n)||r.native)return!0;if(B(n)){if(r.redirect=="manual")return!0;if(r.redirect=="error")throw r.maxAttempts=0,b.fromResponse(n)}}const a=P(e,r,n);return a>r.maxInterval?!0:(await _(a,!1),!1)}function P(e,t,r){return t.retryAfter&&r?.headers.has("Retry-After")?Math.max(D(r.headers.get("Retry-After")?.trim()??""),t.interval):Math.min(Math.pow(Math.max(1,t.interval),e),t.maxInterval)}function D(e){if(!e)return 1/0;const t=Number.parseInt(e,10);if(!Number.isNaN(t))return t;const r=Math.ceil((new Date(e).getTime()-Date.now())/1e3);return Number.isNaN(r)?1/0:r}function C(e,t,r){return r.redirected?(r.status==303&&(t.method="GET"),e instanceof Request?new Request(r.url,e):r.url):e}function H(e,t){return e instanceof Request&&t?e.clone():e}async function F(e,t,r){for(let n=0;n<r.maxAttempts;n++)try{const a=H(e,n<r.maxAttempts-1),c=await g(a,t,r);if(await R(n,t,r,c))return c;e=C(e,t,c);continue}catch(a){if(a instanceof Error&&a.message==l||await R(n,t,r))throw a;continue}return await g(e,t,r)}async function g(e,t,r){return await _(r.delay),await fetch(e,t)}
|
package/esm/mod.js
CHANGED
package/package.json
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scirexs/fetchy",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "A lightweight fetch wrapper.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"fetch",
|
|
7
|
+
"fetch-wrapper",
|
|
8
|
+
"fetch-client",
|
|
9
|
+
"request",
|
|
10
|
+
"http",
|
|
11
|
+
"get",
|
|
12
|
+
"url",
|
|
7
13
|
"typescript"
|
|
8
14
|
],
|
|
9
15
|
"author": "scirexs",
|
package/types/main.d.ts
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
export { _cloneInput, _combineSignal, _correctNumber, _DEFAULT, _fetchWithJitter, _fetchWithRetry, _getBody, _getContentType, _getHeaders, _getNextInterval, _getOptions, _getRequestInit, _getRetryOption, _handleRedirectResponse, _isBool, _isJSONObject, _isNumber, _isPlainObject, _isString, _parseRetryAfter, _shouldNotRetry, _shouldRedirect,
|
|
2
|
-
import type {
|
|
1
|
+
export { _cloneInput, _combineSignal, _correctNumber, _DEFAULT, _fetchWithJitter, _fetchWithRetry, _getBody, _getContentType, _getHeaders, _getNextInterval, _getOptions, _getRequestInit, _getRetryOption, _handleRedirectResponse, _isBool, _isJSONObject, _isNumber, _isPlainObject, _isString, _main, _parseBody, _parseRetryAfter, _shouldCorrectRequest, _shouldNotRetry, _shouldRedirect, _wait, Fetchy, fetchy, HTTPStatusError, NO_RETRY_ERROR, RedirectError, sfetchy, };
|
|
2
|
+
import type { FetchyBody, FetchyOptions, RetryOptions } from "./types.js";
|
|
3
|
+
/** Error message to simulate immediate failures without retry for writing tests. */
|
|
4
|
+
declare const NO_RETRY_ERROR = "$$_NO_RETRY_$$";
|
|
3
5
|
/** Default configuration values for fetchy. */
|
|
4
6
|
declare const _DEFAULT: Options;
|
|
5
7
|
/** Valid input types for fetch requests. */
|
|
6
8
|
type Input = string | URL | Request;
|
|
9
|
+
type FetchyReturn<T> = Response | string | Uint8Array<ArrayBuffer> | Blob | ArrayBuffer | T;
|
|
10
|
+
/** Response body parsing method specification. */
|
|
11
|
+
type ParseMethod = "text" | "json" | "bytes" | "blob" | "buffer";
|
|
7
12
|
/** Internal normalized options used throughout the fetch process. */
|
|
8
13
|
interface Options {
|
|
9
14
|
timeout: number;
|
|
@@ -12,18 +17,9 @@ interface Options {
|
|
|
12
17
|
maxInterval: number;
|
|
13
18
|
maxAttempts: number;
|
|
14
19
|
retryAfter: boolean;
|
|
15
|
-
|
|
16
|
-
onStatus: boolean;
|
|
20
|
+
native: boolean;
|
|
17
21
|
redirect: "follow" | "error" | "manual";
|
|
18
22
|
}
|
|
19
|
-
/** Infer helper type for response type overload. */
|
|
20
|
-
type ThrowError = FetchyOptions & Partial<{
|
|
21
|
-
throwError: true;
|
|
22
|
-
}> | FetchyOptions & Partial<{
|
|
23
|
-
throwError: {
|
|
24
|
-
onError: true;
|
|
25
|
-
};
|
|
26
|
-
}>;
|
|
27
23
|
/**
|
|
28
24
|
* Error thrown when HTTP response has a non-OK status code (4xx, 5xx, ...).
|
|
29
25
|
* Only thrown when throwError.onErrorStatus is set to true.
|
|
@@ -46,7 +42,7 @@ declare class HTTPStatusError extends Error {
|
|
|
46
42
|
status: number;
|
|
47
43
|
body: string;
|
|
48
44
|
constructor(msg: string, status: number, body: string);
|
|
49
|
-
static fromResponse(resp: Response): Promise<
|
|
45
|
+
static fromResponse(resp: Response): Promise<HTTPStatusError>;
|
|
50
46
|
}
|
|
51
47
|
/**
|
|
52
48
|
* Error thrown when a redirect response is received and redirect option is set to "error".
|
|
@@ -67,82 +63,218 @@ declare class HTTPStatusError extends Error {
|
|
|
67
63
|
declare class RedirectError extends Error {
|
|
68
64
|
status: number;
|
|
69
65
|
constructor(msg: string, status: number);
|
|
70
|
-
static fromResponse(resp: Response):
|
|
66
|
+
static fromResponse(resp: Response): RedirectError;
|
|
71
67
|
}
|
|
72
68
|
/**
|
|
73
|
-
*
|
|
74
|
-
*
|
|
69
|
+
* A fluent HTTP client class that provides both instance and static methods for making HTTP requests.
|
|
70
|
+
* Supports features like timeout, retry with exponential backoff, automatic header management, and response parsing.
|
|
75
71
|
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
* @returns Parsed response body or null on failure.
|
|
72
|
+
* This class can be used in two ways:
|
|
73
|
+
* - Instance methods: Create an instance with default options, then call methods with optional URL override
|
|
74
|
+
* - Static methods: Call methods directly with URL and options
|
|
80
75
|
*
|
|
81
76
|
* @example
|
|
82
77
|
* ```ts
|
|
83
|
-
*
|
|
78
|
+
* // Instance usage - reuse configuration
|
|
79
|
+
* const client = new Fetchy({
|
|
80
|
+
* bearer: "token123",
|
|
81
|
+
* timeout: 10,
|
|
82
|
+
* retry: { max: 3 }
|
|
83
|
+
* });
|
|
84
|
+
* const user = await client.json<User>("https://api.example.com/user");
|
|
85
|
+
* const posts = await client.json<Post[]>("https://api.example.com/posts");
|
|
84
86
|
*
|
|
85
|
-
* //
|
|
86
|
-
* const data = await
|
|
87
|
+
* // Static usage - one-off requests
|
|
88
|
+
* const data = await Fetchy.json("https://api.example.com/data");
|
|
89
|
+
* const response = await Fetchy.fetch("https://api.example.com/endpoint", {
|
|
90
|
+
* body: { key: "value" },
|
|
91
|
+
* timeout: 5
|
|
92
|
+
* });
|
|
87
93
|
*
|
|
88
|
-
* //
|
|
94
|
+
* // Safe mode - returns null on error instead of throwing
|
|
95
|
+
* const result = await Fetchy.sjson("https://api.example.com/data");
|
|
96
|
+
* if (result !== null) {
|
|
97
|
+
* // Handle successful response
|
|
98
|
+
* }
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
declare class Fetchy implements FetchyOptions {
|
|
102
|
+
/** Request URL. Used if call fetchy with null. */
|
|
103
|
+
url?: string | URL;
|
|
104
|
+
/** Request body content. Automatically serializes JSON objects. */
|
|
105
|
+
body?: FetchyBody;
|
|
106
|
+
/** Request timeout in seconds. Default is 15 seconds. */
|
|
107
|
+
timeout?: number;
|
|
108
|
+
/** Retry configuration. Set to false to disable retry functionality. */
|
|
109
|
+
retry?: false | RetryOptions;
|
|
110
|
+
/** Bearer token for Authorization header. Automatically adds "Bearer " prefix. */
|
|
111
|
+
bearer?: string;
|
|
112
|
+
/** Initial jitter delay in seconds before sending the request. Adds randomness to prevent thundering herd. */
|
|
113
|
+
delay?: number;
|
|
114
|
+
/** If receive response, does not throw error same with native fetch. */
|
|
115
|
+
native?: true;
|
|
116
|
+
constructor(options?: FetchyOptions);
|
|
117
|
+
/** Call fetchy with instance options. */
|
|
118
|
+
fetch(url?: Input | null): Promise<Response>;
|
|
119
|
+
/** Call fetchy with instance options and parsing as text. */
|
|
120
|
+
text(url?: Input | null): Promise<string>;
|
|
121
|
+
/** Call fetchy with instance options and parsing as json. */
|
|
122
|
+
json<T>(url?: Input | null): Promise<T>;
|
|
123
|
+
/** Call fetchy with instance options and parsing as Uint8Array. */
|
|
124
|
+
bytes(url?: Input | null): Promise<Uint8Array<ArrayBuffer>>;
|
|
125
|
+
/** Call fetchy with instance options and parsing as Blob. */
|
|
126
|
+
blob(url?: Input | null): Promise<Blob>;
|
|
127
|
+
/** Call fetchy with instance options and parsing as ArrayBuffer. */
|
|
128
|
+
buffer(url?: Input | null): Promise<ArrayBuffer>;
|
|
129
|
+
/** Call sfetchy with instance options. */
|
|
130
|
+
safe(url?: Input | null): Promise<Response | null>;
|
|
131
|
+
/** Call sfetchy with instance options and parsing as text. */
|
|
132
|
+
stext(url?: Input | null): Promise<string | null>;
|
|
133
|
+
/** Call sfetchy with instance options and parsing as json. */
|
|
134
|
+
sjson<T>(url?: Input | null): Promise<T | null>;
|
|
135
|
+
/** Call sfetchy with instance options and parsing as Uint8Array. */
|
|
136
|
+
sbytes(url?: Input | null): Promise<Uint8Array<ArrayBuffer> | null>;
|
|
137
|
+
/** Call sfetchy with instance options and parsing as Blob. */
|
|
138
|
+
sblob(url?: Input | null): Promise<Blob | null>;
|
|
139
|
+
/** Call sfetchy with instance options and parsing as ArrayBuffer. */
|
|
140
|
+
sbuffer(url?: Input | null): Promise<ArrayBuffer | null>;
|
|
141
|
+
/** Call fetchy. */
|
|
142
|
+
static fetch(url: Input | null, options?: FetchyOptions): Promise<Response>;
|
|
143
|
+
/** Call fetchy with parsing as text. */
|
|
144
|
+
static text(url: Input | null, options?: FetchyOptions): Promise<string>;
|
|
145
|
+
/** Call fetchy with parsing as json. */
|
|
146
|
+
static json<T>(url: Input | null, options?: FetchyOptions): Promise<T>;
|
|
147
|
+
/** Call fetchy with parsing as Uint8Array. */
|
|
148
|
+
static bytes(url: Input | null, options?: FetchyOptions): Promise<Uint8Array<ArrayBuffer>>;
|
|
149
|
+
/** Call fetchy with parsing as Blob. */
|
|
150
|
+
static blob(url: Input | null, options?: FetchyOptions): Promise<Blob>;
|
|
151
|
+
/** Call fetchy with parsing as ArrayBuffer. */
|
|
152
|
+
static buffer(url: Input | null, options?: FetchyOptions): Promise<ArrayBuffer>;
|
|
153
|
+
/** Call sfetchy. */
|
|
154
|
+
static safe(url: Input | null, options?: FetchyOptions): Promise<Response | null>;
|
|
155
|
+
/** Call sfetchy with parsing as text. */
|
|
156
|
+
static stext(url: Input | null, options?: FetchyOptions): Promise<string | null>;
|
|
157
|
+
/** Call sfetchy with parsing as json. */
|
|
158
|
+
static sjson<T>(url: Input | null, options?: FetchyOptions): Promise<T | null>;
|
|
159
|
+
/** Call sfetchy with parsing as Uint8Array. */
|
|
160
|
+
static sbytes(url: Input | null, options?: FetchyOptions): Promise<Uint8Array<ArrayBuffer> | null>;
|
|
161
|
+
/** Call sfetchy with parsing as Blob. */
|
|
162
|
+
static sblob(url: Input | null, options?: FetchyOptions): Promise<Blob | null>;
|
|
163
|
+
/** Call sfetchy with parsing as ArrayBuffer. */
|
|
164
|
+
static sbuffer(url: Input | null, options?: FetchyOptions): Promise<ArrayBuffer | null>;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Performs an HTTP request with safe error handling that returns null on failure.
|
|
168
|
+
* Automatically parses the response body based on the specified parse method.
|
|
169
|
+
* Unlike `fetchy`, this function never throws errors - it returns null for any failure.
|
|
170
|
+
*
|
|
171
|
+
* This is useful when you want to handle errors gracefully without try-catch blocks,
|
|
172
|
+
* or when a failed request should be treated as "no data" rather than an error condition.
|
|
173
|
+
*
|
|
174
|
+
* @param url - The URL to fetch. Can be a string, URL object, Request object, or null (uses options.url).
|
|
175
|
+
* @param options - Configuration options for the request (timeout, retry, headers, etc.).
|
|
176
|
+
* @param parse - Optional response body parsing method. If omitted, returns Response object.
|
|
177
|
+
* Supported values: "json", "text", "bytes", "blob", "buffer".
|
|
178
|
+
* @returns Parsed response body, Response object, or null if request fails or response is not OK.
|
|
179
|
+
*
|
|
180
|
+
* @example
|
|
181
|
+
* ```ts
|
|
182
|
+
* import { sfetchy } from "@scirexs/fetchy";
|
|
183
|
+
*
|
|
184
|
+
* // Returns null instead of throwing on error
|
|
185
|
+
* const data = await sfetchy("https://api.example.com/user", {}, "json");
|
|
186
|
+
* if (data === null) {
|
|
187
|
+
* console.log("Request failed, using default data");
|
|
188
|
+
* // Handle failure case
|
|
189
|
+
* }
|
|
190
|
+
*
|
|
191
|
+
* // Explicit type assertion with JSON parsing
|
|
89
192
|
* interface User { id: number; name: string; }
|
|
90
|
-
* const user = await
|
|
193
|
+
* const user = await sfetchy<User>("https://api.example.com/user", {}, "json");
|
|
194
|
+
*
|
|
195
|
+
* // Text response - returns null on any error
|
|
196
|
+
* const text = await sfetchy("https://example.com/page", {}, "text");
|
|
91
197
|
*
|
|
92
|
-
* //
|
|
93
|
-
* const
|
|
198
|
+
* // Binary data with safe error handling
|
|
199
|
+
* const bytes = await sfetchy("https://example.com/image.png", {}, "bytes");
|
|
200
|
+
* if (bytes !== null) {
|
|
201
|
+
* // Process binary data
|
|
202
|
+
* }
|
|
94
203
|
*
|
|
95
|
-
* //
|
|
96
|
-
* const
|
|
204
|
+
* // Raw Response object (no parsing)
|
|
205
|
+
* const response = await sfetchy("https://api.example.com/data");
|
|
206
|
+
* if (response !== null && response.ok) {
|
|
207
|
+
* // Handle response
|
|
208
|
+
* }
|
|
97
209
|
* ```
|
|
98
210
|
*/
|
|
99
|
-
declare function
|
|
100
|
-
declare function
|
|
101
|
-
declare function
|
|
102
|
-
declare function
|
|
103
|
-
declare function
|
|
104
|
-
declare function
|
|
105
|
-
declare function fetchyb(url: Input | null, type: "bytes", options?: undefined): Promise<Uint8Array>;
|
|
106
|
-
declare function fetchyb(url: Input | null, type: "bytes", options: FetchyOptions & ThrowError): Promise<Uint8Array>;
|
|
107
|
-
declare function fetchyb(url: Input | null, type: "bytes", options?: FetchyOptions): Promise<Uint8Array | null>;
|
|
108
|
-
declare function fetchyb<T>(url: Input | null, type?: "auto", options?: undefined): Promise<T | string | Uint8Array>;
|
|
109
|
-
declare function fetchyb<T>(url: Input | null, type?: "auto", options?: FetchyOptions & ThrowError): Promise<T | string | Uint8Array>;
|
|
110
|
-
declare function fetchyb<T>(url: Input | null, type?: "auto", options?: FetchyOptions): Promise<T | string | Uint8Array | null>;
|
|
211
|
+
declare function sfetchy(url: Input | null, options?: FetchyOptions, parse?: undefined): Promise<Response | null>;
|
|
212
|
+
declare function sfetchy<T>(url: Input | null, options: FetchyOptions | undefined, parse: "json"): Promise<T | null>;
|
|
213
|
+
declare function sfetchy(url: Input | null, options: FetchyOptions | undefined, parse: "text"): Promise<string | null>;
|
|
214
|
+
declare function sfetchy(url: Input | null, options: FetchyOptions | undefined, parse: "bytes"): Promise<Uint8Array<ArrayBuffer> | null>;
|
|
215
|
+
declare function sfetchy(url: Input | null, options: FetchyOptions | undefined, parse: "blob"): Promise<Blob | null>;
|
|
216
|
+
declare function sfetchy(url: Input | null, options: FetchyOptions | undefined, parse: "buffer"): Promise<ArrayBuffer | null>;
|
|
111
217
|
/**
|
|
112
218
|
* Performs an HTTP request with enhanced features like timeout, retry, and automatic header management.
|
|
113
|
-
*
|
|
219
|
+
* Throws errors on failure unless configured otherwise via the `native` option.
|
|
220
|
+
* Automatically parses the response body based on the specified parse method.
|
|
114
221
|
*
|
|
115
|
-
* @param url - The URL to fetch. Can be a string, URL object, or
|
|
116
|
-
* @param options - Configuration options for the request.
|
|
117
|
-
* @
|
|
222
|
+
* @param url - The URL to fetch. Can be a string, URL object, Request object, or null (uses options.url).
|
|
223
|
+
* @param options - Configuration options for the request (timeout, retry, headers, body, etc.).
|
|
224
|
+
* @param parse - Optional response body parsing method. If omitted, returns Response object.
|
|
225
|
+
* Supported values: "json", "text", "bytes", "blob", "buffer".
|
|
226
|
+
* @returns Parsed response body or Response object.
|
|
227
|
+
* @throws {HTTPStatusError} When response status is not OK (4xx, 5xx) - default behavior.
|
|
228
|
+
* @throws {RedirectError} When redirect is encountered and redirect option is set to "error".
|
|
229
|
+
* @throws {TypeError} When network error occurs (e.g., DNS resolution failure, connection refused).
|
|
230
|
+
* @throws {DOMException} When request is aborted via timeout or AbortSignal.
|
|
118
231
|
*
|
|
119
232
|
* @example
|
|
120
233
|
* ```ts
|
|
121
234
|
* import { fetchy } from "@scirexs/fetchy";
|
|
122
235
|
*
|
|
123
|
-
* // Simple GET request
|
|
236
|
+
* // Simple GET request returning Response object
|
|
124
237
|
* const response = await fetchy("https://api.example.com/data");
|
|
125
|
-
* if (response
|
|
238
|
+
* if (response.ok) {
|
|
126
239
|
* const data = await response.json();
|
|
127
240
|
* }
|
|
128
241
|
*
|
|
129
|
-
* //
|
|
130
|
-
*
|
|
242
|
+
* // Direct JSON parsing with type assertion
|
|
243
|
+
* interface User { id: number; name: string; }
|
|
244
|
+
* const user = await fetchy<User>("https://api.example.com/user", {}, "json");
|
|
245
|
+
*
|
|
246
|
+
* // POST request with JSON body and authentication
|
|
247
|
+
* const result = await fetchy("https://api.example.com/create", {
|
|
131
248
|
* body: { name: "John", age: 30 },
|
|
132
|
-
*
|
|
133
|
-
* });
|
|
249
|
+
* bearer: "your-token-here"
|
|
250
|
+
* }, "json");
|
|
134
251
|
*
|
|
135
|
-
* // With retry and
|
|
252
|
+
* // With retry, timeout, and error handling
|
|
253
|
+
* try {
|
|
254
|
+
* const data = await fetchy("https://api.example.com/data", {
|
|
255
|
+
* timeout: 10,
|
|
256
|
+
* retry: { max: 5, interval: 2, maxInterval: 30 }
|
|
257
|
+
* }, "json");
|
|
258
|
+
* } catch (error) {
|
|
259
|
+
* if (error instanceof HTTPStatusError) {
|
|
260
|
+
* console.error(`HTTP ${error.status}: ${error.body}`);
|
|
261
|
+
* }
|
|
262
|
+
* }
|
|
263
|
+
*
|
|
264
|
+
* // Native error mode - throws native fetch errors without HTTPStatusError
|
|
136
265
|
* const response = await fetchy("https://api.example.com/data", {
|
|
137
|
-
*
|
|
138
|
-
* retry: { max: 5, interval: 2 },
|
|
139
|
-
* throwError: { onErrorStatus: true }
|
|
266
|
+
* native: true
|
|
140
267
|
* });
|
|
141
268
|
* ```
|
|
142
269
|
*/
|
|
143
|
-
declare function fetchy(url: Input | null, options?: undefined): Promise<Response>;
|
|
144
|
-
declare function fetchy(url: Input | null, options: FetchyOptions
|
|
145
|
-
declare function fetchy(url: Input | null, options
|
|
270
|
+
declare function fetchy(url: Input | null, options?: FetchyOptions, parse?: undefined): Promise<Response>;
|
|
271
|
+
declare function fetchy<T>(url: Input | null, options: FetchyOptions | undefined, parse: "json"): Promise<T>;
|
|
272
|
+
declare function fetchy(url: Input | null, options: FetchyOptions | undefined, parse: "text"): Promise<string>;
|
|
273
|
+
declare function fetchy(url: Input | null, options: FetchyOptions | undefined, parse: "bytes"): Promise<Uint8Array<ArrayBuffer>>;
|
|
274
|
+
declare function fetchy(url: Input | null, options: FetchyOptions | undefined, parse: "blob"): Promise<Blob>;
|
|
275
|
+
declare function fetchy(url: Input | null, options: FetchyOptions | undefined, parse: "buffer"): Promise<ArrayBuffer>;
|
|
276
|
+
/** Main procedure of fetchy and sfetchy. */
|
|
277
|
+
declare function _main<T>(url: Input | null, options?: FetchyOptions, parse?: ParseMethod): Promise<FetchyReturn<T>>;
|
|
146
278
|
/** Checks if a value is a string. */
|
|
147
279
|
declare function _isString(v: unknown): v is string;
|
|
148
280
|
/** Checks if a value is a number. */
|
|
@@ -151,8 +283,6 @@ declare function _isNumber(v: unknown): v is number;
|
|
|
151
283
|
declare function _isBool(v: unknown): v is boolean;
|
|
152
284
|
/** Checks if a value is a plain object (not array, null, or other object types). */
|
|
153
285
|
declare function _isPlainObject(v: unknown): v is object;
|
|
154
|
-
/** Determines whether to throw an error based on configuration. */
|
|
155
|
-
declare function _throwError(prop: keyof ErrorOptions, options?: ErrorOptions | boolean): boolean;
|
|
156
286
|
/** Corrects a number to be non-negative, using default if invalid. */
|
|
157
287
|
declare function _correctNumber(dflt: number, num?: number, integer?: boolean): number;
|
|
158
288
|
/** Gets retry option value from configuration with fallback to default. */
|
|
@@ -172,10 +302,14 @@ declare function _getHeaders(options?: FetchyOptions): Headers;
|
|
|
172
302
|
declare function _getContentType(body?: FetchyBody): string | undefined;
|
|
173
303
|
/** Combine abort signals. */
|
|
174
304
|
declare function _combineSignal(url: Input, timeout: number, signal?: AbortSignal | null): AbortSignal | undefined;
|
|
305
|
+
/** Parse response body. */
|
|
306
|
+
declare function _parseBody<T>(resp: Response, method: ParseMethod): Promise<Exclude<FetchyReturn<T>, Response>>;
|
|
175
307
|
/** Waits for specified seconds with optional randomization. */
|
|
176
308
|
declare function _wait(sec: number, random?: boolean): Promise<void>;
|
|
177
309
|
/** Checks if response is a redirect (3xx status). */
|
|
178
310
|
declare function _shouldRedirect(resp: Response): boolean;
|
|
311
|
+
/** Checks if response is a client error (4xx status). */
|
|
312
|
+
declare function _shouldCorrectRequest(resp: Response): boolean;
|
|
179
313
|
/** Determines if retry should stop based on conditions and waits if continuing. */
|
|
180
314
|
declare function _shouldNotRetry(count: number, init: RequestInit, opts: Options, resp?: Response): Promise<boolean>;
|
|
181
315
|
/** Calculates next retry interval using exponential backoff or Retry-After header. */
|
package/types/main.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,cAAc,EACd,cAAc,EACd,QAAQ,EACR,gBAAgB,EAChB,eAAe,EACf,QAAQ,EACR,eAAe,EACf,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,eAAe,EACf,eAAe,EACf,uBAAuB,EACvB,OAAO,EACP,aAAa,EACb,SAAS,EACT,cAAc,EACd,SAAS,EACT,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"}
|
package/types/mod.d.ts
CHANGED
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
* Exports main functions and types for external.
|
|
3
3
|
* @module
|
|
4
4
|
*/
|
|
5
|
-
export {
|
|
6
|
-
export type {
|
|
5
|
+
export { Fetchy, fetchy, HTTPStatusError, NO_RETRY_ERROR, RedirectError, sfetchy } from "./main.js";
|
|
6
|
+
export type { FetchyBody, FetchyOptions, JSONValue, RetryOptions } from "./types.js";
|
|
7
7
|
//# sourceMappingURL=mod.d.ts.map
|
package/types/mod.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,cAAc,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpG,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC"}
|
package/types/types.d.ts
CHANGED
|
@@ -38,10 +38,10 @@ export interface FetchyOptions extends Omit<RequestInit, "body"> {
|
|
|
38
38
|
retry?: RetryOptions | false;
|
|
39
39
|
/** Bearer token for Authorization header. Automatically adds "Bearer " prefix. */
|
|
40
40
|
bearer?: string;
|
|
41
|
-
/** Error throwing behavior configuration. Set to true to throw all errors. */
|
|
42
|
-
onError?: ErrorOptions | boolean;
|
|
43
41
|
/** Initial jitter delay in seconds before sending the request. Adds randomness to prevent thundering herd. */
|
|
44
42
|
delay?: number;
|
|
43
|
+
/** If receive response, does not throw error same with native fetch. */
|
|
44
|
+
native?: true;
|
|
45
45
|
}
|
|
46
46
|
/**
|
|
47
47
|
* Configuration options for retry behavior.
|
|
@@ -67,14 +67,4 @@ export interface RetryOptions {
|
|
|
67
67
|
/** Whether to respect Retry-After header from response. Default is true. */
|
|
68
68
|
retryAfter?: boolean;
|
|
69
69
|
}
|
|
70
|
-
/**
|
|
71
|
-
* Configuration options for error throwing behavior.
|
|
72
|
-
* Allows fine-grained control over which errors should be thrown vs. returned as null.
|
|
73
|
-
*/
|
|
74
|
-
export interface ErrorOptions {
|
|
75
|
-
/** Whether to throw native errors (network errors, parsing errors, etc.). If false, returns null instead. Default is true. */
|
|
76
|
-
onNative?: boolean;
|
|
77
|
-
/** Whether to throw HTTPStatusError for non-OK status codes (4xx, 5xx, ...). Default is false. */
|
|
78
|
-
onStatus?: boolean;
|
|
79
|
-
}
|
|
80
70
|
//# sourceMappingURL=types.d.ts.map
|
package/types/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,EAAE,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAEtG;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,OAAO,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;AAEvE;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,aAAc,SAAQ,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC;IAC9D,kDAAkD;IAClD,GAAG,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC;IACnB,mEAAmE;IACnE,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,yDAAyD;IACzD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,KAAK,CAAC,EAAE,YAAY,GAAG,KAAK,CAAC;IAC7B,kFAAkF;IAClF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,EAAE,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAEtG;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,OAAO,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;AAEvE;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,aAAc,SAAQ,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC;IAC9D,kDAAkD;IAClD,GAAG,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC;IACnB,mEAAmE;IACnE,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,yDAAyD;IACzD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,KAAK,CAAC,EAAE,YAAY,GAAG,KAAK,CAAC;IAC7B,kFAAkF;IAClF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8GAA8G;IAC9G,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,MAAM,CAAC,EAAE,IAAI,CAAC;CACf;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,YAAY;IAC3B,gHAAgH;IAChH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wGAAwG;IACxG,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sDAAsD;IACtD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB"}
|