@fgrzl/fetch 1.1.0-alpha.3 → 1.1.0-alpha.8
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 +15 -12
- package/dist/cjs/client/fetch-client.d.ts +189 -0
- package/dist/cjs/client/fetch-client.d.ts.map +1 -0
- package/dist/cjs/client/fetch-client.js +339 -0
- package/dist/cjs/client/fetch-client.js.map +1 -0
- package/dist/cjs/client/index.d.ts +11 -0
- package/dist/cjs/client/index.d.ts.map +1 -0
- package/dist/cjs/client/index.js +14 -0
- package/dist/cjs/client/index.js.map +1 -0
- package/dist/cjs/client/types.d.ts +63 -0
- package/dist/cjs/client/types.d.ts.map +1 -0
- package/dist/cjs/client/types.js +9 -0
- package/dist/cjs/client/types.js.map +1 -0
- package/dist/{errors.d.ts → cjs/errors/index.d.ts} +20 -3
- package/dist/cjs/errors/index.d.ts.map +1 -0
- package/dist/{errors.js → cjs/errors/index.js} +23 -3
- package/dist/cjs/errors/index.js.map +1 -0
- package/dist/cjs/index.d.ts +65 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +118 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/middleware/authentication/authentication.d.ts +31 -0
- package/dist/cjs/middleware/authentication/authentication.d.ts.map +1 -0
- package/dist/cjs/middleware/authentication/authentication.js +93 -0
- package/dist/cjs/middleware/authentication/authentication.js.map +1 -0
- package/dist/cjs/middleware/authentication/index.d.ts +37 -0
- package/dist/cjs/middleware/authentication/index.d.ts.map +1 -0
- package/dist/cjs/middleware/authentication/index.js +42 -0
- package/dist/cjs/middleware/authentication/index.js.map +1 -0
- package/dist/cjs/middleware/authentication/types.d.ts +73 -0
- package/dist/cjs/middleware/authentication/types.d.ts.map +1 -0
- package/dist/cjs/middleware/authentication/types.js +6 -0
- package/dist/cjs/middleware/authentication/types.js.map +1 -0
- package/dist/cjs/middleware/authorization/authorization.d.ts +30 -0
- package/dist/cjs/middleware/authorization/authorization.d.ts.map +1 -0
- package/dist/cjs/middleware/authorization/authorization.js +82 -0
- package/dist/cjs/middleware/authorization/authorization.js.map +1 -0
- package/dist/cjs/middleware/authorization/index.d.ts +36 -0
- package/dist/cjs/middleware/authorization/index.d.ts.map +1 -0
- package/dist/cjs/middleware/authorization/index.js +41 -0
- package/dist/cjs/middleware/authorization/index.js.map +1 -0
- package/dist/cjs/middleware/authorization/types.d.ts +67 -0
- package/dist/cjs/middleware/authorization/types.d.ts.map +1 -0
- package/dist/cjs/middleware/authorization/types.js +6 -0
- package/dist/cjs/middleware/authorization/types.js.map +1 -0
- package/dist/cjs/middleware/cache/cache.d.ts +41 -0
- package/dist/cjs/middleware/cache/cache.d.ts.map +1 -0
- package/dist/cjs/middleware/cache/cache.js +191 -0
- package/dist/cjs/middleware/cache/cache.js.map +1 -0
- package/dist/cjs/middleware/cache/index.d.ts +44 -0
- package/dist/cjs/middleware/cache/index.d.ts.map +1 -0
- package/dist/cjs/middleware/cache/index.js +50 -0
- package/dist/cjs/middleware/cache/index.js.map +1 -0
- package/dist/cjs/middleware/cache/types.d.ts +89 -0
- package/dist/cjs/middleware/cache/types.d.ts.map +1 -0
- package/dist/cjs/middleware/cache/types.js +6 -0
- package/dist/cjs/middleware/cache/types.js.map +1 -0
- package/dist/cjs/middleware/csrf/csrf.d.ts +34 -0
- package/dist/cjs/middleware/csrf/csrf.d.ts.map +1 -0
- package/dist/cjs/middleware/csrf/csrf.js +94 -0
- package/dist/cjs/middleware/csrf/csrf.js.map +1 -0
- package/dist/cjs/middleware/csrf/index.d.ts +57 -0
- package/dist/cjs/middleware/csrf/index.d.ts.map +1 -0
- package/dist/cjs/middleware/csrf/index.js +62 -0
- package/dist/cjs/middleware/csrf/index.js.map +1 -0
- package/dist/cjs/middleware/csrf/types.d.ts +57 -0
- package/dist/cjs/middleware/csrf/types.d.ts.map +1 -0
- package/dist/cjs/middleware/csrf/types.js +6 -0
- package/dist/cjs/middleware/csrf/types.js.map +1 -0
- package/dist/cjs/middleware/index.d.ts +115 -0
- package/dist/cjs/middleware/index.d.ts.map +1 -0
- package/dist/cjs/middleware/index.js +153 -0
- package/dist/cjs/middleware/index.js.map +1 -0
- package/dist/cjs/middleware/logging/index.d.ts +42 -0
- package/dist/cjs/middleware/logging/index.d.ts.map +1 -0
- package/dist/cjs/middleware/logging/index.js +47 -0
- package/dist/cjs/middleware/logging/index.js.map +1 -0
- package/dist/cjs/middleware/logging/logging.d.ts +29 -0
- package/dist/cjs/middleware/logging/logging.d.ts.map +1 -0
- package/dist/cjs/middleware/logging/logging.js +171 -0
- package/dist/cjs/middleware/logging/logging.js.map +1 -0
- package/dist/cjs/middleware/logging/types.d.ts +90 -0
- package/dist/cjs/middleware/logging/types.d.ts.map +1 -0
- package/dist/cjs/middleware/logging/types.js +6 -0
- package/dist/cjs/middleware/logging/types.js.map +1 -0
- package/dist/cjs/middleware/rate-limit/index.d.ts +16 -0
- package/dist/cjs/middleware/rate-limit/index.d.ts.map +1 -0
- package/dist/cjs/middleware/rate-limit/index.js +21 -0
- package/dist/cjs/middleware/rate-limit/index.js.map +1 -0
- package/dist/cjs/middleware/rate-limit/rate-limit.d.ts +14 -0
- package/dist/cjs/middleware/rate-limit/rate-limit.d.ts.map +1 -0
- package/dist/cjs/middleware/rate-limit/rate-limit.js +87 -0
- package/dist/cjs/middleware/rate-limit/rate-limit.js.map +1 -0
- package/dist/cjs/middleware/rate-limit/types.d.ts +97 -0
- package/dist/cjs/middleware/rate-limit/types.d.ts.map +1 -0
- package/dist/cjs/middleware/rate-limit/types.js +6 -0
- package/dist/cjs/middleware/rate-limit/types.js.map +1 -0
- package/dist/cjs/middleware/retry/index.d.ts +6 -0
- package/dist/cjs/middleware/retry/index.d.ts.map +1 -0
- package/dist/cjs/middleware/retry/index.js +11 -0
- package/dist/cjs/middleware/retry/index.js.map +1 -0
- package/dist/cjs/middleware/retry/retry.d.ts +39 -0
- package/dist/cjs/middleware/retry/retry.d.ts.map +1 -0
- package/dist/cjs/middleware/retry/retry.js +144 -0
- package/dist/cjs/middleware/retry/retry.js.map +1 -0
- package/dist/cjs/middleware/retry/types.d.ts +61 -0
- package/dist/cjs/middleware/retry/types.d.ts.map +1 -0
- package/dist/cjs/middleware/retry/types.js +6 -0
- package/dist/cjs/middleware/retry/types.js.map +1 -0
- package/dist/client/fetch-client.d.ts +189 -0
- package/dist/client/fetch-client.d.ts.map +1 -0
- package/dist/client/fetch-client.js +335 -0
- package/dist/client/fetch-client.js.map +1 -0
- package/dist/client/index.d.ts +11 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +10 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/types.d.ts +63 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/types.js +8 -0
- package/dist/client/types.js.map +1 -0
- package/dist/errors/index.d.ts +64 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +73 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/index.d.ts +49 -20
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +86 -42
- package/dist/index.js.map +1 -1
- package/dist/middleware/authentication/authentication.d.ts +31 -0
- package/dist/middleware/authentication/authentication.d.ts.map +1 -0
- package/dist/middleware/authentication/authentication.js +90 -0
- package/dist/middleware/authentication/authentication.js.map +1 -0
- package/dist/middleware/authentication/index.d.ts +37 -0
- package/dist/middleware/authentication/index.d.ts.map +1 -0
- package/dist/middleware/authentication/index.js +37 -0
- package/dist/middleware/authentication/index.js.map +1 -0
- package/dist/middleware/authentication/types.d.ts +73 -0
- package/dist/middleware/authentication/types.d.ts.map +1 -0
- package/dist/middleware/authentication/types.js +5 -0
- package/dist/middleware/authentication/types.js.map +1 -0
- package/dist/middleware/authorization/authorization.d.ts +30 -0
- package/dist/middleware/authorization/authorization.d.ts.map +1 -0
- package/dist/middleware/authorization/authorization.js +79 -0
- package/dist/middleware/authorization/authorization.js.map +1 -0
- package/dist/middleware/authorization/index.d.ts +36 -0
- package/dist/middleware/authorization/index.d.ts.map +1 -0
- package/dist/middleware/authorization/index.js +36 -0
- package/dist/middleware/authorization/index.js.map +1 -0
- package/dist/middleware/authorization/types.d.ts +67 -0
- package/dist/middleware/authorization/types.d.ts.map +1 -0
- package/dist/middleware/authorization/types.js +5 -0
- package/dist/middleware/authorization/types.js.map +1 -0
- package/dist/middleware/cache/cache.d.ts +41 -0
- package/dist/middleware/cache/cache.d.ts.map +1 -0
- package/dist/middleware/cache/cache.js +186 -0
- package/dist/middleware/cache/cache.js.map +1 -0
- package/dist/middleware/cache/index.d.ts +44 -0
- package/dist/middleware/cache/index.d.ts.map +1 -0
- package/dist/middleware/cache/index.js +44 -0
- package/dist/middleware/cache/index.js.map +1 -0
- package/dist/middleware/cache/types.d.ts +89 -0
- package/dist/middleware/cache/types.d.ts.map +1 -0
- package/dist/middleware/cache/types.js +5 -0
- package/dist/middleware/cache/types.js.map +1 -0
- package/dist/middleware/csrf/csrf.d.ts +34 -0
- package/dist/middleware/csrf/csrf.d.ts.map +1 -0
- package/dist/middleware/csrf/csrf.js +91 -0
- package/dist/middleware/csrf/csrf.js.map +1 -0
- package/dist/middleware/csrf/index.d.ts +57 -0
- package/dist/middleware/csrf/index.d.ts.map +1 -0
- package/dist/middleware/csrf/index.js +57 -0
- package/dist/middleware/csrf/index.js.map +1 -0
- package/dist/middleware/csrf/types.d.ts +57 -0
- package/dist/middleware/csrf/types.d.ts.map +1 -0
- package/dist/middleware/csrf/types.js +5 -0
- package/dist/middleware/csrf/types.js.map +1 -0
- package/dist/middleware/index.d.ts +115 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +134 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/middleware/logging/index.d.ts +42 -0
- package/dist/middleware/logging/index.d.ts.map +1 -0
- package/dist/middleware/logging/index.js +42 -0
- package/dist/middleware/logging/index.js.map +1 -0
- package/dist/middleware/logging/logging.d.ts +29 -0
- package/dist/middleware/logging/logging.d.ts.map +1 -0
- package/dist/middleware/logging/logging.js +168 -0
- package/dist/middleware/logging/logging.js.map +1 -0
- package/dist/middleware/logging/types.d.ts +90 -0
- package/dist/middleware/logging/types.d.ts.map +1 -0
- package/dist/middleware/logging/types.js +5 -0
- package/dist/middleware/logging/types.js.map +1 -0
- package/dist/middleware/rate-limit/index.d.ts +16 -0
- package/dist/middleware/rate-limit/index.d.ts.map +1 -0
- package/dist/middleware/rate-limit/index.js +16 -0
- package/dist/middleware/rate-limit/index.js.map +1 -0
- package/dist/middleware/rate-limit/rate-limit.d.ts +14 -0
- package/dist/middleware/rate-limit/rate-limit.d.ts.map +1 -0
- package/dist/middleware/rate-limit/rate-limit.js +84 -0
- package/dist/middleware/rate-limit/rate-limit.js.map +1 -0
- package/dist/middleware/rate-limit/types.d.ts +97 -0
- package/dist/middleware/rate-limit/types.d.ts.map +1 -0
- package/dist/middleware/rate-limit/types.js +5 -0
- package/dist/middleware/rate-limit/types.js.map +1 -0
- package/dist/middleware/retry/index.d.ts +6 -0
- package/dist/middleware/retry/index.d.ts.map +1 -0
- package/dist/middleware/retry/index.js +6 -0
- package/dist/middleware/retry/index.js.map +1 -0
- package/dist/middleware/retry/retry.d.ts +39 -0
- package/dist/middleware/retry/retry.d.ts.map +1 -0
- package/dist/middleware/retry/retry.js +141 -0
- package/dist/middleware/retry/retry.js.map +1 -0
- package/dist/middleware/retry/types.d.ts +61 -0
- package/dist/middleware/retry/types.d.ts.map +1 -0
- package/dist/middleware/retry/types.js +5 -0
- package/dist/middleware/retry/types.js.map +1 -0
- package/package.json +42 -8
- package/dist/client.d.ts +0 -133
- package/dist/client.js +0 -166
- package/dist/client.js.map +0 -1
- package/dist/csrf.d.ts +0 -32
- package/dist/csrf.js +0 -53
- package/dist/csrf.js.map +0 -1
- package/dist/errors.js.map +0 -1
- package/dist/test-utils.d.ts +0 -24
- package/dist/test-utils.js +0 -52
- package/dist/test-utils.js.map +0 -1
- package/dist/unauthorized.d.ts +0 -27
- package/dist/unauthorized.js +0 -41
- package/dist/unauthorized.js.map +0 -1
package/README.md
CHANGED
|
@@ -7,9 +7,11 @@ A lightweight, middleware-friendly fetch client for TypeScript projects.
|
|
|
7
7
|
|
|
8
8
|
## ✨ Features
|
|
9
9
|
|
|
10
|
+
- **Pit of Success Design**: Simple defaults that just work, customizable when needed
|
|
10
11
|
- Simple API: `api.get('/api/user')`
|
|
11
|
-
- Built-in CSRF token support
|
|
12
|
+
- Built-in CSRF token support (XSRF-TOKEN standard)
|
|
12
13
|
- Automatic 401 redirect handling
|
|
14
|
+
- Retry middleware with configurable strategies
|
|
13
15
|
- Custom middleware support (request/response)
|
|
14
16
|
- TypeScript-first, small and dependency-free
|
|
15
17
|
|
|
@@ -21,6 +23,8 @@ npm install @fgrzl/fetch
|
|
|
21
23
|
|
|
22
24
|
## 🚀 Quick Start
|
|
23
25
|
|
|
26
|
+
**Level 1: Just works with defaults**
|
|
27
|
+
|
|
24
28
|
```ts
|
|
25
29
|
import api from "@fgrzl/fetch";
|
|
26
30
|
|
|
@@ -32,26 +36,25 @@ if (response.ok) {
|
|
|
32
36
|
}
|
|
33
37
|
```
|
|
34
38
|
|
|
35
|
-
|
|
39
|
+
**Level 2: Custom configuration when needed**
|
|
36
40
|
|
|
37
41
|
```ts
|
|
38
|
-
import { FetchClient, useCSRF,
|
|
42
|
+
import { FetchClient, useCSRF, useAuthorization, useRetry } from "@fgrzl/fetch";
|
|
39
43
|
|
|
40
44
|
const client = new FetchClient({
|
|
41
45
|
credentials: "same-origin",
|
|
42
46
|
});
|
|
43
47
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
useUnauthorized(client, {
|
|
50
|
-
loginPath: "/login",
|
|
51
|
-
});
|
|
48
|
+
// Smart defaults - just works
|
|
49
|
+
useCSRF(client);
|
|
50
|
+
useAuthorization(client);
|
|
51
|
+
useRetry(client);
|
|
52
52
|
|
|
53
53
|
// All requests now return FetchResponse<T>
|
|
54
|
-
interface User {
|
|
54
|
+
interface User {
|
|
55
|
+
id: number;
|
|
56
|
+
name: string;
|
|
57
|
+
}
|
|
55
58
|
const userResponse = await client.get<User>("/api/user");
|
|
56
59
|
if (userResponse.ok) {
|
|
57
60
|
console.log(userResponse.data.name); // Typed access to data
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Enhanced fetch client with intercept middleware architecture.
|
|
3
|
+
*/
|
|
4
|
+
import type { FetchResponse, FetchClientOptions } from './types';
|
|
5
|
+
/**
|
|
6
|
+
* Intercept middleware type that allows full control over request/response cycle.
|
|
7
|
+
* Middleware can modify requests, handle responses, implement retries, etc.
|
|
8
|
+
*/
|
|
9
|
+
export type FetchMiddleware = (request: RequestInit & {
|
|
10
|
+
url?: string;
|
|
11
|
+
}, next: (modifiedRequest?: RequestInit & {
|
|
12
|
+
url?: string;
|
|
13
|
+
}) => Promise<FetchResponse<unknown>>) => Promise<FetchResponse<unknown>>;
|
|
14
|
+
/**
|
|
15
|
+
* Enhanced HTTP client with intercept middleware architecture.
|
|
16
|
+
*
|
|
17
|
+
* Features:
|
|
18
|
+
* - 🎯 Smart defaults (JSON content-type, same-origin credentials)
|
|
19
|
+
* - 🔧 Powerful middleware system for cross-cutting concerns
|
|
20
|
+
* - 🛡️ Consistent error handling (never throws, always returns response)
|
|
21
|
+
* - 📦 TypeScript-first with full type inference
|
|
22
|
+
* - 🚀 Modern async/await API
|
|
23
|
+
*
|
|
24
|
+
* @example Basic usage:
|
|
25
|
+
* ```typescript
|
|
26
|
+
* const client = new FetchClient();
|
|
27
|
+
*
|
|
28
|
+
* // GET request - just works
|
|
29
|
+
* const users = await client.get<User[]>('/api/users');
|
|
30
|
+
* if (users.ok) {
|
|
31
|
+
* console.log(users.data); // Type is User[]
|
|
32
|
+
* }
|
|
33
|
+
*
|
|
34
|
+
* // POST request - JSON by default
|
|
35
|
+
* const result = await client.post('/api/users', { name: 'John' });
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* @example With middleware:
|
|
39
|
+
* ```typescript
|
|
40
|
+
* const client = new FetchClient();
|
|
41
|
+
*
|
|
42
|
+
* // Add auth middleware
|
|
43
|
+
* client.use((request, next) => {
|
|
44
|
+
* request.headers = { ...request.headers, Authorization: 'Bearer token' };
|
|
45
|
+
* return next(request);
|
|
46
|
+
* });
|
|
47
|
+
*
|
|
48
|
+
* // Now all requests include auth
|
|
49
|
+
* const data = await client.get('/api/protected');
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export declare class FetchClient {
|
|
53
|
+
private middlewares;
|
|
54
|
+
private credentials;
|
|
55
|
+
constructor(config?: FetchClientOptions);
|
|
56
|
+
use(middleware: FetchMiddleware): this;
|
|
57
|
+
request<T = unknown>(url: string, init?: RequestInit): Promise<FetchResponse<T>>;
|
|
58
|
+
private coreFetch;
|
|
59
|
+
private parseResponse;
|
|
60
|
+
private buildUrlWithParams;
|
|
61
|
+
/**
|
|
62
|
+
* HEAD request with query parameter support.
|
|
63
|
+
*
|
|
64
|
+
* HEAD requests are used to retrieve metadata about a resource without downloading
|
|
65
|
+
* the response body. Useful for checking if a resource exists, getting content length,
|
|
66
|
+
* last modified date, etc.
|
|
67
|
+
*
|
|
68
|
+
* @template T - Expected response data type (will be null for HEAD requests)
|
|
69
|
+
* @param url - Request URL
|
|
70
|
+
* @param params - Query parameters to append to URL
|
|
71
|
+
* @returns Promise resolving to typed response (data will always be null)
|
|
72
|
+
*
|
|
73
|
+
* @example Check if resource exists:
|
|
74
|
+
* ```typescript
|
|
75
|
+
* const headResponse = await client.head('/api/large-file.zip');
|
|
76
|
+
* if (headResponse.ok) {
|
|
77
|
+
* const contentLength = headResponse.headers.get('content-length');
|
|
78
|
+
* const lastModified = headResponse.headers.get('last-modified');
|
|
79
|
+
* console.log(`File size: ${contentLength} bytes`);
|
|
80
|
+
* }
|
|
81
|
+
* ```
|
|
82
|
+
*
|
|
83
|
+
* @example Check with query parameters:
|
|
84
|
+
* ```typescript
|
|
85
|
+
* const exists = await client.head('/api/users', { id: 123 });
|
|
86
|
+
* if (exists.status === 404) {
|
|
87
|
+
* console.log('User not found');
|
|
88
|
+
* }
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
head<T = null>(url: string, params?: Record<string, string | number | boolean | undefined>): Promise<FetchResponse<T>>;
|
|
92
|
+
/**
|
|
93
|
+
* HEAD request that returns useful metadata about a resource.
|
|
94
|
+
*
|
|
95
|
+
* This is a convenience method that extracts common metadata from HEAD responses
|
|
96
|
+
* for easier consumption.
|
|
97
|
+
*
|
|
98
|
+
* @param url - Request URL
|
|
99
|
+
* @param params - Query parameters to append to URL
|
|
100
|
+
* @returns Promise resolving to response with extracted metadata
|
|
101
|
+
*
|
|
102
|
+
* @example Get resource metadata:
|
|
103
|
+
* ```typescript
|
|
104
|
+
* const metadata = await client.headMetadata('/api/large-file.zip');
|
|
105
|
+
* if (metadata.ok) {
|
|
106
|
+
* console.log('File exists:', metadata.exists);
|
|
107
|
+
* console.log('Content type:', metadata.contentType);
|
|
108
|
+
* console.log('Size:', metadata.contentLength, 'bytes');
|
|
109
|
+
* console.log('Last modified:', metadata.lastModified);
|
|
110
|
+
* }
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
headMetadata(url: string, params?: Record<string, string | number | boolean | undefined>): Promise<FetchResponse<null> & {
|
|
114
|
+
exists: boolean;
|
|
115
|
+
contentType: string | undefined;
|
|
116
|
+
contentLength: number | undefined;
|
|
117
|
+
lastModified: Date | undefined;
|
|
118
|
+
etag: string | undefined;
|
|
119
|
+
cacheControl: string | undefined;
|
|
120
|
+
}>;
|
|
121
|
+
/**
|
|
122
|
+
* GET request with query parameter support.
|
|
123
|
+
*
|
|
124
|
+
* @template T - Expected response data type
|
|
125
|
+
* @param url - Request URL
|
|
126
|
+
* @param params - Query parameters to append to URL
|
|
127
|
+
* @returns Promise resolving to typed response
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* ```typescript
|
|
131
|
+
* const users = await client.get<User[]>('/api/users');
|
|
132
|
+
* const filteredUsers = await client.get<User[]>('/api/users', { status: 'active', limit: 10 });
|
|
133
|
+
* if (users.ok) console.log(users.data);
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
get<T>(url: string, params?: Record<string, string | number | boolean | undefined>): Promise<FetchResponse<T>>;
|
|
137
|
+
/**
|
|
138
|
+
* POST request with automatic JSON serialization.
|
|
139
|
+
*
|
|
140
|
+
* @template T - Expected response data type
|
|
141
|
+
* @param url - Request URL
|
|
142
|
+
* @param body - Request body (auto-serialized to JSON)
|
|
143
|
+
* @param headers - Additional headers (Content-Type: application/json is default)
|
|
144
|
+
* @returns Promise resolving to typed response
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```typescript
|
|
148
|
+
* const result = await client.post<User>('/api/users', { name: 'John' });
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
post<T>(url: string, body?: unknown, headers?: Record<string, string>): Promise<FetchResponse<T>>;
|
|
152
|
+
/**
|
|
153
|
+
* PUT request with automatic JSON serialization.
|
|
154
|
+
*
|
|
155
|
+
* @template T - Expected response data type
|
|
156
|
+
* @param url - Request URL
|
|
157
|
+
* @param body - Request body (auto-serialized to JSON)
|
|
158
|
+
* @param headers - Additional headers (Content-Type: application/json is default)
|
|
159
|
+
* @returns Promise resolving to typed response
|
|
160
|
+
*/
|
|
161
|
+
put<T>(url: string, body?: unknown, headers?: Record<string, string>): Promise<FetchResponse<T>>;
|
|
162
|
+
/**
|
|
163
|
+
* PATCH request with automatic JSON serialization.
|
|
164
|
+
*
|
|
165
|
+
* @template T - Expected response data type
|
|
166
|
+
* @param url - Request URL
|
|
167
|
+
* @param body - Request body (auto-serialized to JSON)
|
|
168
|
+
* @param headers - Additional headers (Content-Type: application/json is default)
|
|
169
|
+
* @returns Promise resolving to typed response
|
|
170
|
+
*/
|
|
171
|
+
patch<T>(url: string, body?: unknown, headers?: Record<string, string>): Promise<FetchResponse<T>>;
|
|
172
|
+
/**
|
|
173
|
+
* DELETE request with query parameter support.
|
|
174
|
+
*
|
|
175
|
+
* @template T - Expected response data type
|
|
176
|
+
* @param url - Request URL
|
|
177
|
+
* @param params - Query parameters to append to URL
|
|
178
|
+
* @returns Promise resolving to typed response
|
|
179
|
+
*
|
|
180
|
+
* @example
|
|
181
|
+
* ```typescript
|
|
182
|
+
* const result = await client.del('/api/users/123');
|
|
183
|
+
* const bulkResult = await client.del('/api/users', { status: 'inactive', force: true });
|
|
184
|
+
* if (result.ok) console.log('Deleted successfully');
|
|
185
|
+
* ```
|
|
186
|
+
*/
|
|
187
|
+
del<T>(url: string, params?: Record<string, string | number | boolean | undefined>): Promise<FetchResponse<T>>;
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=fetch-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch-client.d.ts","sourceRoot":"","sources":["../../../src/client/fetch-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview Enhanced fetch client with intercept middleware architecture.
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.FetchClient = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* Enhanced HTTP client with intercept middleware architecture.
|
|
9
|
+
*
|
|
10
|
+
* Features:
|
|
11
|
+
* - 🎯 Smart defaults (JSON content-type, same-origin credentials)
|
|
12
|
+
* - 🔧 Powerful middleware system for cross-cutting concerns
|
|
13
|
+
* - 🛡️ Consistent error handling (never throws, always returns response)
|
|
14
|
+
* - 📦 TypeScript-first with full type inference
|
|
15
|
+
* - 🚀 Modern async/await API
|
|
16
|
+
*
|
|
17
|
+
* @example Basic usage:
|
|
18
|
+
* ```typescript
|
|
19
|
+
* const client = new FetchClient();
|
|
20
|
+
*
|
|
21
|
+
* // GET request - just works
|
|
22
|
+
* const users = await client.get<User[]>('/api/users');
|
|
23
|
+
* if (users.ok) {
|
|
24
|
+
* console.log(users.data); // Type is User[]
|
|
25
|
+
* }
|
|
26
|
+
*
|
|
27
|
+
* // POST request - JSON by default
|
|
28
|
+
* const result = await client.post('/api/users', { name: 'John' });
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @example With middleware:
|
|
32
|
+
* ```typescript
|
|
33
|
+
* const client = new FetchClient();
|
|
34
|
+
*
|
|
35
|
+
* // Add auth middleware
|
|
36
|
+
* client.use((request, next) => {
|
|
37
|
+
* request.headers = { ...request.headers, Authorization: 'Bearer token' };
|
|
38
|
+
* return next(request);
|
|
39
|
+
* });
|
|
40
|
+
*
|
|
41
|
+
* // Now all requests include auth
|
|
42
|
+
* const data = await client.get('/api/protected');
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
class FetchClient {
|
|
46
|
+
constructor(config = {}) {
|
|
47
|
+
this.middlewares = [];
|
|
48
|
+
this.credentials = config.credentials ?? 'same-origin';
|
|
49
|
+
}
|
|
50
|
+
use(middleware) {
|
|
51
|
+
this.middlewares.push(middleware);
|
|
52
|
+
return this;
|
|
53
|
+
}
|
|
54
|
+
async request(url, init = {}) {
|
|
55
|
+
// Create the execution chain
|
|
56
|
+
let index = 0;
|
|
57
|
+
const execute = async (request) => {
|
|
58
|
+
// Use provided request or fall back to original
|
|
59
|
+
const currentRequest = request || { ...init, url };
|
|
60
|
+
const currentUrl = currentRequest.url || url;
|
|
61
|
+
if (index >= this.middlewares.length) {
|
|
62
|
+
// Core fetch - end of middleware chain
|
|
63
|
+
const { url: _, ...requestInit } = currentRequest; // Remove url from request init
|
|
64
|
+
return this.coreFetch(requestInit, currentUrl);
|
|
65
|
+
}
|
|
66
|
+
const middleware = this.middlewares[index++];
|
|
67
|
+
if (!middleware) {
|
|
68
|
+
const { url: _, ...requestInit } = currentRequest;
|
|
69
|
+
return this.coreFetch(requestInit, currentUrl);
|
|
70
|
+
}
|
|
71
|
+
return middleware(currentRequest, execute);
|
|
72
|
+
};
|
|
73
|
+
const result = await execute();
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
async coreFetch(request, url) {
|
|
77
|
+
try {
|
|
78
|
+
const finalInit = {
|
|
79
|
+
credentials: this.credentials,
|
|
80
|
+
...request,
|
|
81
|
+
};
|
|
82
|
+
// Convert Headers object to plain object for better compatibility
|
|
83
|
+
if (finalInit.headers instanceof Headers) {
|
|
84
|
+
const headersObj = {};
|
|
85
|
+
finalInit.headers.forEach((value, key) => {
|
|
86
|
+
headersObj[key] = value;
|
|
87
|
+
});
|
|
88
|
+
finalInit.headers = headersObj;
|
|
89
|
+
}
|
|
90
|
+
const response = await fetch(url, finalInit);
|
|
91
|
+
const data = await this.parseResponse(response);
|
|
92
|
+
return {
|
|
93
|
+
data: response.ok ? data : null,
|
|
94
|
+
status: response.status,
|
|
95
|
+
statusText: response.statusText,
|
|
96
|
+
headers: response.headers,
|
|
97
|
+
url: response.url,
|
|
98
|
+
ok: response.ok,
|
|
99
|
+
...(response.ok
|
|
100
|
+
? {}
|
|
101
|
+
: {
|
|
102
|
+
error: {
|
|
103
|
+
message: response.statusText,
|
|
104
|
+
body: data,
|
|
105
|
+
},
|
|
106
|
+
}),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
if (error instanceof TypeError && error.message.includes('fetch')) {
|
|
111
|
+
return {
|
|
112
|
+
data: null,
|
|
113
|
+
status: 0,
|
|
114
|
+
statusText: 'Network Error',
|
|
115
|
+
headers: new Headers(),
|
|
116
|
+
url,
|
|
117
|
+
ok: false,
|
|
118
|
+
error: {
|
|
119
|
+
message: 'Failed to fetch',
|
|
120
|
+
body: error,
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
throw error;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
async parseResponse(res) {
|
|
128
|
+
const contentType = res.headers.get('content-type') || '';
|
|
129
|
+
if (contentType.includes('application/json')) {
|
|
130
|
+
return res.json();
|
|
131
|
+
}
|
|
132
|
+
if (contentType.includes('text/')) {
|
|
133
|
+
return res.text();
|
|
134
|
+
}
|
|
135
|
+
if (contentType.includes('application/octet-stream') ||
|
|
136
|
+
contentType.includes('image/') ||
|
|
137
|
+
contentType.includes('video/') ||
|
|
138
|
+
contentType.includes('audio/')) {
|
|
139
|
+
return res.blob();
|
|
140
|
+
}
|
|
141
|
+
if (res.body) {
|
|
142
|
+
const text = await res.text();
|
|
143
|
+
return text || null;
|
|
144
|
+
}
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
// Helper method to build URL with query parameters
|
|
148
|
+
buildUrlWithParams(url, params) {
|
|
149
|
+
if (!params) {
|
|
150
|
+
return url;
|
|
151
|
+
}
|
|
152
|
+
const urlObj = new URL(url, url.startsWith('http') ? undefined : 'http://localhost');
|
|
153
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
154
|
+
if (value !== undefined && value !== null) {
|
|
155
|
+
urlObj.searchParams.set(key, String(value));
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
// If the original URL was relative, return just the pathname + search
|
|
159
|
+
if (!url.startsWith('http')) {
|
|
160
|
+
return urlObj.pathname + urlObj.search;
|
|
161
|
+
}
|
|
162
|
+
return urlObj.toString();
|
|
163
|
+
}
|
|
164
|
+
// 🎯 PIT OF SUCCESS: Convenience methods with smart defaults
|
|
165
|
+
/**
|
|
166
|
+
* HEAD request with query parameter support.
|
|
167
|
+
*
|
|
168
|
+
* HEAD requests are used to retrieve metadata about a resource without downloading
|
|
169
|
+
* the response body. Useful for checking if a resource exists, getting content length,
|
|
170
|
+
* last modified date, etc.
|
|
171
|
+
*
|
|
172
|
+
* @template T - Expected response data type (will be null for HEAD requests)
|
|
173
|
+
* @param url - Request URL
|
|
174
|
+
* @param params - Query parameters to append to URL
|
|
175
|
+
* @returns Promise resolving to typed response (data will always be null)
|
|
176
|
+
*
|
|
177
|
+
* @example Check if resource exists:
|
|
178
|
+
* ```typescript
|
|
179
|
+
* const headResponse = await client.head('/api/large-file.zip');
|
|
180
|
+
* if (headResponse.ok) {
|
|
181
|
+
* const contentLength = headResponse.headers.get('content-length');
|
|
182
|
+
* const lastModified = headResponse.headers.get('last-modified');
|
|
183
|
+
* console.log(`File size: ${contentLength} bytes`);
|
|
184
|
+
* }
|
|
185
|
+
* ```
|
|
186
|
+
*
|
|
187
|
+
* @example Check with query parameters:
|
|
188
|
+
* ```typescript
|
|
189
|
+
* const exists = await client.head('/api/users', { id: 123 });
|
|
190
|
+
* if (exists.status === 404) {
|
|
191
|
+
* console.log('User not found');
|
|
192
|
+
* }
|
|
193
|
+
* ```
|
|
194
|
+
*/
|
|
195
|
+
head(url, params) {
|
|
196
|
+
const finalUrl = this.buildUrlWithParams(url, params);
|
|
197
|
+
return this.request(finalUrl, { method: 'HEAD' });
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* HEAD request that returns useful metadata about a resource.
|
|
201
|
+
*
|
|
202
|
+
* This is a convenience method that extracts common metadata from HEAD responses
|
|
203
|
+
* for easier consumption.
|
|
204
|
+
*
|
|
205
|
+
* @param url - Request URL
|
|
206
|
+
* @param params - Query parameters to append to URL
|
|
207
|
+
* @returns Promise resolving to response with extracted metadata
|
|
208
|
+
*
|
|
209
|
+
* @example Get resource metadata:
|
|
210
|
+
* ```typescript
|
|
211
|
+
* const metadata = await client.headMetadata('/api/large-file.zip');
|
|
212
|
+
* if (metadata.ok) {
|
|
213
|
+
* console.log('File exists:', metadata.exists);
|
|
214
|
+
* console.log('Content type:', metadata.contentType);
|
|
215
|
+
* console.log('Size:', metadata.contentLength, 'bytes');
|
|
216
|
+
* console.log('Last modified:', metadata.lastModified);
|
|
217
|
+
* }
|
|
218
|
+
* ```
|
|
219
|
+
*/
|
|
220
|
+
async headMetadata(url, params) {
|
|
221
|
+
const response = await this.head(url, params);
|
|
222
|
+
const contentLengthHeader = response.headers.get('content-length');
|
|
223
|
+
const lastModifiedHeader = response.headers.get('last-modified');
|
|
224
|
+
return {
|
|
225
|
+
...response,
|
|
226
|
+
exists: response.ok,
|
|
227
|
+
contentType: response.headers.get('content-type') || undefined,
|
|
228
|
+
contentLength: contentLengthHeader ? parseInt(contentLengthHeader, 10) : undefined,
|
|
229
|
+
lastModified: lastModifiedHeader ? new Date(lastModifiedHeader) : undefined,
|
|
230
|
+
etag: response.headers.get('etag') || undefined,
|
|
231
|
+
cacheControl: response.headers.get('cache-control') || undefined,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* GET request with query parameter support.
|
|
236
|
+
*
|
|
237
|
+
* @template T - Expected response data type
|
|
238
|
+
* @param url - Request URL
|
|
239
|
+
* @param params - Query parameters to append to URL
|
|
240
|
+
* @returns Promise resolving to typed response
|
|
241
|
+
*
|
|
242
|
+
* @example
|
|
243
|
+
* ```typescript
|
|
244
|
+
* const users = await client.get<User[]>('/api/users');
|
|
245
|
+
* const filteredUsers = await client.get<User[]>('/api/users', { status: 'active', limit: 10 });
|
|
246
|
+
* if (users.ok) console.log(users.data);
|
|
247
|
+
* ```
|
|
248
|
+
*/
|
|
249
|
+
get(url, params) {
|
|
250
|
+
const finalUrl = this.buildUrlWithParams(url, params);
|
|
251
|
+
return this.request(finalUrl, { method: 'GET' });
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* POST request with automatic JSON serialization.
|
|
255
|
+
*
|
|
256
|
+
* @template T - Expected response data type
|
|
257
|
+
* @param url - Request URL
|
|
258
|
+
* @param body - Request body (auto-serialized to JSON)
|
|
259
|
+
* @param headers - Additional headers (Content-Type: application/json is default)
|
|
260
|
+
* @returns Promise resolving to typed response
|
|
261
|
+
*
|
|
262
|
+
* @example
|
|
263
|
+
* ```typescript
|
|
264
|
+
* const result = await client.post<User>('/api/users', { name: 'John' });
|
|
265
|
+
* ```
|
|
266
|
+
*/
|
|
267
|
+
post(url, body, headers) {
|
|
268
|
+
const requestHeaders = {
|
|
269
|
+
'Content-Type': 'application/json',
|
|
270
|
+
...(headers ?? {}),
|
|
271
|
+
};
|
|
272
|
+
return this.request(url, {
|
|
273
|
+
method: 'POST',
|
|
274
|
+
headers: requestHeaders,
|
|
275
|
+
...(body !== undefined ? { body: JSON.stringify(body) } : {}),
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* PUT request with automatic JSON serialization.
|
|
280
|
+
*
|
|
281
|
+
* @template T - Expected response data type
|
|
282
|
+
* @param url - Request URL
|
|
283
|
+
* @param body - Request body (auto-serialized to JSON)
|
|
284
|
+
* @param headers - Additional headers (Content-Type: application/json is default)
|
|
285
|
+
* @returns Promise resolving to typed response
|
|
286
|
+
*/
|
|
287
|
+
put(url, body, headers) {
|
|
288
|
+
const requestHeaders = {
|
|
289
|
+
'Content-Type': 'application/json',
|
|
290
|
+
...(headers ?? {}),
|
|
291
|
+
};
|
|
292
|
+
return this.request(url, {
|
|
293
|
+
method: 'PUT',
|
|
294
|
+
headers: requestHeaders,
|
|
295
|
+
...(body !== undefined ? { body: JSON.stringify(body) } : {}),
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* PATCH request with automatic JSON serialization.
|
|
300
|
+
*
|
|
301
|
+
* @template T - Expected response data type
|
|
302
|
+
* @param url - Request URL
|
|
303
|
+
* @param body - Request body (auto-serialized to JSON)
|
|
304
|
+
* @param headers - Additional headers (Content-Type: application/json is default)
|
|
305
|
+
* @returns Promise resolving to typed response
|
|
306
|
+
*/
|
|
307
|
+
patch(url, body, headers) {
|
|
308
|
+
const requestHeaders = {
|
|
309
|
+
'Content-Type': 'application/json',
|
|
310
|
+
...(headers ?? {}),
|
|
311
|
+
};
|
|
312
|
+
return this.request(url, {
|
|
313
|
+
method: 'PATCH',
|
|
314
|
+
headers: requestHeaders,
|
|
315
|
+
...(body !== undefined ? { body: JSON.stringify(body) } : {}),
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* DELETE request with query parameter support.
|
|
320
|
+
*
|
|
321
|
+
* @template T - Expected response data type
|
|
322
|
+
* @param url - Request URL
|
|
323
|
+
* @param params - Query parameters to append to URL
|
|
324
|
+
* @returns Promise resolving to typed response
|
|
325
|
+
*
|
|
326
|
+
* @example
|
|
327
|
+
* ```typescript
|
|
328
|
+
* const result = await client.del('/api/users/123');
|
|
329
|
+
* const bulkResult = await client.del('/api/users', { status: 'inactive', force: true });
|
|
330
|
+
* if (result.ok) console.log('Deleted successfully');
|
|
331
|
+
* ```
|
|
332
|
+
*/
|
|
333
|
+
del(url, params) {
|
|
334
|
+
const finalUrl = this.buildUrlWithParams(url, params);
|
|
335
|
+
return this.request(finalUrl, { method: 'DELETE' });
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
exports.FetchClient = FetchClient;
|
|
339
|
+
//# sourceMappingURL=fetch-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch-client.js","sourceRoot":"","sources":["../../../src/client/fetch-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Client module exports - "Pit of Success" design.
|
|
3
|
+
*
|
|
4
|
+
* This module provides a clean, discoverable API:
|
|
5
|
+
* 🎯 Level 1: FetchClient class (what 90% of users need)
|
|
6
|
+
* 🎯 Level 2: Types for TypeScript users (auto-discovered via IntelliSense)
|
|
7
|
+
*/
|
|
8
|
+
export { FetchClient } from './fetch-client';
|
|
9
|
+
export type { FetchMiddleware } from './fetch-client';
|
|
10
|
+
export type { FetchResponse, FetchClientOptions } from './types';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG7C,YAAY,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACtD,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview Client module exports - "Pit of Success" design.
|
|
4
|
+
*
|
|
5
|
+
* This module provides a clean, discoverable API:
|
|
6
|
+
* 🎯 Level 1: FetchClient class (what 90% of users need)
|
|
7
|
+
* 🎯 Level 2: Types for TypeScript users (auto-discovered via IntelliSense)
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.FetchClient = void 0;
|
|
11
|
+
// 🎯 LEVEL 1: Main client class - the "pit of success" entry point
|
|
12
|
+
var fetch_client_1 = require("./fetch-client");
|
|
13
|
+
Object.defineProperty(exports, "FetchClient", { enumerable: true, get: function () { return fetch_client_1.FetchClient; } });
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAEH,mEAAmE;AACnE,+CAA6C;AAApC,2GAAA,WAAW,OAAA"}
|