@ooneex/fetcher 0.0.1 → 0.3.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @ooneex/fetcher
2
2
 
3
- A powerful and flexible TypeScript/JavaScript HTTP client library built on top of the native Fetch API. This package provides a comprehensive set of methods for making HTTP requests with automatic JSON handling, header management, file uploads, and response status detection.
3
+ A lightweight HTTP client wrapper for making fetch requests with typed headers and response handling. This package provides a fluent API for HTTP operations with built-in support for authentication tokens, content types, request cancellation, and file uploads.
4
4
 
5
5
  ![Browser](https://img.shields.io/badge/Browser-Compatible-green?style=flat-square&logo=googlechrome)
6
6
  ![Bun](https://img.shields.io/badge/Bun-Compatible-orange?style=flat-square&logo=bun)
@@ -11,29 +11,21 @@ A powerful and flexible TypeScript/JavaScript HTTP client library built on top o
11
11
 
12
12
  ## Features
13
13
 
14
- ✅ **Native Fetch Based** - Built on top of the modern Fetch API
14
+ ✅ **Simple API** - Intuitive methods for GET, POST, PUT, PATCH, DELETE, HEAD, and OPTIONS
15
15
 
16
- ✅ **Type-Safe** - Full TypeScript support with proper type definitions
16
+ ✅ **Type-Safe Responses** - Generic response types with full TypeScript support
17
17
 
18
- ✅ **HTTP Methods** - Support for GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS
18
+ ✅ **Authentication** - Built-in support for Bearer and Basic authentication tokens
19
19
 
20
- ✅ **File Upload** - Built-in file and blob upload functionality
20
+ ✅ **File Uploads** - Easy file upload with automatic FormData handling
21
21
 
22
- ✅ **Header Management** - Comprehensive header manipulation methods
22
+ ✅ **Request Cancellation** - Abort in-flight requests with AbortController integration
23
23
 
24
- ✅ **Authentication** - Bearer token and basic authentication support
24
+ ✅ **Header Management** - Fluent API for managing request headers
25
25
 
26
- ✅ **Request Aborting** - Built-in AbortController support
26
+ ✅ **Base URL Support** - Configure base URL for cleaner API calls
27
27
 
28
- ✅ **Status Detection** - Automatic HTTP status code classification
29
-
30
- ✅ **JSON Handling** - Automatic JSON serialization and deserialization
31
-
32
- ✅ **Error Handling** - Comprehensive error handling and response parsing
33
-
34
- ✅ **Cross-Platform** - Works in Browser, Node.js, Bun, and Deno
35
-
36
- ✅ **Zero Dependencies** - Minimal external dependencies
28
+ ✅ **Cloneable** - Create independent copies of configured fetcher instances
37
29
 
38
30
  ## Installation
39
31
 
@@ -59,64 +51,53 @@ npm install @ooneex/fetcher
59
51
 
60
52
  ## Usage
61
53
 
62
- ### Basic Usage
54
+ ### Basic GET Request
63
55
 
64
56
  ```typescript
65
57
  import { Fetcher } from '@ooneex/fetcher';
66
58
 
67
- const api = new Fetcher('https://api.example.com');
59
+ const fetcher = new Fetcher('https://api.example.com');
68
60
 
69
- // GET request
70
- const response = await api.get('/users');
71
- console.log(response.data); // parsed JSON data
72
- console.log(response.isSuccessful); // true for 2xx status codes
61
+ const response = await fetcher.get<{ users: User[] }>('/users');
73
62
 
74
- // POST request with JSON data
75
- const newUser = { name: 'John Doe', email: 'john@example.com' };
76
- const createResponse = await api.post('/users', newUser);
63
+ if (response.success) {
64
+ console.log(response.data.users);
65
+ } else {
66
+ console.error(response.message);
67
+ }
77
68
  ```
78
69
 
79
- ### Authentication
70
+ ### POST Request with Data
80
71
 
81
72
  ```typescript
82
73
  import { Fetcher } from '@ooneex/fetcher';
83
74
 
84
- const api = new Fetcher('https://api.example.com');
75
+ const fetcher = new Fetcher('https://api.example.com');
85
76
 
86
- // Bearer token authentication
87
- api.setBearerToken('your-jwt-token');
77
+ const response = await fetcher.post<{ user: User }>('/users', {
78
+ name: 'John Doe',
79
+ email: 'john@example.com'
80
+ });
88
81
 
89
- // Basic authentication
90
- api.setBasicToken('base64-encoded-credentials');
91
-
92
- // Make authenticated requests
93
- const response = await api.get('/protected-resource');
94
-
95
- // Clear authentication
96
- api.clearBearerToken();
97
- api.clearBasicToken();
82
+ if (response.success) {
83
+ console.log('Created user:', response.data.user);
84
+ }
98
85
  ```
99
86
 
100
- ### Header Management
87
+ ### With Authentication
101
88
 
102
89
  ```typescript
103
90
  import { Fetcher } from '@ooneex/fetcher';
104
91
 
105
- const api = new Fetcher('https://api.example.com');
106
-
107
- // Set content type
108
- api.setContentType('application/json');
92
+ const fetcher = new Fetcher('https://api.example.com');
109
93
 
110
- // Set language
111
- api.setLang('en-US');
94
+ // Set Bearer token
95
+ fetcher.setBearerToken('your-jwt-token');
112
96
 
113
- // Chain header methods
114
- api.setBearerToken('token')
115
- .setContentType('application/json')
116
- .setLang('fr-FR');
97
+ const response = await fetcher.get<{ profile: Profile }>('/me');
117
98
 
118
- // Access header object directly
119
- api.header.set('X-Custom-Header', 'custom-value');
99
+ // Clear token when done
100
+ fetcher.clearBearerToken();
120
101
  ```
121
102
 
122
103
  ### File Upload
@@ -124,431 +105,371 @@ api.header.set('X-Custom-Header', 'custom-value');
124
105
  ```typescript
125
106
  import { Fetcher } from '@ooneex/fetcher';
126
107
 
127
- const api = new Fetcher('https://api.example.com');
108
+ const fetcher = new Fetcher('https://api.example.com');
128
109
 
129
- // Upload a file
130
- const fileInput = document.querySelector('input[type="file"]');
131
- const file = fileInput.files[0];
110
+ const file = document.querySelector('input[type="file"]').files[0];
132
111
 
133
- const uploadResponse = await api.upload('/upload', file, 'document');
112
+ const response = await fetcher.upload<{ url: string }>(
113
+ '/upload',
114
+ file,
115
+ 'avatar' // form field name
116
+ );
134
117
 
135
- // Upload a blob
136
- const blob = new Blob(['Hello, World!'], { type: 'text/plain' });
137
- const blobResponse = await api.upload('/upload-text', blob, 'textFile');
118
+ if (response.success) {
119
+ console.log('Uploaded to:', response.data.url);
120
+ }
138
121
  ```
139
122
 
140
- ### Request Aborting
123
+ ### Request Cancellation
141
124
 
142
125
  ```typescript
143
126
  import { Fetcher } from '@ooneex/fetcher';
144
127
 
145
- const api = new Fetcher('https://api.example.com');
128
+ const fetcher = new Fetcher('https://api.example.com');
146
129
 
147
130
  // Start a request
148
- const requestPromise = api.get('/slow-endpoint');
131
+ const promise = fetcher.get('/slow-endpoint');
149
132
 
150
- // Abort the request
151
- api.abort();
133
+ // Cancel it
134
+ fetcher.abort();
152
135
 
136
+ // Handle the cancellation
153
137
  try {
154
- const response = await requestPromise;
138
+ await promise;
155
139
  } catch (error) {
156
- console.log('Request was aborted');
140
+ if (error.name === 'AbortError') {
141
+ console.log('Request was cancelled');
142
+ }
157
143
  }
158
144
  ```
159
145
 
160
- ### Advanced Usage
146
+ ## API Reference
161
147
 
162
- ```typescript
163
- import { Fetcher } from '@ooneex/fetcher';
148
+ ### Classes
164
149
 
165
- const api = new Fetcher('https://api.example.com');
166
-
167
- // Configure headers and authentication
168
- api.setBearerToken('jwt-token')
169
- .setContentType('application/json')
170
- .setLang('en-US');
171
-
172
- // Make various HTTP requests
173
- const users = await api.get('/users');
174
- const user = await api.post('/users', { name: 'Jane Doe' });
175
- const updated = await api.put('/users/1', { name: 'Jane Smith' });
176
- const patched = await api.patch('/users/1', { email: 'jane@example.com' });
177
- await api.delete('/users/1');
178
-
179
- // Check response status
180
- if (user.isSuccessful) {
181
- console.log('User created:', user.data);
182
- } else if (user.isClientError) {
183
- console.log('Client error:', user.message);
184
- } else if (user.isServerError) {
185
- console.log('Server error:', user.message);
186
- }
150
+ #### `Fetcher`
187
151
 
188
- // Clone fetcher for different configurations
189
- const authenticatedApi = api.clone().setBearerToken('different-token');
152
+ HTTP client class for making fetch requests.
153
+
154
+ **Constructor:**
155
+ ```typescript
156
+ new Fetcher(baseURL?: string)
190
157
  ```
191
158
 
192
- ## API Reference
159
+ **Parameters:**
160
+ - `baseURL` - Optional base URL to prepend to all request paths
193
161
 
194
- ### `Fetcher` Class
162
+ **Properties:**
163
+
164
+ ##### `header: Header`
195
165
 
196
- The main class for making HTTP requests.
166
+ Access to the underlying Header instance for advanced header manipulation.
197
167
 
198
- #### Constructor
168
+ **Methods:**
199
169
 
200
- ##### `new Fetcher(baseURL: string)`
201
- Creates a new Fetcher instance with the specified base URL.
170
+ ##### `get<T>(path: string): Promise<ResponseDataType<T>>`
171
+
172
+ Performs a GET request.
202
173
 
203
174
  **Parameters:**
204
- - `baseURL` - The base URL for all requests
175
+ - `path` - Request path (appended to base URL if set)
176
+
177
+ **Returns:** Promise resolving to typed response data
205
178
 
206
179
  **Example:**
207
180
  ```typescript
208
- const api = new Fetcher('https://api.example.com');
181
+ const response = await fetcher.get<{ items: Item[] }>('/items');
209
182
  ```
210
183
 
211
- #### Authentication Methods
184
+ ##### `post<T>(path: string, data?: unknown): Promise<ResponseDataType<T>>`
212
185
 
213
- ##### `setBearerToken(token: string): Fetcher`
214
- Sets the Authorization header with a Bearer token.
186
+ Performs a POST request with optional body data.
215
187
 
216
188
  **Parameters:**
217
- - `token` - The Bearer token
189
+ - `path` - Request path
190
+ - `data` - Optional request body (automatically JSON-stringified for objects)
218
191
 
219
- **Returns:** The Fetcher instance for method chaining
192
+ **Returns:** Promise resolving to typed response data
220
193
 
221
194
  **Example:**
222
195
  ```typescript
223
- api.setBearerToken('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...');
196
+ const response = await fetcher.post<{ id: string }>('/items', { name: 'New Item' });
224
197
  ```
225
198
 
226
- ##### `setBasicToken(token: string): Fetcher`
227
- Sets the Authorization header with Basic authentication.
199
+ ##### `put<T>(path: string, data?: unknown): Promise<ResponseDataType<T>>`
228
200
 
229
- **Parameters:**
230
- - `token` - The base64-encoded credentials
201
+ Performs a PUT request with optional body data.
231
202
 
232
- **Returns:** The Fetcher instance for method chaining
203
+ ##### `patch<T>(path: string, data?: unknown): Promise<ResponseDataType<T>>`
233
204
 
234
- **Example:**
235
- ```typescript
236
- api.setBasicToken(btoa('username:password'));
237
- ```
205
+ Performs a PATCH request with optional body data.
238
206
 
239
- ##### `clearBearerToken(): Fetcher`
240
- Removes the Authorization header.
207
+ ##### `delete<T>(path: string): Promise<ResponseDataType<T>>`
241
208
 
242
- **Returns:** The Fetcher instance for method chaining
209
+ Performs a DELETE request.
243
210
 
244
- ##### `clearBasicToken(): Fetcher`
245
- Removes the Authorization header.
211
+ ##### `head<T>(path: string): Promise<ResponseDataType<T>>`
246
212
 
247
- **Returns:** The Fetcher instance for method chaining
213
+ Performs a HEAD request.
248
214
 
249
- #### Header Management Methods
215
+ ##### `options<T>(path: string): Promise<ResponseDataType<T>>`
250
216
 
251
- ##### `setContentType(contentType: MimeType): Fetcher`
252
- Sets the Content-Type header.
217
+ Performs an OPTIONS request.
253
218
 
254
- **Parameters:**
255
- - `contentType` - The MIME type for the content
219
+ ##### `request<T>(method: HttpMethodType, path: string, data?: unknown): Promise<ResponseDataType<T>>`
256
220
 
257
- **Returns:** The Fetcher instance for method chaining
221
+ Performs a custom HTTP request.
222
+
223
+ **Parameters:**
224
+ - `method` - HTTP method (GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS)
225
+ - `path` - Request path
226
+ - `data` - Optional request body
258
227
 
259
228
  **Example:**
260
229
  ```typescript
261
- api.setContentType('application/json');
262
- api.setContentType('multipart/form-data');
230
+ const response = await fetcher.request<{ result: string }>('POST', '/custom', { foo: 'bar' });
263
231
  ```
264
232
 
265
- ##### `setLang(lang: string): Fetcher`
266
- Sets the Accept-Language header.
233
+ ##### `upload<T>(path: string, file: File | Blob, name?: string): Promise<ResponseDataType<T>>`
234
+
235
+ Uploads a file using multipart/form-data.
267
236
 
268
237
  **Parameters:**
269
- - `lang` - The language code
238
+ - `path` - Upload endpoint path
239
+ - `file` - File or Blob to upload
240
+ - `name` - Form field name (default: 'file')
270
241
 
271
- **Returns:** The Fetcher instance for method chaining
242
+ **Returns:** Promise resolving to typed response data
272
243
 
273
244
  **Example:**
274
245
  ```typescript
275
- api.setLang('en-US');
276
- api.setLang('fr-FR');
246
+ const response = await fetcher.upload<{ url: string }>('/upload', file, 'document');
277
247
  ```
278
248
 
279
- #### Request Control Methods
280
-
281
- ##### `abort(): Fetcher`
282
- Aborts the current request and creates a new AbortController.
249
+ ##### `setBearerToken(token: string): this`
283
250
 
284
- **Returns:** The Fetcher instance for method chaining
251
+ Sets the Authorization header with a Bearer token.
285
252
 
286
- **Example:**
287
- ```typescript
288
- api.abort(); // Cancels any ongoing requests
289
- ```
253
+ **Parameters:**
254
+ - `token` - JWT or other bearer token
290
255
 
291
- ##### `clone(): Fetcher`
292
- Creates a new Fetcher instance with the same base URL.
256
+ **Returns:** The fetcher instance for chaining
293
257
 
294
- **Returns:** A new Fetcher instance
258
+ ##### `setBasicToken(token: string): this`
295
259
 
296
- **Example:**
297
- ```typescript
298
- const newApi = api.clone();
299
- ```
260
+ Sets the Authorization header with Basic authentication.
300
261
 
301
- #### HTTP Method Shortcuts
262
+ **Parameters:**
263
+ - `token` - Base64-encoded credentials
302
264
 
303
- ##### `get<T = unknown>(path: string): Promise<FetcherResponseType<T>>`
304
- Performs a GET request.
265
+ **Returns:** The fetcher instance for chaining
305
266
 
306
- **Parameters:**
307
- - `path` - The endpoint path
267
+ ##### `clearBearerToken(): this`
308
268
 
309
- **Returns:** Promise resolving to a FetcherResponseType
269
+ Removes the Authorization header.
310
270
 
311
- **Example:**
312
- ```typescript
313
- const users = await api.get<User[]>('/users');
314
- ```
271
+ **Returns:** The fetcher instance for chaining
315
272
 
316
- ##### `post<T = unknown>(path: string, data?: unknown): Promise<FetcherResponseType<T>>`
317
- Performs a POST request.
273
+ ##### `clearBasicToken(): this`
318
274
 
319
- **Parameters:**
320
- - `path` - The endpoint path
321
- - `data` - Optional request body data
275
+ Removes the Authorization header.
322
276
 
323
- **Returns:** Promise resolving to a FetcherResponseType
277
+ **Returns:** The fetcher instance for chaining
324
278
 
325
- **Example:**
326
- ```typescript
327
- const newUser = await api.post<User>('/users', { name: 'John' });
328
- ```
279
+ ##### `setContentType(contentType: MimeType): this`
329
280
 
330
- ##### `put<T = unknown>(path: string, data?: unknown): Promise<FetcherResponseType<T>>`
331
- Performs a PUT request.
281
+ Sets the Content-Type header.
332
282
 
333
283
  **Parameters:**
334
- - `path` - The endpoint path
335
- - `data` - Optional request body data
284
+ - `contentType` - MIME type string
336
285
 
337
- **Returns:** Promise resolving to a FetcherResponseType
286
+ **Returns:** The fetcher instance for chaining
338
287
 
339
- **Example:**
340
- ```typescript
341
- const updatedUser = await api.put<User>('/users/1', { name: 'Jane' });
342
- ```
288
+ ##### `setLang(lang: string): this`
343
289
 
344
- ##### `patch<T = unknown>(path: string, data?: unknown): Promise<FetcherResponseType<T>>`
345
- Performs a PATCH request.
290
+ Sets the Accept-Language or custom language header.
346
291
 
347
292
  **Parameters:**
348
- - `path` - The endpoint path
349
- - `data` - Optional request body data
293
+ - `lang` - Language code (e.g., 'en', 'fr')
350
294
 
351
- **Returns:** Promise resolving to a FetcherResponseType
295
+ **Returns:** The fetcher instance for chaining
352
296
 
353
- **Example:**
354
- ```typescript
355
- const patchedUser = await api.patch<User>('/users/1', { email: 'new@email.com' });
356
- ```
297
+ ##### `abort(): this`
357
298
 
358
- ##### `delete<T = unknown>(path: string): Promise<FetcherResponseType<T>>`
359
- Performs a DELETE request.
299
+ Cancels any in-flight requests and resets the AbortController.
360
300
 
361
- **Parameters:**
362
- - `path` - The endpoint path
301
+ **Returns:** The fetcher instance for chaining
363
302
 
364
- **Returns:** Promise resolving to a FetcherResponseType
303
+ ##### `clone(): Fetcher`
365
304
 
366
- **Example:**
367
- ```typescript
368
- await api.delete('/users/1');
369
- ```
305
+ Creates a new Fetcher instance with the same base URL.
370
306
 
371
- ##### `head<T = unknown>(path: string): Promise<FetcherResponseType<T>>`
372
- Performs a HEAD request.
307
+ **Returns:** New Fetcher instance
373
308
 
374
- **Parameters:**
375
- - `path` - The endpoint path
309
+ ### Interfaces
376
310
 
377
- **Returns:** Promise resolving to a FetcherResponseType
311
+ #### `IFetcher`
378
312
 
379
- **Example:**
380
313
  ```typescript
381
- const headers = await api.head('/users/1');
314
+ interface IFetcher {
315
+ readonly header: Header;
316
+
317
+ setBearerToken(token: string): IFetcher;
318
+ setBasicToken(token: string): IFetcher;
319
+ clearBearerToken(): IFetcher;
320
+ clearBasicToken(): IFetcher;
321
+ setContentType(contentType: MimeType): IFetcher;
322
+ setLang(lang: string): IFetcher;
323
+ abort(): IFetcher;
324
+ clone(): IFetcher;
325
+
326
+ get<T>(path: string): Promise<ResponseDataType<T>>;
327
+ post<T>(path: string, data?: unknown): Promise<ResponseDataType<T>>;
328
+ put<T>(path: string, data?: unknown): Promise<ResponseDataType<T>>;
329
+ patch<T>(path: string, data?: unknown): Promise<ResponseDataType<T>>;
330
+ delete<T>(path: string): Promise<ResponseDataType<T>>;
331
+ head<T>(path: string): Promise<ResponseDataType<T>>;
332
+ options<T>(path: string): Promise<ResponseDataType<T>>;
333
+ request<T>(method: HttpMethodType, path: string, data?: unknown): Promise<ResponseDataType<T>>;
334
+ upload<T>(path: string, file: File | Blob, name?: string): Promise<ResponseDataType<T>>;
335
+ }
382
336
  ```
383
337
 
384
- ##### `options<T = unknown>(path: string): Promise<FetcherResponseType<T>>`
385
- Performs an OPTIONS request.
386
-
387
- **Parameters:**
388
- - `path` - The endpoint path
338
+ ## Advanced Usage
389
339
 
390
- **Returns:** Promise resolving to a FetcherResponseType
340
+ ### Creating API Client Classes
391
341
 
392
- **Example:**
393
342
  ```typescript
394
- const options = await api.options('/users');
395
- ```
343
+ import { Fetcher } from '@ooneex/fetcher';
396
344
 
397
- ##### `request<T = unknown>(method: HttpMethodType, path: string, data?: unknown): Promise<FetcherResponseType<T>>`
398
- Performs a custom HTTP request.
345
+ class UserApi {
346
+ private fetcher: Fetcher;
399
347
 
400
- **Parameters:**
401
- - `method` - The HTTP method
402
- - `path` - The endpoint path
403
- - `data` - Optional request body data
348
+ constructor(baseUrl: string, token?: string) {
349
+ this.fetcher = new Fetcher(baseUrl);
350
+ if (token) {
351
+ this.fetcher.setBearerToken(token);
352
+ }
353
+ }
404
354
 
405
- **Returns:** Promise resolving to a FetcherResponseType
355
+ public async getUsers() {
356
+ return this.fetcher.get<{ users: User[] }>('/users');
357
+ }
406
358
 
407
- **Example:**
408
- ```typescript
409
- const response = await api.request('PATCH', '/users/1', { status: 'active' });
410
- ```
359
+ public async createUser(data: CreateUserDto) {
360
+ return this.fetcher.post<{ user: User }>('/users', data);
361
+ }
411
362
 
412
- ##### `upload<T = unknown>(path: string, file: File | Blob, name?: string): Promise<FetcherResponseType<T>>`
413
- Uploads a file or blob.
363
+ public async updateUser(id: string, data: UpdateUserDto) {
364
+ return this.fetcher.patch<{ user: User }>(`/users/${id}`, data);
365
+ }
414
366
 
415
- **Parameters:**
416
- - `path` - The endpoint path
417
- - `file` - The file or blob to upload
418
- - `name` - Optional field name (defaults to "file")
367
+ public async deleteUser(id: string) {
368
+ return this.fetcher.delete<{ success: boolean }>(`/users/${id}`);
369
+ }
370
+ }
371
+ ```
419
372
 
420
- **Returns:** Promise resolving to a FetcherResponseType
373
+ ### Request Interceptors with Header Manipulation
421
374
 
422
- **Example:**
423
375
  ```typescript
424
- const fileInput = document.querySelector('input[type="file"]');
425
- const file = fileInput.files[0];
426
- const response = await api.upload('/upload', file, 'document');
427
- ```
376
+ import { Fetcher } from '@ooneex/fetcher';
428
377
 
429
- #### Properties
378
+ const fetcher = new Fetcher('https://api.example.com');
430
379
 
431
- ##### `header: Header`
432
- Read-only access to the Header instance for direct header manipulation.
380
+ // Add custom headers
381
+ fetcher.header.set('X-Request-ID', generateRequestId());
382
+ fetcher.header.set('X-Client-Version', '1.0.0');
433
383
 
434
- **Example:**
435
- ```typescript
436
- api.header.set('X-API-Key', 'your-api-key');
437
- const contentType = api.header.get('Content-Type');
384
+ const response = await fetcher.get('/endpoint');
438
385
  ```
439
386
 
440
- ### Types
387
+ ### Error Handling
441
388
 
442
- #### `FetcherResponseType<T>`
443
- The response object returned by all HTTP methods.
389
+ ```typescript
390
+ import { Fetcher } from '@ooneex/fetcher';
444
391
 
445
- **Properties:**
446
- - `data: T | null` - The parsed response data
447
- - `message: string | null` - Error message if parsing failed
448
- - `header: ReadonlyHeader` - Response headers
449
- - `isInformational: boolean` - True for 1xx status codes
450
- - `isSuccessful: boolean` - True for 2xx status codes
451
- - `isRedirect: boolean` - True for 3xx status codes
452
- - `isClientError: boolean` - True for 4xx status codes
453
- - `isServerError: boolean` - True for 5xx status codes
454
- - `isError: boolean` - True for 4xx or 5xx status codes
392
+ const fetcher = new Fetcher('https://api.example.com');
455
393
 
456
- **Example:**
457
- ```typescript
458
- const response = await api.get<User[]>('/users');
394
+ const response = await fetcher.get<{ data: string }>('/resource');
459
395
 
460
- if (response.isSuccessful) {
461
- console.log('Users:', response.data);
396
+ if (response.success) {
397
+ // Handle successful response
398
+ console.log(response.data);
462
399
  } else if (response.isClientError) {
400
+ // Handle 4xx errors
463
401
  console.error('Client error:', response.message);
464
402
  } else if (response.isServerError) {
403
+ // Handle 5xx errors
465
404
  console.error('Server error:', response.message);
405
+ } else if (response.isNotFound) {
406
+ // Handle 404
407
+ console.error('Resource not found');
408
+ } else if (response.isUnauthorized) {
409
+ // Handle 401
410
+ console.error('Unauthorized - please login');
466
411
  }
467
412
  ```
468
413
 
469
- #### `IFetcher`
470
- Interface defining the Fetcher contract.
414
+ ### Chaining Configuration
471
415
 
472
- **Example:**
473
416
  ```typescript
474
- import { IFetcher } from '@ooneex/fetcher';
417
+ import { Fetcher } from '@ooneex/fetcher';
475
418
 
476
- class CustomFetcher implements IFetcher {
477
- // Implement all required methods
478
- }
479
- ```
419
+ const fetcher = new Fetcher('https://api.example.com')
420
+ .setBearerToken('your-token')
421
+ .setLang('en')
422
+ .setContentType('application/json');
480
423
 
481
- ## Error Handling
424
+ const response = await fetcher.post('/data', { key: 'value' });
425
+ ```
482
426
 
483
- The fetcher automatically handles various error scenarios:
427
+ ### Cloning for Different Contexts
484
428
 
485
429
  ```typescript
486
430
  import { Fetcher } from '@ooneex/fetcher';
487
431
 
488
- const api = new Fetcher('https://api.example.com');
432
+ const baseFetcher = new Fetcher('https://api.example.com');
489
433
 
490
- try {
491
- const response = await api.get('/users');
492
-
493
- if (response.isSuccessful) {
494
- // Handle successful response
495
- console.log('Data:', response.data);
496
- } else if (response.isClientError) {
497
- // Handle 4xx errors
498
- console.error('Client error:', response.message);
499
- } else if (response.isServerError) {
500
- // Handle 5xx errors
501
- console.error('Server error:', response.message);
502
- }
503
- } catch (error) {
504
- // Handle network errors or other exceptions
505
- console.error('Request failed:', error);
506
- }
507
- ```
434
+ // Create authenticated clone
435
+ const authFetcher = baseFetcher.clone();
436
+ authFetcher.setBearerToken('user-token');
508
437
 
509
- ## Advanced Features
438
+ // Create admin clone
439
+ const adminFetcher = baseFetcher.clone();
440
+ adminFetcher.setBearerToken('admin-token');
510
441
 
511
- ### URL Building
512
- The fetcher automatically handles URL building:
513
-
514
- ```typescript
515
- const api = new Fetcher('https://api.example.com');
516
-
517
- // These all work correctly
518
- await api.get('/users'); // -> https://api.example.com/users
519
- await api.get('users'); // -> https://api.example.com/users
520
- await api.get('https://other.com/api'); // -> https://other.com/api (absolute URL)
521
-
522
- // Base URL with trailing slash
523
- const api2 = new Fetcher('https://api.example.com/');
524
- await api2.get('/users'); // -> https://api.example.com/users
442
+ // Use independently
443
+ await authFetcher.get('/user/profile');
444
+ await adminFetcher.get('/admin/dashboard');
525
445
  ```
526
446
 
527
- ### Content Type Handling
528
- The fetcher automatically sets appropriate Content-Type headers:
447
+ ### Uploading Multiple Files
529
448
 
530
449
  ```typescript
531
- const api = new Fetcher('https://api.example.com');
532
-
533
- // Automatic JSON content type for objects
534
- await api.post('/users', { name: 'John' }); // Content-Type: application/json
535
-
536
- // FormData handling
537
- const formData = new FormData();
538
- formData.append('name', 'John');
539
- await api.post('/users', formData); // Content-Type: multipart/form-data
540
-
541
- // String data
542
- await api.post('/users', 'raw string data');
450
+ import { Fetcher } from '@ooneex/fetcher';
543
451
 
544
- // Blob/ArrayBuffer data
545
- const blob = new Blob(['data'], { type: 'text/plain' });
546
- await api.post('/upload', blob);
452
+ const fetcher = new Fetcher('https://api.example.com');
453
+
454
+ async function uploadFiles(files: File[]) {
455
+ const results = [];
456
+
457
+ for (const file of files) {
458
+ const response = await fetcher.upload<{ url: string }>(
459
+ '/upload',
460
+ file,
461
+ 'file'
462
+ );
463
+ results.push(response);
464
+ }
465
+
466
+ return results;
467
+ }
547
468
  ```
548
469
 
549
470
  ## License
550
471
 
551
- This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
472
+ This project is licensed under the MIT License - see the [LICENSE](./LICENSE) file for details.
552
473
 
553
474
  ## Contributing
554
475
 
package/dist/index.d.ts CHANGED
@@ -27,10 +27,10 @@ interface IFetcher {
27
27
  upload<T extends Record<string, unknown> = Record<string, unknown>>(path: string, file: File | Blob, name?: string): Promise<ResponseDataType<T>>;
28
28
  }
29
29
  declare class Fetcher implements IFetcher {
30
- private baseURL;
30
+ private baseURL?;
31
31
  private abortController;
32
32
  readonly header: Header2;
33
- constructor(baseURL: string);
33
+ constructor(baseURL?: string | undefined);
34
34
  setBearerToken(token: string): this;
35
35
  setBasicToken(token: string): this;
36
36
  clearBearerToken(): this;
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- import{Header as c}from"@ooneex/http-header";class T{baseURL;abortController;header=new c;constructor(e){this.baseURL=e;this.abortController=new AbortController}setBearerToken(e){return this.header.setBearerToken(e),this}setBasicToken(e){return this.header.setBasicAuth(e),this}clearBearerToken(){return this.header.remove("Authorization"),this}clearBasicToken(){return this.header.remove("Authorization"),this}setContentType(e){return this.header.contentType(e),this}setLang(e){return this.header.setLang(e),this}abort(){return this.abortController.abort(),this.abortController=new AbortController,this}clone(){return new T(this.baseURL)}async get(e){return this.request("GET",e)}async post(e,n){return this.request("POST",e,n)}async put(e,n){return this.request("PUT",e,n)}async patch(e,n){return this.request("PATCH",e,n)}async delete(e){return this.request("DELETE",e)}async head(e){return this.request("HEAD",e)}async options(e){return this.request("OPTIONS",e)}async request(e,n,r){let s=this.buildURL(n),o=this.buildRequestOptions(e,r),i=await fetch(s,o);try{return await i.json()}catch(t){throw Error(t instanceof Error?t.message:"Failed to parse JSON response")}}async upload(e,n,r="file"){let s=new FormData;s.append(r,n);let o=this.header.get("Content-Type");this.header.remove("Content-Type");let i=await this.request("POST",e,s);if(o)this.header.set("Content-Type",o);return i}buildURL(e){if(e.startsWith("http://")||e.startsWith("https://"))return e;let n=e.startsWith("/")?e:`/${e}`;return`${this.baseURL.endsWith("/")?this.baseURL.slice(0,-1):this.baseURL}${n}`}buildRequestOptions(e,n){let r=this.header.native,s;if(n!==void 0&&e!=="GET"&&e!=="HEAD"&&e!=="OPTIONS"){if(n instanceof FormData)s=n,this.header.clearContentType();else if(typeof n==="string")s=n;else if(n instanceof Blob||n instanceof ArrayBuffer)s=n;else if(s=JSON.stringify(n),!this.header.has("Content-Type"))this.header.setJson()}return{method:e,headers:r,...s!==void 0&&{body:s},signal:this.abortController.signal}}}export{T as Fetcher};
1
+ import{Header as c}from"@ooneex/http-header";class t{baseURL;abortController;header=new c;constructor(e){this.baseURL=e;this.abortController=new AbortController}setBearerToken(e){return this.header.setBearerToken(e),this}setBasicToken(e){return this.header.setBasicAuth(e),this}clearBearerToken(){return this.header.remove("Authorization"),this}clearBasicToken(){return this.header.remove("Authorization"),this}setContentType(e){return this.header.contentType(e),this}setLang(e){return this.header.setLang(e),this}abort(){return this.abortController.abort(),this.abortController=new AbortController,this}clone(){return new t(this.baseURL)}async get(e){return this.request("GET",e)}async post(e,n){return this.request("POST",e,n)}async put(e,n){return this.request("PUT",e,n)}async patch(e,n){return this.request("PATCH",e,n)}async delete(e){return this.request("DELETE",e)}async head(e){return this.request("HEAD",e)}async options(e){return this.request("OPTIONS",e)}async request(e,n,r){let s=this.buildURL(n),o=this.buildRequestOptions(e,r),i=await fetch(s,o);try{return await i.json()}catch(T){throw Error(T instanceof Error?T.message:"Failed to parse JSON response")}}async upload(e,n,r="file"){let s=new FormData;s.append(r,n);let o=this.header.get("Content-Type");this.header.remove("Content-Type");let i=await this.request("POST",e,s);if(o)this.header.set("Content-Type",o);return i}buildURL(e){if(e.startsWith("http://")||e.startsWith("https://"))return e;if(!this.baseURL)return e;let n=e.startsWith("/")?e:`/${e}`;return`${this.baseURL.endsWith("/")?this.baseURL.slice(0,-1):this.baseURL}${n}`}buildRequestOptions(e,n){let r=this.header.native,s;if(n!==void 0&&e!=="GET"&&e!=="HEAD"&&e!=="OPTIONS"){if(n instanceof FormData)s=n,this.header.clearContentType();else if(typeof n==="string")s=n;else if(n instanceof Blob||n instanceof ArrayBuffer)s=n;else if(s=JSON.stringify(n),!this.header.has("Content-Type"))this.header.setJson()}return{method:e,headers:r,...s!==void 0&&{body:s},signal:this.abortController.signal}}}export{t as Fetcher};
2
2
 
3
- //# debugId=8AF8D142203AB99D64756E2164756E21
3
+ //# debugId=FC0FC58E0FCC4CA964756E2164756E21
package/dist/index.js.map CHANGED
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["src/Fetcher.ts"],
4
4
  "sourcesContent": [
5
- "import { Header } from \"@ooneex/http-header\";\nimport type { MimeType } from \"@ooneex/http-mimes\";\nimport type { ResponseDataType } from \"@ooneex/http-response\";\nimport type { HttpMethodType } from \"@ooneex/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 return new Fetcher(this.baseURL);\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 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"
5
+ "import { Header } from \"@ooneex/http-header\";\nimport type { MimeType } from \"@ooneex/http-mimes\";\nimport type { ResponseDataType } from \"@ooneex/http-response\";\nimport type { HttpMethodType } from \"@ooneex/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
6
  ],
7
- "mappings": "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",
8
- "debugId": "8AF8D142203AB99D64756E2164756E21",
7
+ "mappings": "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",
8
+ "debugId": "FC0FC58E0FCC4CA964756E2164756E21",
9
9
  "names": []
10
10
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ooneex/fetcher",
3
- "description": "",
4
- "version": "0.0.1",
3
+ "description": "A lightweight HTTP client wrapper for making fetch requests with typed headers and response handling",
4
+ "version": "0.3.0",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist",
@@ -25,9 +25,7 @@
25
25
  "test": "bun test tests",
26
26
  "build": "bunup",
27
27
  "lint": "tsgo --noEmit && bunx biome lint",
28
- "publish:prod": "bun publish --tolerate-republish --access public",
29
- "publish:pack": "bun pm pack --destination ./dist",
30
- "publish:dry": "bun publish --dry-run"
28
+ "publish": "bun publish --access public || true"
31
29
  },
32
30
  "dependencies": {
33
31
  "@ooneex/http-header": "0.0.1"
@@ -36,5 +34,14 @@
36
34
  "@ooneex/http-response": "0.0.1",
37
35
  "@ooneex/http-mimes": "0.0.1",
38
36
  "@ooneex/types": "0.0.1"
39
- }
37
+ },
38
+ "keywords": [
39
+ "api-client",
40
+ "bun",
41
+ "fetch",
42
+ "fetcher",
43
+ "http-client",
44
+ "ooneex",
45
+ "typescript"
46
+ ]
40
47
  }
Binary file