@talosjs/fetcher 1.0.0
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 +476 -0
- package/dist/index.d.ts +54 -0
- package/dist/index.js +129 -0
- package/dist/index.js.map +10 -0
- package/package.json +47 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Talos
|
|
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,476 @@
|
|
|
1
|
+
# @talosjs/fetcher
|
|
2
|
+
|
|
3
|
+
Lightweight HTTP client with typed headers, response parsing, and configurable request/response handling for external API integration. This package provides a fluent API for HTTP operations with built-in support for authentication tokens, content types, request cancellation, and file uploads.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
8
|
+

|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
✅ **Simple API** - Intuitive methods for GET, POST, PUT, PATCH, DELETE, HEAD, and OPTIONS
|
|
13
|
+
|
|
14
|
+
✅ **Typed Responses** - Generic response types with `ResponseDataType<T>` for full TypeScript support
|
|
15
|
+
|
|
16
|
+
✅ **Authentication** - Built-in support for Bearer and Basic authentication tokens
|
|
17
|
+
|
|
18
|
+
✅ **File Uploads** - Easy file upload with automatic FormData handling
|
|
19
|
+
|
|
20
|
+
✅ **Request Cancellation** - Abort in-flight requests with AbortController integration
|
|
21
|
+
|
|
22
|
+
✅ **Header Management** - Typed header manipulation via `@talosjs/http-header`
|
|
23
|
+
|
|
24
|
+
✅ **Base URL Support** - Configure base URL for cleaner API calls
|
|
25
|
+
|
|
26
|
+
✅ **Cloneable** - Create independent copies of configured fetcher instances
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
bun add @talosjs/fetcher
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Usage
|
|
35
|
+
|
|
36
|
+
### Basic GET Request
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
import { Fetcher } from '@talosjs/fetcher';
|
|
40
|
+
|
|
41
|
+
const fetcher = new Fetcher('https://api.example.com');
|
|
42
|
+
|
|
43
|
+
const response = await fetcher.get<{ users: User[] }>('/users');
|
|
44
|
+
|
|
45
|
+
if (response.success) {
|
|
46
|
+
console.log(response.data.users);
|
|
47
|
+
} else {
|
|
48
|
+
console.error(response.message);
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### POST Request with Data
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
import { Fetcher } from '@talosjs/fetcher';
|
|
56
|
+
|
|
57
|
+
const fetcher = new Fetcher('https://api.example.com');
|
|
58
|
+
|
|
59
|
+
const response = await fetcher.post<{ user: User }>('/users', {
|
|
60
|
+
name: 'John Doe',
|
|
61
|
+
email: 'john@example.com'
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
if (response.success) {
|
|
65
|
+
console.log('Created user:', response.data.user);
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### With Authentication
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
import { Fetcher } from '@talosjs/fetcher';
|
|
73
|
+
|
|
74
|
+
const fetcher = new Fetcher('https://api.example.com');
|
|
75
|
+
|
|
76
|
+
// Set Bearer token
|
|
77
|
+
fetcher.setBearerToken('your-jwt-token');
|
|
78
|
+
|
|
79
|
+
const response = await fetcher.get<{ profile: Profile }>('/me');
|
|
80
|
+
|
|
81
|
+
// Clear token when done
|
|
82
|
+
fetcher.clearBearerToken();
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### File Upload
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
import { Fetcher } from '@talosjs/fetcher';
|
|
89
|
+
|
|
90
|
+
const fetcher = new Fetcher('https://api.example.com');
|
|
91
|
+
|
|
92
|
+
const file = document.querySelector('input[type="file"]').files[0];
|
|
93
|
+
|
|
94
|
+
const response = await fetcher.upload<{ url: string }>(
|
|
95
|
+
'/upload',
|
|
96
|
+
file,
|
|
97
|
+
'avatar' // form field name
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
if (response.success) {
|
|
101
|
+
console.log('Uploaded to:', response.data.url);
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Request Cancellation
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
import { Fetcher } from '@talosjs/fetcher';
|
|
109
|
+
|
|
110
|
+
const fetcher = new Fetcher('https://api.example.com');
|
|
111
|
+
|
|
112
|
+
// Start a request
|
|
113
|
+
const promise = fetcher.get('/slow-endpoint');
|
|
114
|
+
|
|
115
|
+
// Cancel it
|
|
116
|
+
fetcher.abort();
|
|
117
|
+
|
|
118
|
+
// Handle the cancellation
|
|
119
|
+
try {
|
|
120
|
+
await promise;
|
|
121
|
+
} catch (error) {
|
|
122
|
+
if (error.name === 'AbortError') {
|
|
123
|
+
console.log('Request was cancelled');
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## API Reference
|
|
129
|
+
|
|
130
|
+
### Classes
|
|
131
|
+
|
|
132
|
+
#### `Fetcher`
|
|
133
|
+
|
|
134
|
+
HTTP client class for making fetch requests.
|
|
135
|
+
|
|
136
|
+
**Constructor:**
|
|
137
|
+
```typescript
|
|
138
|
+
new Fetcher(baseURL?: string)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Parameters:**
|
|
142
|
+
- `baseURL` - Optional base URL to prepend to all request paths
|
|
143
|
+
|
|
144
|
+
**Properties:**
|
|
145
|
+
|
|
146
|
+
##### `header: Header`
|
|
147
|
+
|
|
148
|
+
Access to the underlying Header instance for advanced header manipulation.
|
|
149
|
+
|
|
150
|
+
**Methods:**
|
|
151
|
+
|
|
152
|
+
##### `get<T>(path: string): Promise<ResponseDataType<T>>`
|
|
153
|
+
|
|
154
|
+
Performs a GET request.
|
|
155
|
+
|
|
156
|
+
**Parameters:**
|
|
157
|
+
- `path` - Request path (appended to base URL if set)
|
|
158
|
+
|
|
159
|
+
**Returns:** Promise resolving to typed response data
|
|
160
|
+
|
|
161
|
+
**Example:**
|
|
162
|
+
```typescript
|
|
163
|
+
const response = await fetcher.get<{ items: Item[] }>('/items');
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
##### `post<T>(path: string, data?: unknown): Promise<ResponseDataType<T>>`
|
|
167
|
+
|
|
168
|
+
Performs a POST request with optional body data.
|
|
169
|
+
|
|
170
|
+
**Parameters:**
|
|
171
|
+
- `path` - Request path
|
|
172
|
+
- `data` - Optional request body (automatically JSON-stringified for objects)
|
|
173
|
+
|
|
174
|
+
**Returns:** Promise resolving to typed response data
|
|
175
|
+
|
|
176
|
+
**Example:**
|
|
177
|
+
```typescript
|
|
178
|
+
const response = await fetcher.post<{ id: string }>('/items', { name: 'New Item' });
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
##### `put<T>(path: string, data?: unknown): Promise<ResponseDataType<T>>`
|
|
182
|
+
|
|
183
|
+
Performs a PUT request with optional body data.
|
|
184
|
+
|
|
185
|
+
##### `patch<T>(path: string, data?: unknown): Promise<ResponseDataType<T>>`
|
|
186
|
+
|
|
187
|
+
Performs a PATCH request with optional body data.
|
|
188
|
+
|
|
189
|
+
##### `delete<T>(path: string): Promise<ResponseDataType<T>>`
|
|
190
|
+
|
|
191
|
+
Performs a DELETE request.
|
|
192
|
+
|
|
193
|
+
##### `head<T>(path: string): Promise<ResponseDataType<T>>`
|
|
194
|
+
|
|
195
|
+
Performs a HEAD request.
|
|
196
|
+
|
|
197
|
+
##### `options<T>(path: string): Promise<ResponseDataType<T>>`
|
|
198
|
+
|
|
199
|
+
Performs an OPTIONS request.
|
|
200
|
+
|
|
201
|
+
##### `request<T>(method: HttpMethodType, path: string, data?: unknown): Promise<ResponseDataType<T>>`
|
|
202
|
+
|
|
203
|
+
Performs a custom HTTP request.
|
|
204
|
+
|
|
205
|
+
**Parameters:**
|
|
206
|
+
- `method` - HTTP method (GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS)
|
|
207
|
+
- `path` - Request path
|
|
208
|
+
- `data` - Optional request body
|
|
209
|
+
|
|
210
|
+
**Example:**
|
|
211
|
+
```typescript
|
|
212
|
+
const response = await fetcher.request<{ result: string }>('POST', '/custom', { foo: 'bar' });
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
##### `upload<T>(path: string, file: File | Blob, name?: string): Promise<ResponseDataType<T>>`
|
|
216
|
+
|
|
217
|
+
Uploads a file using multipart/form-data.
|
|
218
|
+
|
|
219
|
+
**Parameters:**
|
|
220
|
+
- `path` - Upload endpoint path
|
|
221
|
+
- `file` - File or Blob to upload
|
|
222
|
+
- `name` - Form field name (default: 'file')
|
|
223
|
+
|
|
224
|
+
**Returns:** Promise resolving to typed response data
|
|
225
|
+
|
|
226
|
+
**Example:**
|
|
227
|
+
```typescript
|
|
228
|
+
const response = await fetcher.upload<{ url: string }>('/upload', file, 'document');
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
##### `setBearerToken(token: string): this`
|
|
232
|
+
|
|
233
|
+
Sets the Authorization header with a Bearer token.
|
|
234
|
+
|
|
235
|
+
**Parameters:**
|
|
236
|
+
- `token` - JWT or other bearer token
|
|
237
|
+
|
|
238
|
+
**Returns:** The fetcher instance for chaining
|
|
239
|
+
|
|
240
|
+
##### `setBasicToken(token: string): this`
|
|
241
|
+
|
|
242
|
+
Sets the Authorization header with Basic authentication.
|
|
243
|
+
|
|
244
|
+
**Parameters:**
|
|
245
|
+
- `token` - Base64-encoded credentials
|
|
246
|
+
|
|
247
|
+
**Returns:** The fetcher instance for chaining
|
|
248
|
+
|
|
249
|
+
##### `clearBearerToken(): this`
|
|
250
|
+
|
|
251
|
+
Removes the Authorization header.
|
|
252
|
+
|
|
253
|
+
**Returns:** The fetcher instance for chaining
|
|
254
|
+
|
|
255
|
+
##### `clearBasicToken(): this`
|
|
256
|
+
|
|
257
|
+
Removes the Authorization header.
|
|
258
|
+
|
|
259
|
+
**Returns:** The fetcher instance for chaining
|
|
260
|
+
|
|
261
|
+
##### `setContentType(contentType: MimeType): this`
|
|
262
|
+
|
|
263
|
+
Sets the Content-Type header.
|
|
264
|
+
|
|
265
|
+
**Parameters:**
|
|
266
|
+
- `contentType` - MIME type string
|
|
267
|
+
|
|
268
|
+
**Returns:** The fetcher instance for chaining
|
|
269
|
+
|
|
270
|
+
##### `setLang(lang: string): this`
|
|
271
|
+
|
|
272
|
+
Sets the Accept-Language or custom language header.
|
|
273
|
+
|
|
274
|
+
**Parameters:**
|
|
275
|
+
- `lang` - Language code (e.g., 'en', 'fr')
|
|
276
|
+
|
|
277
|
+
**Returns:** The fetcher instance for chaining
|
|
278
|
+
|
|
279
|
+
##### `abort(): this`
|
|
280
|
+
|
|
281
|
+
Cancels any in-flight requests and resets the AbortController.
|
|
282
|
+
|
|
283
|
+
**Returns:** The fetcher instance for chaining
|
|
284
|
+
|
|
285
|
+
##### `clone(): Fetcher`
|
|
286
|
+
|
|
287
|
+
Creates a new Fetcher instance with the same base URL.
|
|
288
|
+
|
|
289
|
+
**Returns:** New Fetcher instance
|
|
290
|
+
|
|
291
|
+
### Interfaces
|
|
292
|
+
|
|
293
|
+
#### `IFetcher`
|
|
294
|
+
|
|
295
|
+
```typescript
|
|
296
|
+
interface IFetcher {
|
|
297
|
+
readonly header: Header;
|
|
298
|
+
|
|
299
|
+
setBearerToken(token: string): IFetcher;
|
|
300
|
+
setBasicToken(token: string): IFetcher;
|
|
301
|
+
clearBearerToken(): IFetcher;
|
|
302
|
+
clearBasicToken(): IFetcher;
|
|
303
|
+
setContentType(contentType: MimeType): IFetcher;
|
|
304
|
+
setLang(lang: string): IFetcher;
|
|
305
|
+
abort(): IFetcher;
|
|
306
|
+
clone(): IFetcher;
|
|
307
|
+
|
|
308
|
+
get<T>(path: string): Promise<ResponseDataType<T>>;
|
|
309
|
+
post<T>(path: string, data?: unknown): Promise<ResponseDataType<T>>;
|
|
310
|
+
put<T>(path: string, data?: unknown): Promise<ResponseDataType<T>>;
|
|
311
|
+
patch<T>(path: string, data?: unknown): Promise<ResponseDataType<T>>;
|
|
312
|
+
delete<T>(path: string): Promise<ResponseDataType<T>>;
|
|
313
|
+
head<T>(path: string): Promise<ResponseDataType<T>>;
|
|
314
|
+
options<T>(path: string): Promise<ResponseDataType<T>>;
|
|
315
|
+
request<T>(method: HttpMethodType, path: string, data?: unknown): Promise<ResponseDataType<T>>;
|
|
316
|
+
upload<T>(path: string, file: File | Blob, name?: string): Promise<ResponseDataType<T>>;
|
|
317
|
+
}
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
## Advanced Usage
|
|
321
|
+
|
|
322
|
+
### Creating API Client Classes
|
|
323
|
+
|
|
324
|
+
```typescript
|
|
325
|
+
import { Fetcher } from '@talosjs/fetcher';
|
|
326
|
+
|
|
327
|
+
class UserApi {
|
|
328
|
+
private fetcher: Fetcher;
|
|
329
|
+
|
|
330
|
+
constructor(baseUrl: string, token?: string) {
|
|
331
|
+
this.fetcher = new Fetcher(baseUrl);
|
|
332
|
+
if (token) {
|
|
333
|
+
this.fetcher.setBearerToken(token);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
public async getUsers() {
|
|
338
|
+
return this.fetcher.get<{ users: User[] }>('/users');
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
public async createUser(data: CreateUserDto) {
|
|
342
|
+
return this.fetcher.post<{ user: User }>('/users', data);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
public async updateUser(id: string, data: UpdateUserDto) {
|
|
346
|
+
return this.fetcher.patch<{ user: User }>(`/users/${id}`, data);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
public async deleteUser(id: string) {
|
|
350
|
+
return this.fetcher.delete<{ success: boolean }>(`/users/${id}`);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### Request Interceptors with Header Manipulation
|
|
356
|
+
|
|
357
|
+
```typescript
|
|
358
|
+
import { Fetcher } from '@talosjs/fetcher';
|
|
359
|
+
|
|
360
|
+
const fetcher = new Fetcher('https://api.example.com');
|
|
361
|
+
|
|
362
|
+
// Add custom headers
|
|
363
|
+
fetcher.header.set('X-Request-ID', generateRequestId());
|
|
364
|
+
fetcher.header.set('X-Client-Version', '1.0.0');
|
|
365
|
+
|
|
366
|
+
const response = await fetcher.get('/endpoint');
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
### Error Handling
|
|
370
|
+
|
|
371
|
+
```typescript
|
|
372
|
+
import { Fetcher } from '@talosjs/fetcher';
|
|
373
|
+
|
|
374
|
+
const fetcher = new Fetcher('https://api.example.com');
|
|
375
|
+
|
|
376
|
+
const response = await fetcher.get<{ data: string }>('/resource');
|
|
377
|
+
|
|
378
|
+
if (response.success) {
|
|
379
|
+
// Handle successful response
|
|
380
|
+
console.log(response.data);
|
|
381
|
+
} else if (response.isClientError) {
|
|
382
|
+
// Handle 4xx errors
|
|
383
|
+
console.error('Client error:', response.message);
|
|
384
|
+
} else if (response.isServerError) {
|
|
385
|
+
// Handle 5xx errors
|
|
386
|
+
console.error('Server error:', response.message);
|
|
387
|
+
} else if (response.isNotFound) {
|
|
388
|
+
// Handle 404
|
|
389
|
+
console.error('Resource not found');
|
|
390
|
+
} else if (response.isUnauthorized) {
|
|
391
|
+
// Handle 401
|
|
392
|
+
console.error('Unauthorized - please login');
|
|
393
|
+
}
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
### Chaining Configuration
|
|
397
|
+
|
|
398
|
+
```typescript
|
|
399
|
+
import { Fetcher } from '@talosjs/fetcher';
|
|
400
|
+
|
|
401
|
+
const fetcher = new Fetcher('https://api.example.com')
|
|
402
|
+
.setBearerToken('your-token')
|
|
403
|
+
.setLang('en')
|
|
404
|
+
.setContentType('application/json');
|
|
405
|
+
|
|
406
|
+
const response = await fetcher.post('/data', { key: 'value' });
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
### Cloning for Different Contexts
|
|
410
|
+
|
|
411
|
+
```typescript
|
|
412
|
+
import { Fetcher } from '@talosjs/fetcher';
|
|
413
|
+
|
|
414
|
+
const baseFetcher = new Fetcher('https://api.example.com');
|
|
415
|
+
|
|
416
|
+
// Create authenticated clone
|
|
417
|
+
const authFetcher = baseFetcher.clone();
|
|
418
|
+
authFetcher.setBearerToken('user-token');
|
|
419
|
+
|
|
420
|
+
// Create admin clone
|
|
421
|
+
const adminFetcher = baseFetcher.clone();
|
|
422
|
+
adminFetcher.setBearerToken('admin-token');
|
|
423
|
+
|
|
424
|
+
// Use independently
|
|
425
|
+
await authFetcher.get('/user/profile');
|
|
426
|
+
await adminFetcher.get('/admin/dashboard');
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
### Uploading Multiple Files
|
|
430
|
+
|
|
431
|
+
```typescript
|
|
432
|
+
import { Fetcher } from '@talosjs/fetcher';
|
|
433
|
+
|
|
434
|
+
const fetcher = new Fetcher('https://api.example.com');
|
|
435
|
+
|
|
436
|
+
async function uploadFiles(files: File[]) {
|
|
437
|
+
const results = [];
|
|
438
|
+
|
|
439
|
+
for (const file of files) {
|
|
440
|
+
const response = await fetcher.upload<{ url: string }>(
|
|
441
|
+
'/upload',
|
|
442
|
+
file,
|
|
443
|
+
'file'
|
|
444
|
+
);
|
|
445
|
+
results.push(response);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
return results;
|
|
449
|
+
}
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
## License
|
|
453
|
+
|
|
454
|
+
This project is licensed under the MIT License - see the [LICENSE](./LICENSE) file for details.
|
|
455
|
+
|
|
456
|
+
## Contributing
|
|
457
|
+
|
|
458
|
+
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
|
|
459
|
+
|
|
460
|
+
### Development Setup
|
|
461
|
+
|
|
462
|
+
1. Clone the repository
|
|
463
|
+
2. Install dependencies: `bun install`
|
|
464
|
+
3. Run tests: `bun run test`
|
|
465
|
+
4. Build the project: `bun run build`
|
|
466
|
+
|
|
467
|
+
### Guidelines
|
|
468
|
+
|
|
469
|
+
- Write tests for new features
|
|
470
|
+
- Follow the existing code style
|
|
471
|
+
- Update documentation for API changes
|
|
472
|
+
- Ensure all tests pass before submitting PR
|
|
473
|
+
|
|
474
|
+
---
|
|
475
|
+
|
|
476
|
+
Made with ❤️ by the Talos team
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Header as Header2 } from "@talosjs/http-header";
|
|
2
|
+
import { MimeType as MimeType2 } from "@talosjs/http-mimes";
|
|
3
|
+
import { ResponseDataType as ResponseDataType2 } from "@talosjs/http-response";
|
|
4
|
+
import { HttpMethodType as HttpMethodType2 } from "@talosjs/types";
|
|
5
|
+
import { Header } from "@talosjs/http-header";
|
|
6
|
+
import { MimeType } from "@talosjs/http-mimes";
|
|
7
|
+
import { ResponseDataType } from "@talosjs/http-response";
|
|
8
|
+
import { HttpMethodType } from "@talosjs/types";
|
|
9
|
+
interface IFetcher {
|
|
10
|
+
readonly header: Header;
|
|
11
|
+
setBearerToken(token: string): IFetcher;
|
|
12
|
+
setBasicToken(token: string): IFetcher;
|
|
13
|
+
clearBearerToken(): IFetcher;
|
|
14
|
+
clearBasicToken(): IFetcher;
|
|
15
|
+
setContentType(contentType: MimeType): IFetcher;
|
|
16
|
+
setLang(lang: string): IFetcher;
|
|
17
|
+
abort(): IFetcher;
|
|
18
|
+
clone(): IFetcher;
|
|
19
|
+
get<T extends Record<string, unknown> = Record<string, unknown>>(path: string): Promise<ResponseDataType<T>>;
|
|
20
|
+
post<T extends Record<string, unknown> = Record<string, unknown>>(path: string, data?: unknown): Promise<ResponseDataType<T>>;
|
|
21
|
+
put<T extends Record<string, unknown> = Record<string, unknown>>(path: string, data?: unknown): Promise<ResponseDataType<T>>;
|
|
22
|
+
patch<T extends Record<string, unknown> = Record<string, unknown>>(path: string, data?: unknown): Promise<ResponseDataType<T>>;
|
|
23
|
+
delete<T extends Record<string, unknown> = Record<string, unknown>>(path: string): Promise<ResponseDataType<T>>;
|
|
24
|
+
head<T extends Record<string, unknown> = Record<string, unknown>>(path: string): Promise<ResponseDataType<T>>;
|
|
25
|
+
options<T extends Record<string, unknown> = Record<string, unknown>>(path: string): Promise<ResponseDataType<T>>;
|
|
26
|
+
request<T extends Record<string, unknown> = Record<string, unknown>>(method: HttpMethodType, path: string, data?: unknown): Promise<ResponseDataType<T>>;
|
|
27
|
+
upload<T extends Record<string, unknown> = Record<string, unknown>>(path: string, file: File | Blob, name?: string): Promise<ResponseDataType<T>>;
|
|
28
|
+
}
|
|
29
|
+
declare class Fetcher implements IFetcher {
|
|
30
|
+
private baseURL?;
|
|
31
|
+
private abortController;
|
|
32
|
+
readonly header: Header2;
|
|
33
|
+
constructor(baseURL?: string | undefined);
|
|
34
|
+
setBearerToken(token: string): this;
|
|
35
|
+
setBasicToken(token: string): this;
|
|
36
|
+
clearBearerToken(): this;
|
|
37
|
+
clearBasicToken(): this;
|
|
38
|
+
setContentType(contentType: MimeType2): this;
|
|
39
|
+
setLang(lang: string): this;
|
|
40
|
+
abort(): this;
|
|
41
|
+
clone(): Fetcher;
|
|
42
|
+
get<T extends Record<string, unknown> = Record<string, unknown>>(path: string): Promise<ResponseDataType2<T>>;
|
|
43
|
+
post<T extends Record<string, unknown> = Record<string, unknown>>(path: string, data?: unknown): Promise<ResponseDataType2<T>>;
|
|
44
|
+
put<T extends Record<string, unknown> = Record<string, unknown>>(path: string, data?: unknown): Promise<ResponseDataType2<T>>;
|
|
45
|
+
patch<T extends Record<string, unknown> = Record<string, unknown>>(path: string, data?: unknown): Promise<ResponseDataType2<T>>;
|
|
46
|
+
delete<T extends Record<string, unknown> = Record<string, unknown>>(path: string): Promise<ResponseDataType2<T>>;
|
|
47
|
+
head<T extends Record<string, unknown> = Record<string, unknown>>(path: string): Promise<ResponseDataType2<T>>;
|
|
48
|
+
options<T extends Record<string, unknown> = Record<string, unknown>>(path: string): Promise<ResponseDataType2<T>>;
|
|
49
|
+
request<T extends Record<string, unknown> = Record<string, unknown>>(method: HttpMethodType2, path: string, data?: unknown): Promise<ResponseDataType2<T>>;
|
|
50
|
+
upload<T extends Record<string, unknown> = Record<string, unknown>>(path: string, file: File | Blob, name?: string): Promise<ResponseDataType2<T>>;
|
|
51
|
+
private buildURL;
|
|
52
|
+
private buildRequestOptions;
|
|
53
|
+
}
|
|
54
|
+
export { IFetcher, Fetcher };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
// src/Fetcher.ts
|
|
2
|
+
import { Header } from "@talosjs/http-header";
|
|
3
|
+
|
|
4
|
+
class Fetcher {
|
|
5
|
+
baseURL;
|
|
6
|
+
abortController;
|
|
7
|
+
header = new Header;
|
|
8
|
+
constructor(baseURL) {
|
|
9
|
+
this.baseURL = baseURL;
|
|
10
|
+
this.abortController = new AbortController;
|
|
11
|
+
}
|
|
12
|
+
setBearerToken(token) {
|
|
13
|
+
this.header.setBearerToken(token);
|
|
14
|
+
return this;
|
|
15
|
+
}
|
|
16
|
+
setBasicToken(token) {
|
|
17
|
+
this.header.setBasicAuth(token);
|
|
18
|
+
return this;
|
|
19
|
+
}
|
|
20
|
+
clearBearerToken() {
|
|
21
|
+
this.header.remove("Authorization");
|
|
22
|
+
return this;
|
|
23
|
+
}
|
|
24
|
+
clearBasicToken() {
|
|
25
|
+
this.header.remove("Authorization");
|
|
26
|
+
return this;
|
|
27
|
+
}
|
|
28
|
+
setContentType(contentType) {
|
|
29
|
+
this.header.contentType(contentType);
|
|
30
|
+
return this;
|
|
31
|
+
}
|
|
32
|
+
setLang(lang) {
|
|
33
|
+
this.header.setLang(lang);
|
|
34
|
+
return this;
|
|
35
|
+
}
|
|
36
|
+
abort() {
|
|
37
|
+
this.abortController.abort();
|
|
38
|
+
this.abortController = new AbortController;
|
|
39
|
+
return this;
|
|
40
|
+
}
|
|
41
|
+
clone() {
|
|
42
|
+
const cloned = new Fetcher(this.baseURL);
|
|
43
|
+
return cloned;
|
|
44
|
+
}
|
|
45
|
+
async get(path) {
|
|
46
|
+
return this.request("GET", path);
|
|
47
|
+
}
|
|
48
|
+
async post(path, data) {
|
|
49
|
+
return this.request("POST", path, data);
|
|
50
|
+
}
|
|
51
|
+
async put(path, data) {
|
|
52
|
+
return this.request("PUT", path, data);
|
|
53
|
+
}
|
|
54
|
+
async patch(path, data) {
|
|
55
|
+
return this.request("PATCH", path, data);
|
|
56
|
+
}
|
|
57
|
+
async delete(path) {
|
|
58
|
+
return this.request("DELETE", path);
|
|
59
|
+
}
|
|
60
|
+
async head(path) {
|
|
61
|
+
return this.request("HEAD", path);
|
|
62
|
+
}
|
|
63
|
+
async options(path) {
|
|
64
|
+
return this.request("OPTIONS", path);
|
|
65
|
+
}
|
|
66
|
+
async request(method, path, data) {
|
|
67
|
+
const fullURL = this.buildURL(path);
|
|
68
|
+
const requestOptions = this.buildRequestOptions(method, data);
|
|
69
|
+
const response = await fetch(fullURL, requestOptions);
|
|
70
|
+
try {
|
|
71
|
+
return await response.json();
|
|
72
|
+
} catch (error) {
|
|
73
|
+
throw new Error(error instanceof Error ? error.message : "Failed to parse JSON response");
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
async upload(path, file, name = "file") {
|
|
77
|
+
const formData = new FormData;
|
|
78
|
+
formData.append(name, file);
|
|
79
|
+
const originalContentType = this.header.get("Content-Type");
|
|
80
|
+
this.header.remove("Content-Type");
|
|
81
|
+
const result = await this.request("POST", path, formData);
|
|
82
|
+
if (originalContentType) {
|
|
83
|
+
this.header.set("Content-Type", originalContentType);
|
|
84
|
+
}
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
buildURL(url) {
|
|
88
|
+
if (url.startsWith("http://") || url.startsWith("https://")) {
|
|
89
|
+
return url;
|
|
90
|
+
}
|
|
91
|
+
if (!this.baseURL) {
|
|
92
|
+
return url;
|
|
93
|
+
}
|
|
94
|
+
const path = url.startsWith("/") ? url : `/${url}`;
|
|
95
|
+
const baseURL = this.baseURL.endsWith("/") ? this.baseURL.slice(0, -1) : this.baseURL;
|
|
96
|
+
return `${baseURL}${path}`;
|
|
97
|
+
}
|
|
98
|
+
buildRequestOptions(method, data) {
|
|
99
|
+
const headers = this.header.native;
|
|
100
|
+
let body;
|
|
101
|
+
if (data !== undefined && method !== "GET" && method !== "HEAD" && method !== "OPTIONS") {
|
|
102
|
+
if (data instanceof FormData) {
|
|
103
|
+
body = data;
|
|
104
|
+
this.header.clearContentType();
|
|
105
|
+
} else if (typeof data === "string") {
|
|
106
|
+
body = data;
|
|
107
|
+
} else if (data instanceof Blob || data instanceof ArrayBuffer) {
|
|
108
|
+
body = data;
|
|
109
|
+
} else {
|
|
110
|
+
body = JSON.stringify(data);
|
|
111
|
+
if (!this.header.has("Content-Type")) {
|
|
112
|
+
this.header.setJson();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
const requestOptions = {
|
|
117
|
+
method,
|
|
118
|
+
headers,
|
|
119
|
+
...body !== undefined && { body },
|
|
120
|
+
signal: this.abortController.signal
|
|
121
|
+
};
|
|
122
|
+
return requestOptions;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
export {
|
|
126
|
+
Fetcher
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
//# debugId=6BEC85E0C8278A0F64756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["src/Fetcher.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import { Header } from \"@talosjs/http-header\";\nimport type { MimeType } from \"@talosjs/http-mimes\";\nimport type { ResponseDataType } from \"@talosjs/http-response\";\nimport type { HttpMethodType } from \"@talosjs/types\";\nimport type { IFetcher } from \"./types\";\n\nexport class Fetcher implements IFetcher {\n private abortController: AbortController;\n public readonly header: Header = new Header();\n\n constructor(private baseURL?: string) {\n this.abortController = new AbortController();\n }\n\n public setBearerToken(token: string): this {\n this.header.setBearerToken(token);\n\n return this;\n }\n\n public setBasicToken(token: string): this {\n this.header.setBasicAuth(token);\n\n return this;\n }\n\n public clearBearerToken(): this {\n this.header.remove(\"Authorization\");\n\n return this;\n }\n\n public clearBasicToken(): this {\n this.header.remove(\"Authorization\");\n\n return this;\n }\n\n public setContentType(contentType: MimeType): this {\n this.header.contentType(contentType);\n\n return this;\n }\n\n public setLang(lang: string): this {\n this.header.setLang(lang);\n\n return this;\n }\n\n public abort(): this {\n this.abortController.abort();\n this.abortController = new AbortController();\n\n return this;\n }\n\n public clone(): Fetcher {\n const cloned = new Fetcher(this.baseURL);\n return cloned;\n }\n\n public async get<T extends Record<string, unknown> = Record<string, unknown>>(\n path: string,\n ): Promise<ResponseDataType<T>> {\n return this.request<T>(\"GET\", path);\n }\n\n public async post<T extends Record<string, unknown> = Record<string, unknown>>(\n path: string,\n data?: unknown,\n ): Promise<ResponseDataType<T>> {\n return this.request<T>(\"POST\", path, data);\n }\n\n public async put<T extends Record<string, unknown> = Record<string, unknown>>(\n path: string,\n data?: unknown,\n ): Promise<ResponseDataType<T>> {\n return this.request<T>(\"PUT\", path, data);\n }\n\n public async patch<T extends Record<string, unknown> = Record<string, unknown>>(\n path: string,\n data?: unknown,\n ): Promise<ResponseDataType<T>> {\n return this.request<T>(\"PATCH\", path, data);\n }\n\n public async delete<T extends Record<string, unknown> = Record<string, unknown>>(\n path: string,\n ): Promise<ResponseDataType<T>> {\n return this.request<T>(\"DELETE\", path);\n }\n\n public async head<T extends Record<string, unknown> = Record<string, unknown>>(\n path: string,\n ): Promise<ResponseDataType<T>> {\n return this.request<T>(\"HEAD\", path);\n }\n\n public async options<T extends Record<string, unknown> = Record<string, unknown>>(\n path: string,\n ): Promise<ResponseDataType<T>> {\n return this.request<T>(\"OPTIONS\", path);\n }\n\n public async request<T extends Record<string, unknown> = Record<string, unknown>>(\n method: HttpMethodType,\n path: string,\n data?: unknown,\n ): Promise<ResponseDataType<T>> {\n const fullURL = this.buildURL(path);\n const requestOptions = this.buildRequestOptions(method, data);\n const response = await fetch(fullURL, requestOptions);\n\n try {\n return await response.json();\n } catch (error) {\n throw new Error(error instanceof Error ? error.message : \"Failed to parse JSON response\");\n }\n }\n\n public async upload<T extends Record<string, unknown> = Record<string, unknown>>(\n path: string,\n file: File | Blob,\n name = \"file\",\n ): Promise<ResponseDataType<T>> {\n const formData = new FormData();\n formData.append(name, file);\n\n // Clear any existing Content-Type to let browser set multipart/form-data boundary\n const originalContentType = this.header.get(\"Content-Type\");\n this.header.remove(\"Content-Type\");\n\n const result = await this.request<T>(\"POST\", path, formData);\n\n // Restore original Content-Type if it existed\n if (originalContentType) {\n this.header.set(\"Content-Type\", originalContentType);\n }\n\n return result;\n }\n\n private buildURL(url: string): string {\n if (url.startsWith(\"http://\") || url.startsWith(\"https://\")) {\n return url;\n }\n\n if (!this.baseURL) {\n return url;\n }\n\n const path = url.startsWith(\"/\") ? url : `/${url}`;\n const baseURL = this.baseURL.endsWith(\"/\") ? this.baseURL.slice(0, -1) : this.baseURL;\n\n return `${baseURL}${path}`;\n }\n\n private buildRequestOptions(method: string, data?: unknown): RequestInit {\n const headers = this.header.native;\n\n let body: BodyInit | undefined;\n\n if (data !== undefined && method !== \"GET\" && method !== \"HEAD\" && method !== \"OPTIONS\") {\n if (data instanceof FormData) {\n body = data;\n this.header.clearContentType();\n } else if (typeof data === \"string\") {\n body = data;\n } else if (data instanceof Blob || data instanceof ArrayBuffer) {\n body = data;\n } else {\n body = JSON.stringify(data);\n // Set Content-Type to application/json if not already set\n if (!this.header.has(\"Content-Type\")) {\n this.header.setJson();\n }\n }\n }\n\n const requestOptions: RequestInit = {\n method,\n headers,\n ...(body !== undefined && { body }),\n signal: this.abortController.signal,\n };\n\n return requestOptions;\n }\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "6BEC85E0C8278A0F64756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@talosjs/fetcher",
|
|
3
|
+
"description": "Lightweight HTTP client with typed headers, response parsing, and configurable request/response handling for external API integration",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist",
|
|
8
|
+
"LICENSE",
|
|
9
|
+
"README.md",
|
|
10
|
+
"package.json"
|
|
11
|
+
],
|
|
12
|
+
"module": "./dist/index.js",
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"import": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"default": "./dist/index.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"./package.json": "./package.json"
|
|
22
|
+
},
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"scripts": {
|
|
25
|
+
"test": "bun test tests",
|
|
26
|
+
"build": "bunup",
|
|
27
|
+
"lint": "tsgo --noEmit && bunx biome lint",
|
|
28
|
+
"npm:publish": "bun publish --tolerate-republish --force --production --access public"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@talosjs/http-header": "^1.2.12"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@talosjs/http-response": "^1.4.1",
|
|
35
|
+
"@talosjs/http-mimes": "^1.1.11",
|
|
36
|
+
"@talosjs/types": "^1.3.7"
|
|
37
|
+
},
|
|
38
|
+
"keywords": [
|
|
39
|
+
"api-client",
|
|
40
|
+
"bun",
|
|
41
|
+
"fetch",
|
|
42
|
+
"fetcher",
|
|
43
|
+
"http-client",
|
|
44
|
+
"talos",
|
|
45
|
+
"typescript"
|
|
46
|
+
]
|
|
47
|
+
}
|