create-request 0.0.1-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +575 -0
- package/dist/library/BaseRequest.d.ts +119 -0
- package/dist/library/BodyRequest.d.ts +8 -0
- package/dist/library/RequestError.d.ts +18 -0
- package/dist/library/ResponseWrapper.d.ts +54 -0
- package/dist/library/enums.d.ts +56 -0
- package/dist/library/index.d.ts +16 -0
- package/dist/library/index.esm.js +616 -0
- package/dist/library/index.js +635 -0
- package/dist/library/requestFactories.d.ts +30 -0
- package/dist/library/requestMethods.d.ts +24 -0
- package/dist/library/types.d.ts +19 -0
- package/package.json +56 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Daniel Amenou
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,575 @@
|
|
|
1
|
+
# create-request
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/create-request)
|
|
4
|
+
[](https://github.com/yourusername/create-request/blob/main/LICENSE)
|
|
5
|
+
[](https://bundlephobia.com/package/create-request)
|
|
6
|
+
|
|
7
|
+
`create-request` is a modern TypeScript library that transforms how you make API calls. Built as an elegant wrapper around the native Fetch API, it provides a chainable, fluent interface that dramatically reduces boilerplate while adding powerful features like automatic retries, timeout handling, and comprehensive error management.
|
|
8
|
+
|
|
9
|
+
With first-class TypeScript support, built-in response parsing, and intuitive authentication helpers, `create-request` makes your API code more readable, more reliable, and fully type-safeβall with zero dependencies and a tiny footprint.
|
|
10
|
+
|
|
11
|
+
## Why create-request?
|
|
12
|
+
|
|
13
|
+
**You've probably been here before:** writing boilerplate fetch code, handling retries manually, struggling with timeouts, or wrestling with TypeScript types for your API responses. `create-request` solves all of that with an elegant, chainable API:
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
// Instead of verbose fetch code with manual JSON parsing, error handling, etc.
|
|
17
|
+
// You get a clean, intuitive API that just works
|
|
18
|
+
const users = await create.get()
|
|
19
|
+
.withTimeout(5000)
|
|
20
|
+
.withRetries(3)
|
|
21
|
+
.withBearerToken('your-token')
|
|
22
|
+
.sendTo('https://api.example.com/users')
|
|
23
|
+
.json<User[]>(); // Fully typed response!
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## π Designed for Developer Happiness
|
|
27
|
+
|
|
28
|
+
- **Write Less Code** - Accomplish in one line what might take dozens with raw fetch
|
|
29
|
+
- **Fewer Bugs** - Strong typing and smart defaults prevent common API bugs
|
|
30
|
+
- **Self-Documenting** - Chainable API clearly expresses intent for easier code reviews
|
|
31
|
+
- **Universal** - Works the same in browser and Node.js environments
|
|
32
|
+
|
|
33
|
+
## Overview
|
|
34
|
+
|
|
35
|
+
`create-request` provides a chainable, fluent API for making HTTP requests with built-in solutions for the most common API challenges. It's designed for developers who value clean code, type safety, and robust error handling.
|
|
36
|
+
|
|
37
|
+
## Features
|
|
38
|
+
|
|
39
|
+
- π **Fully Typed** - Complete TypeScript support with accurate type definitions
|
|
40
|
+
- π **Chainable API** - Fluent interface for building requests
|
|
41
|
+
- β±οΈ **Timeout Support** - Set timeouts for any request (no more hanging requests!)
|
|
42
|
+
- π **Automatic Retries** - Smart retry mechanism with customizable strategies
|
|
43
|
+
- π **Auth Helpers** - One-liner methods for common auth patterns
|
|
44
|
+
- π§© **Query Parameter Management** - Easy query parameter handling with arrays support
|
|
45
|
+
- π¦ **Response Transformations** - Parse responses as JSON, text, blob, etc.
|
|
46
|
+
- π« **Robust Error Handling** - Detailed error information with custom error class
|
|
47
|
+
- π **Zero Dependencies** - Built on the native Fetch API with no external baggage
|
|
48
|
+
- π **Universal** - Works exactly the same in all modern browsers and Node.js
|
|
49
|
+
- π§ **Smart Content-Type** - Automatic content type detection for request bodies
|
|
50
|
+
- π·οΈ **Type Safety** - Enums for all string constants to prevent typos
|
|
51
|
+
|
|
52
|
+
## Installation
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npm install create-request
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Or with yarn:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
yarn add create-request
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## See the Difference: How create-request Transforms API Calls
|
|
65
|
+
|
|
66
|
+
### 1. Simplified Error Handling
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
create.get()
|
|
70
|
+
.sendTo('https://api.example.com/data')
|
|
71
|
+
.json()
|
|
72
|
+
.then(data => {
|
|
73
|
+
// Process successful response
|
|
74
|
+
console.log(data);
|
|
75
|
+
})
|
|
76
|
+
.catch(error => {
|
|
77
|
+
if (error instanceof RequestError) {
|
|
78
|
+
// Rich error details that fetch doesn't provide:
|
|
79
|
+
console.log(`${error.status} error from ${error.method} ${error.url}`);
|
|
80
|
+
console.log(`Was it a timeout? ${error.timeoutError}`);
|
|
81
|
+
|
|
82
|
+
// Original error data still available:
|
|
83
|
+
console.log(error.response);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### 2. Type-Safe API Responses
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
interface User {
|
|
92
|
+
id: number;
|
|
93
|
+
name: string;
|
|
94
|
+
email: string;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// TypeScript knows exactly what you're getting back!
|
|
98
|
+
const users = await create.get()
|
|
99
|
+
.sendTo('https://api.example.com/users')
|
|
100
|
+
.json<User[]>();
|
|
101
|
+
|
|
102
|
+
// No more type casting or guessing - your IDE autocomplete works perfectly
|
|
103
|
+
users.forEach(user => console.log(user.name));
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### 3. Request Retries Made Simple
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
// Without create-request: Pages of manual retry logic with delay calculations
|
|
110
|
+
// With create-request: One line
|
|
111
|
+
|
|
112
|
+
const data = await create.get()
|
|
113
|
+
.withRetries(3)
|
|
114
|
+
.onRetry(({ retryCount, error }) => {
|
|
115
|
+
console.log(`Retry ${retryCount} after ${error.message}`);
|
|
116
|
+
})
|
|
117
|
+
.sendTo('https://api.example.com/flaky-endpoint')
|
|
118
|
+
.json();
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Basic Usage
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
import create from 'create-request';
|
|
125
|
+
|
|
126
|
+
// Simple GET request with chained response parsing
|
|
127
|
+
const users = await create.get()
|
|
128
|
+
.withTimeout(5000)
|
|
129
|
+
.sendTo('https://api.example.com/users')
|
|
130
|
+
.json(); // Parse response directly
|
|
131
|
+
|
|
132
|
+
// POST request with JSON body
|
|
133
|
+
const newUser = await create.post()
|
|
134
|
+
.withBody({ name: 'Daniel Amenou', email: 'daniel@example.com' })
|
|
135
|
+
.withBearerToken('your-token-here')
|
|
136
|
+
.sendTo('https://api.example.com/users')
|
|
137
|
+
.json();
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## API Reference
|
|
141
|
+
|
|
142
|
+
### Request Creation
|
|
143
|
+
|
|
144
|
+
Create requests using the appropriate factory method:
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
// Methods without body
|
|
148
|
+
create.get()
|
|
149
|
+
create.del()
|
|
150
|
+
create.head()
|
|
151
|
+
create.options()
|
|
152
|
+
|
|
153
|
+
// Methods with body
|
|
154
|
+
create.put()
|
|
155
|
+
create.post()
|
|
156
|
+
create.patch()
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Request Configuration
|
|
160
|
+
|
|
161
|
+
All requests support these configuration methods:
|
|
162
|
+
|
|
163
|
+
#### Common Settings
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
import { RequestPriority, CredentialsPolicy, RequestMode, RedirectMode } from 'create-request';
|
|
167
|
+
|
|
168
|
+
// Set request headers
|
|
169
|
+
.withHeaders({ 'X-API-Key': 'abc123' })
|
|
170
|
+
|
|
171
|
+
// Set cookies
|
|
172
|
+
.withCookies({
|
|
173
|
+
sessionId: 'abc123',
|
|
174
|
+
preference: 'darkMode',
|
|
175
|
+
region: 'us-east'
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
// Set a single content type header
|
|
179
|
+
.withContentType('application/json')
|
|
180
|
+
|
|
181
|
+
// Set request timeout in milliseconds
|
|
182
|
+
.withTimeout(5000)
|
|
183
|
+
|
|
184
|
+
// Configure retry behavior
|
|
185
|
+
.withRetries(3)
|
|
186
|
+
.onRetry(({ retryCount, error }) => {
|
|
187
|
+
console.log(`Retry ${retryCount} after error: ${error.message}`);
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
// Use an external abort controller
|
|
191
|
+
.withAbortController(myAbortController)
|
|
192
|
+
|
|
193
|
+
// Set credentials policy - uses same-origin by default
|
|
194
|
+
.withCredentials(CredentialsPolicy.INCLUDE)
|
|
195
|
+
|
|
196
|
+
// Set redirect behavior
|
|
197
|
+
.withRedirect(RedirectMode.FOLLOW)
|
|
198
|
+
|
|
199
|
+
// Set request mode
|
|
200
|
+
.withMode(RequestMode.CORS)
|
|
201
|
+
|
|
202
|
+
// Set referrer
|
|
203
|
+
.withReferrer('https://example.com')
|
|
204
|
+
|
|
205
|
+
// Set keepalive flag (allows request to outlive the page)
|
|
206
|
+
.withKeepAlive(true)
|
|
207
|
+
|
|
208
|
+
// Set request priority
|
|
209
|
+
.withPriority(RequestPriority.HIGH)
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
#### Query Parameters
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
// Add multiple query parameters
|
|
216
|
+
.withQueryParams({
|
|
217
|
+
search: 'keyword',
|
|
218
|
+
page: 1,
|
|
219
|
+
filters: ['active', 'verified']
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
// Add a single query parameter
|
|
223
|
+
.withQueryParam('sort', 'desc')
|
|
224
|
+
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
#### Authentication
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
// Basic authentication
|
|
231
|
+
.withBasicAuth('username', 'password')
|
|
232
|
+
|
|
233
|
+
// Bearer token
|
|
234
|
+
.withBearerToken('your-jwt-token')
|
|
235
|
+
|
|
236
|
+
// Custom authorization header
|
|
237
|
+
.withAuthorization('Custom scheme-and-token')
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Requests with Body
|
|
241
|
+
|
|
242
|
+
For POST, PUT, and PATCH requests, you can set a body:
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
// JSON body (automatically sets Content-Type: application/json)
|
|
246
|
+
.withBody({ name: 'John', age: 30 })
|
|
247
|
+
|
|
248
|
+
// String body
|
|
249
|
+
.withBody('Plain text content')
|
|
250
|
+
|
|
251
|
+
// FormData
|
|
252
|
+
const form = new FormData();
|
|
253
|
+
form.append('file', fileBlob);
|
|
254
|
+
.withBody(form)
|
|
255
|
+
|
|
256
|
+
// Blob body
|
|
257
|
+
const blob = new Blob(['Hello, world!'], { type: 'text/plain' });
|
|
258
|
+
const request = create.post()
|
|
259
|
+
.withBody(blob)
|
|
260
|
+
.sendTo('https://api.example.com/upload');
|
|
261
|
+
|
|
262
|
+
// ArrayBuffer body
|
|
263
|
+
const buffer = new ArrayBuffer(8);
|
|
264
|
+
const request = create.post()
|
|
265
|
+
.withBody(buffer)
|
|
266
|
+
.sendTo('https://api.example.com/upload');
|
|
267
|
+
|
|
268
|
+
// ReadableStream body
|
|
269
|
+
const stream = new ReadableStream();
|
|
270
|
+
const request = create.post()
|
|
271
|
+
.withBody(stream)
|
|
272
|
+
.sendTo('https://api.example.com/upload');
|
|
273
|
+
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### Response Handling
|
|
277
|
+
|
|
278
|
+
The library provides convenient methods for handling responses that can be chained directly after `sendTo()`:
|
|
279
|
+
|
|
280
|
+
```typescript
|
|
281
|
+
// Parse as JSON with type inference
|
|
282
|
+
const jsonData = await create.get()
|
|
283
|
+
.sendTo('https://api.example.com/data')
|
|
284
|
+
.json<MyDataType>();
|
|
285
|
+
|
|
286
|
+
// Get as text
|
|
287
|
+
const text = await create.get()
|
|
288
|
+
.sendTo('https://api.example.com/text')
|
|
289
|
+
.text();
|
|
290
|
+
|
|
291
|
+
// Get as blob
|
|
292
|
+
const blob = await create.get()
|
|
293
|
+
.sendTo('https://api.example.com/file')
|
|
294
|
+
.blob();
|
|
295
|
+
|
|
296
|
+
// Get as ArrayBuffer
|
|
297
|
+
const buffer = await create.get()
|
|
298
|
+
.sendTo('https://api.example.com/binary')
|
|
299
|
+
.arrayBuffer();
|
|
300
|
+
|
|
301
|
+
// Get as ReadableStream
|
|
302
|
+
const stream = await create.get()
|
|
303
|
+
.sendTo('https://api.example.com/stream')
|
|
304
|
+
.body();
|
|
305
|
+
|
|
306
|
+
// For more control, you can access the raw response first
|
|
307
|
+
const response = await create.get().sendTo('https://api.example.com/data');
|
|
308
|
+
const status = response.status;
|
|
309
|
+
const headers = response.headers;
|
|
310
|
+
const data = await response.json();
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### Error Handling
|
|
314
|
+
|
|
315
|
+
The library provides a `RequestError` class with details about failed requests:
|
|
316
|
+
|
|
317
|
+
```typescript
|
|
318
|
+
try {
|
|
319
|
+
const data = await create.get()
|
|
320
|
+
.sendTo('https://api.example.com/data')
|
|
321
|
+
.json();
|
|
322
|
+
} catch (error) {
|
|
323
|
+
if (error instanceof RequestError) {
|
|
324
|
+
console.log(error.message); // Error message
|
|
325
|
+
console.log(error.status); // HTTP status code (if available)
|
|
326
|
+
console.log(error.url); // Request URL
|
|
327
|
+
console.log(error.method); // HTTP method
|
|
328
|
+
console.log(error.timeoutError); // Whether it was a timeout
|
|
329
|
+
console.log(error.response); // Raw response (if available)
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
## Advanced Usage
|
|
335
|
+
|
|
336
|
+
### Handling File Downloads
|
|
337
|
+
|
|
338
|
+
```typescript
|
|
339
|
+
const blob = await create.get()
|
|
340
|
+
.withHeaders({ Accept: 'application/pdf' })
|
|
341
|
+
.sendTo('https://api.example.com/reports/123/download')
|
|
342
|
+
.blob();
|
|
343
|
+
|
|
344
|
+
const url = window.URL.createObjectURL(blob);
|
|
345
|
+
|
|
346
|
+
// Create a download link
|
|
347
|
+
const a = document.createElement('a');
|
|
348
|
+
a.href = url;
|
|
349
|
+
a.download = 'report.pdf';
|
|
350
|
+
a.click();
|
|
351
|
+
|
|
352
|
+
// Clean up
|
|
353
|
+
window.URL.revokeObjectURL(url);
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### Working with AbortController
|
|
357
|
+
|
|
358
|
+
```typescript
|
|
359
|
+
const controller = new AbortController();
|
|
360
|
+
|
|
361
|
+
// Pass the controller to the request
|
|
362
|
+
try {
|
|
363
|
+
const data = await create.get()
|
|
364
|
+
.withAbortController(controller)
|
|
365
|
+
.sendTo('https://api.example.com/data')
|
|
366
|
+
.json();
|
|
367
|
+
} catch (error) {
|
|
368
|
+
// Handle the aborted request
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// Cancel the request after 2 seconds
|
|
372
|
+
setTimeout(() => controller.abort(), 2000);
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
### Request Priority
|
|
376
|
+
|
|
377
|
+
```typescript
|
|
378
|
+
import { RequestPriority } from 'create-request';
|
|
379
|
+
|
|
380
|
+
// High priority for critical resources
|
|
381
|
+
const userProfile = await create.get()
|
|
382
|
+
.withPriority(RequestPriority.HIGH)
|
|
383
|
+
.sendTo('https://api.example.com/user/profile')
|
|
384
|
+
.json();
|
|
385
|
+
|
|
386
|
+
// Low priority for non-critical resources
|
|
387
|
+
const recommendations = await create.get()
|
|
388
|
+
.withPriority(RequestPriority.LOW)
|
|
389
|
+
.sendTo('https://api.example.com/recommendations')
|
|
390
|
+
.json();
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### Creating Reusable Request Configurations
|
|
394
|
+
|
|
395
|
+
```typescript
|
|
396
|
+
import { RequestPriority, CredentialsPolicy } from 'create-request';
|
|
397
|
+
|
|
398
|
+
function createAuthenticatedRequest(token) {
|
|
399
|
+
return create.get()
|
|
400
|
+
.withBearerToken(token)
|
|
401
|
+
.withHeaders({
|
|
402
|
+
'X-App-Version': '1.0.0',
|
|
403
|
+
})
|
|
404
|
+
.withTimeout(10000)
|
|
405
|
+
.withRetries(2)
|
|
406
|
+
.withCredentials(CredentialsPolicy.INCLUDE)
|
|
407
|
+
.withPriority(RequestPriority.HIGH);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// Later use the configured request
|
|
411
|
+
const users = await createAuthenticatedRequest(myToken)
|
|
412
|
+
.sendTo('https://api.example.com/users')
|
|
413
|
+
.json();
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
### Cookie Management
|
|
417
|
+
|
|
418
|
+
```typescript
|
|
419
|
+
// Set multiple cookies in a single request
|
|
420
|
+
const response = await create.get()
|
|
421
|
+
.withCookies({
|
|
422
|
+
sessionId: 'abc123',
|
|
423
|
+
theme: 'dark',
|
|
424
|
+
region: 'us-east',
|
|
425
|
+
'analytics-opt-in': 'true'
|
|
426
|
+
})
|
|
427
|
+
.sendTo('https://api.example.com/dashboard');
|
|
428
|
+
|
|
429
|
+
// Combine with other header settings
|
|
430
|
+
const response = await create.get()
|
|
431
|
+
.withCookies({ sessionId: 'abc123' })
|
|
432
|
+
.withBearerToken('your-token-here')
|
|
433
|
+
.sendTo('https://api.example.com/protected-resource');
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
## Environment-Specific Limitations
|
|
437
|
+
|
|
438
|
+
### Browser Limitations
|
|
439
|
+
|
|
440
|
+
1. **CORS Restrictions** - Browsers enforce Same-Origin Policy and CORS. Requests to different origins must have proper CORS headers set up server-side.
|
|
441
|
+
|
|
442
|
+
2. **Cookies and Authentication** - Third-party cookies might be blocked depending on browser settings. Use `withCredentials(CredentialsPolicy.INCLUDE)` for cross-origin authenticated requests.
|
|
443
|
+
|
|
444
|
+
3. **Mixed Content** - Browsers block HTTP requests from HTTPS pages. Always use HTTPS endpoints in production.
|
|
445
|
+
|
|
446
|
+
4. **Content Security Policy (CSP)** - If your application uses CSP, you must configure it to allow connections to your API endpoints.
|
|
447
|
+
|
|
448
|
+
5. **Priority Hints** - The `withPriority` feature is only supported in some modern browsers and may be ignored in others.
|
|
449
|
+
|
|
450
|
+
6. **KeepAlive** - The `withKeepAlive` feature allows requests to outlive the page but has varying support across browsers.
|
|
451
|
+
|
|
452
|
+
### Server-Side (Node.js) Limitations
|
|
453
|
+
|
|
454
|
+
1. **Missing Node.js Fetch** - Prior to Node 18, the Fetch API isn't available natively.
|
|
455
|
+
|
|
456
|
+
2. **Self-signed Certificates** - Node.js rejects self-signed certificates by default. You may need additional configuration for development environments.
|
|
457
|
+
|
|
458
|
+
3. **Memory Management** - When downloading large files or processing large responses, be mindful of memory consumption, especially when using `arrayBuffer()` or `blob()`.
|
|
459
|
+
|
|
460
|
+
4. **Proxy Support** - Additional configuration may be needed to work with HTTP proxies in Node.js.
|
|
461
|
+
|
|
462
|
+
5. **Limited Feature Support** - Features like `withKeepAlive` and `withPriority` might not be relevant or fully supported in Node.js environments.
|
|
463
|
+
|
|
464
|
+
## Browser Compatibility
|
|
465
|
+
|
|
466
|
+
This library works with all browsers that support the Fetch API:
|
|
467
|
+
|
|
468
|
+
- Chrome 42+
|
|
469
|
+
- Firefox 39+
|
|
470
|
+
- Safari 10.1+
|
|
471
|
+
- Edge 14+
|
|
472
|
+
- Opera 29+
|
|
473
|
+
|
|
474
|
+
## Comparison with Other Libraries
|
|
475
|
+
|
|
476
|
+
| Feature | create-request | axios | fetch |
|
|
477
|
+
|---------|---------------|-------|-------|
|
|
478
|
+
| Bundle Size | Small (~2KB) | Medium (~14KB) | Smallest (built-in) |
|
|
479
|
+
| TypeScript Support | Full with type inference | Partial | Manual |
|
|
480
|
+
| Type Safety | Enums for constants | Limited | None |
|
|
481
|
+
| Chainable API | β
Yes | β No | β No |
|
|
482
|
+
| Request Cancellation | β
Yes (AbortController) | β
Yes | β
Yes (manual) |
|
|
483
|
+
| Auto JSON | β
Yes | β
Yes | β No |
|
|
484
|
+
| Timeout | β
Yes | β
Yes | β No (manual) |
|
|
485
|
+
| Retries | β
Yes | β No (needs addon) | β No (manual) |
|
|
486
|
+
| Query params with arrays | β
Yes | β
Yes | β No (manual) |
|
|
487
|
+
| Request Priority | β
Yes (simple API) | β No | β
Yes (via options) |
|
|
488
|
+
| KeepAlive | β
Yes (simple API) | β No | β
Yes (via options) |
|
|
489
|
+
| Learning Curve | Low | Medium | Medium |
|
|
490
|
+
|
|
491
|
+
### Why Not Just Use fetch?
|
|
492
|
+
like JSON parsing
|
|
493
|
+
The native Fetch API is powerful but low-level, requiring you to:ing
|
|
494
|
+
- Write boilerplate for common tasks like JSON parsing
|
|
495
|
+
- Manually implement timeout handlingeps
|
|
496
|
+
- Create your own retry mechanisms- Parse non-2xx responses manually
|
|
497
|
+
- Handle errors across multiple steps
|
|
498
|
+
- Parse non-2xx responses manually`create-request` gives you all these features with a cleaner API that's designed specifically for modern TypeScript applications.
|
|
499
|
+
|
|
500
|
+
`create-request` gives you all these features with a cleaner API that's designed specifically for modern TypeScript applications.### Why Not axios?
|
|
501
|
+
|
|
502
|
+
### Why Not axios?est` offers:
|
|
503
|
+
|
|
504
|
+
While axios is popular, `create-request` offers:er)
|
|
505
|
+
- Smaller bundle size (~85% smaller)n
|
|
506
|
+
- More complete TypeScript integration
|
|
507
|
+
- Built-in retries without addons- Modern features like priority hints
|
|
508
|
+
- Modern features like priority hintsainable API
|
|
509
|
+
- A more intuitive, chainable API
|
|
510
|
+
|
|
511
|
+
## Real-world Examples
|
|
512
|
+
t for Authentication
|
|
513
|
+
### API Client for Authentication
|
|
514
|
+
|
|
515
|
+
```typescripta reusable authentication client
|
|
516
|
+
// Create a reusable authentication client
|
|
517
|
+
function createAuthClient(baseUrl) {
|
|
518
|
+
return {{
|
|
519
|
+
login: async (email, password) => {
|
|
520
|
+
return create.post()
|
|
521
|
+
.withBody({ email, password })eout(3000)
|
|
522
|
+
.withTimeout(3000) .sendTo(`${baseUrl}/auth/login`)
|
|
523
|
+
.sendTo(`${baseUrl}/auth/login`) .json();
|
|
524
|
+
.json();
|
|
525
|
+
},
|
|
526
|
+
en) => {
|
|
527
|
+
refreshToken: async (refreshToken) => {t()
|
|
528
|
+
return create.post()
|
|
529
|
+
.withBody({ refreshToken })ries(2)
|
|
530
|
+
.withRetries(2) .sendTo(`${baseUrl}/auth/refresh`)
|
|
531
|
+
.sendTo(`${baseUrl}/auth/refresh`) .json();
|
|
532
|
+
.json(); }
|
|
533
|
+
} };
|
|
534
|
+
};
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// Use it in your applicationst authClient = createAuthClient('https://api.example.com');
|
|
538
|
+
const authClient = createAuthClient('https://api.example.com');const { token, user } = await authClient.login('user@example.com', 'password');
|
|
539
|
+
const { token, user } = await authClient.login('user@example.com', 'password');
|
|
540
|
+
```
|
|
541
|
+
ad with Progress
|
|
542
|
+
### File Upload with Progress
|
|
543
|
+
|
|
544
|
+
```typescript
|
|
545
|
+
// Upload a file with abort capabilityconst uploadFile = async (file, onProgress) => {
|
|
546
|
+
const uploadFile = async (file, onProgress) => {Controller();
|
|
547
|
+
const controller = new AbortController();
|
|
548
|
+
const form = new FormData();
|
|
549
|
+
const form = new FormData();append('file', file);
|
|
550
|
+
form.append('file', file);
|
|
551
|
+
|
|
552
|
+
try {
|
|
553
|
+
return await create.post()
|
|
554
|
+
.withBody(form)oller(controller)
|
|
555
|
+
.withAbortController(controller)or large files
|
|
556
|
+
.withTimeout(60000) // 1 minute timeout for large filesries(2)
|
|
557
|
+
.withRetries(2)s://api.example.com/upload')
|
|
558
|
+
.sendTo('https://api.example.com/upload')
|
|
559
|
+
.json();
|
|
560
|
+
} catch (error) {f (error instanceof RequestError) {
|
|
561
|
+
if (error instanceof RequestError) {ror(`Upload failed: ${error.message}`);
|
|
562
|
+
console.error(`Upload failed: ${error.message}`); }
|
|
563
|
+
} throw error;
|
|
564
|
+
throw error;
|
|
565
|
+
}
|
|
566
|
+
turn {
|
|
567
|
+
return { abort: () => controller.abort()
|
|
568
|
+
abort: () => controller.abort();
|
|
569
|
+
};};
|
|
570
|
+
};
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
## License
|
|
574
|
+
|
|
575
|
+
MIT
|