@fgrzl/fetch 1.1.0-alpha.7 → 1.1.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.
Files changed (224) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/CONTRIBUTING.md +327 -0
  3. package/README.md +50 -21
  4. package/dist/cjs/index.js +1110 -105
  5. package/dist/cjs/index.js.map +1 -1
  6. package/dist/cjs/index.min.js +2 -0
  7. package/dist/cjs/index.min.js.map +1 -0
  8. package/dist/index.d.ts +1381 -10
  9. package/dist/index.js +1066 -91
  10. package/dist/index.js.map +1 -1
  11. package/dist/index.min.js +2 -0
  12. package/dist/index.min.js.map +1 -0
  13. package/package.json +14 -5
  14. package/dist/cjs/client/fetch-client.d.ts +0 -189
  15. package/dist/cjs/client/fetch-client.d.ts.map +0 -1
  16. package/dist/cjs/client/fetch-client.js +0 -339
  17. package/dist/cjs/client/fetch-client.js.map +0 -1
  18. package/dist/cjs/client/index.d.ts +0 -11
  19. package/dist/cjs/client/index.d.ts.map +0 -1
  20. package/dist/cjs/client/index.js +0 -14
  21. package/dist/cjs/client/index.js.map +0 -1
  22. package/dist/cjs/client/types.d.ts +0 -63
  23. package/dist/cjs/client/types.d.ts.map +0 -1
  24. package/dist/cjs/client/types.js +0 -9
  25. package/dist/cjs/client/types.js.map +0 -1
  26. package/dist/cjs/errors/index.d.ts +0 -64
  27. package/dist/cjs/errors/index.d.ts.map +0 -1
  28. package/dist/cjs/errors/index.js +0 -79
  29. package/dist/cjs/errors/index.js.map +0 -1
  30. package/dist/cjs/index.d.ts +0 -65
  31. package/dist/cjs/index.d.ts.map +0 -1
  32. package/dist/cjs/middleware/authentication/authentication.d.ts +0 -31
  33. package/dist/cjs/middleware/authentication/authentication.d.ts.map +0 -1
  34. package/dist/cjs/middleware/authentication/authentication.js +0 -93
  35. package/dist/cjs/middleware/authentication/authentication.js.map +0 -1
  36. package/dist/cjs/middleware/authentication/index.d.ts +0 -37
  37. package/dist/cjs/middleware/authentication/index.d.ts.map +0 -1
  38. package/dist/cjs/middleware/authentication/index.js +0 -42
  39. package/dist/cjs/middleware/authentication/index.js.map +0 -1
  40. package/dist/cjs/middleware/authentication/types.d.ts +0 -73
  41. package/dist/cjs/middleware/authentication/types.d.ts.map +0 -1
  42. package/dist/cjs/middleware/authentication/types.js +0 -6
  43. package/dist/cjs/middleware/authentication/types.js.map +0 -1
  44. package/dist/cjs/middleware/authorization/authorization.d.ts +0 -30
  45. package/dist/cjs/middleware/authorization/authorization.d.ts.map +0 -1
  46. package/dist/cjs/middleware/authorization/authorization.js +0 -82
  47. package/dist/cjs/middleware/authorization/authorization.js.map +0 -1
  48. package/dist/cjs/middleware/authorization/index.d.ts +0 -36
  49. package/dist/cjs/middleware/authorization/index.d.ts.map +0 -1
  50. package/dist/cjs/middleware/authorization/index.js +0 -41
  51. package/dist/cjs/middleware/authorization/index.js.map +0 -1
  52. package/dist/cjs/middleware/authorization/types.d.ts +0 -67
  53. package/dist/cjs/middleware/authorization/types.d.ts.map +0 -1
  54. package/dist/cjs/middleware/authorization/types.js +0 -6
  55. package/dist/cjs/middleware/authorization/types.js.map +0 -1
  56. package/dist/cjs/middleware/cache/cache.d.ts +0 -41
  57. package/dist/cjs/middleware/cache/cache.d.ts.map +0 -1
  58. package/dist/cjs/middleware/cache/cache.js +0 -191
  59. package/dist/cjs/middleware/cache/cache.js.map +0 -1
  60. package/dist/cjs/middleware/cache/index.d.ts +0 -44
  61. package/dist/cjs/middleware/cache/index.d.ts.map +0 -1
  62. package/dist/cjs/middleware/cache/index.js +0 -50
  63. package/dist/cjs/middleware/cache/index.js.map +0 -1
  64. package/dist/cjs/middleware/cache/types.d.ts +0 -89
  65. package/dist/cjs/middleware/cache/types.d.ts.map +0 -1
  66. package/dist/cjs/middleware/cache/types.js +0 -6
  67. package/dist/cjs/middleware/cache/types.js.map +0 -1
  68. package/dist/cjs/middleware/csrf/csrf.d.ts +0 -34
  69. package/dist/cjs/middleware/csrf/csrf.d.ts.map +0 -1
  70. package/dist/cjs/middleware/csrf/csrf.js +0 -94
  71. package/dist/cjs/middleware/csrf/csrf.js.map +0 -1
  72. package/dist/cjs/middleware/csrf/index.d.ts +0 -57
  73. package/dist/cjs/middleware/csrf/index.d.ts.map +0 -1
  74. package/dist/cjs/middleware/csrf/index.js +0 -62
  75. package/dist/cjs/middleware/csrf/index.js.map +0 -1
  76. package/dist/cjs/middleware/csrf/types.d.ts +0 -57
  77. package/dist/cjs/middleware/csrf/types.d.ts.map +0 -1
  78. package/dist/cjs/middleware/csrf/types.js +0 -6
  79. package/dist/cjs/middleware/csrf/types.js.map +0 -1
  80. package/dist/cjs/middleware/index.d.ts +0 -115
  81. package/dist/cjs/middleware/index.d.ts.map +0 -1
  82. package/dist/cjs/middleware/index.js +0 -153
  83. package/dist/cjs/middleware/index.js.map +0 -1
  84. package/dist/cjs/middleware/logging/index.d.ts +0 -42
  85. package/dist/cjs/middleware/logging/index.d.ts.map +0 -1
  86. package/dist/cjs/middleware/logging/index.js +0 -47
  87. package/dist/cjs/middleware/logging/index.js.map +0 -1
  88. package/dist/cjs/middleware/logging/logging.d.ts +0 -29
  89. package/dist/cjs/middleware/logging/logging.d.ts.map +0 -1
  90. package/dist/cjs/middleware/logging/logging.js +0 -171
  91. package/dist/cjs/middleware/logging/logging.js.map +0 -1
  92. package/dist/cjs/middleware/logging/types.d.ts +0 -90
  93. package/dist/cjs/middleware/logging/types.d.ts.map +0 -1
  94. package/dist/cjs/middleware/logging/types.js +0 -6
  95. package/dist/cjs/middleware/logging/types.js.map +0 -1
  96. package/dist/cjs/middleware/rate-limit/index.d.ts +0 -16
  97. package/dist/cjs/middleware/rate-limit/index.d.ts.map +0 -1
  98. package/dist/cjs/middleware/rate-limit/index.js +0 -21
  99. package/dist/cjs/middleware/rate-limit/index.js.map +0 -1
  100. package/dist/cjs/middleware/rate-limit/rate-limit.d.ts +0 -14
  101. package/dist/cjs/middleware/rate-limit/rate-limit.d.ts.map +0 -1
  102. package/dist/cjs/middleware/rate-limit/rate-limit.js +0 -87
  103. package/dist/cjs/middleware/rate-limit/rate-limit.js.map +0 -1
  104. package/dist/cjs/middleware/rate-limit/types.d.ts +0 -97
  105. package/dist/cjs/middleware/rate-limit/types.d.ts.map +0 -1
  106. package/dist/cjs/middleware/rate-limit/types.js +0 -6
  107. package/dist/cjs/middleware/rate-limit/types.js.map +0 -1
  108. package/dist/cjs/middleware/retry/index.d.ts +0 -6
  109. package/dist/cjs/middleware/retry/index.d.ts.map +0 -1
  110. package/dist/cjs/middleware/retry/index.js +0 -11
  111. package/dist/cjs/middleware/retry/index.js.map +0 -1
  112. package/dist/cjs/middleware/retry/retry.d.ts +0 -39
  113. package/dist/cjs/middleware/retry/retry.d.ts.map +0 -1
  114. package/dist/cjs/middleware/retry/retry.js +0 -144
  115. package/dist/cjs/middleware/retry/retry.js.map +0 -1
  116. package/dist/cjs/middleware/retry/types.d.ts +0 -61
  117. package/dist/cjs/middleware/retry/types.d.ts.map +0 -1
  118. package/dist/cjs/middleware/retry/types.js +0 -6
  119. package/dist/cjs/middleware/retry/types.js.map +0 -1
  120. package/dist/client/fetch-client.d.ts +0 -189
  121. package/dist/client/fetch-client.d.ts.map +0 -1
  122. package/dist/client/fetch-client.js +0 -335
  123. package/dist/client/fetch-client.js.map +0 -1
  124. package/dist/client/index.d.ts +0 -11
  125. package/dist/client/index.d.ts.map +0 -1
  126. package/dist/client/index.js +0 -10
  127. package/dist/client/index.js.map +0 -1
  128. package/dist/client/types.d.ts +0 -63
  129. package/dist/client/types.d.ts.map +0 -1
  130. package/dist/client/types.js +0 -8
  131. package/dist/client/types.js.map +0 -1
  132. package/dist/errors/index.d.ts +0 -64
  133. package/dist/errors/index.d.ts.map +0 -1
  134. package/dist/errors/index.js +0 -73
  135. package/dist/errors/index.js.map +0 -1
  136. package/dist/index.d.ts.map +0 -1
  137. package/dist/middleware/authentication/authentication.d.ts +0 -31
  138. package/dist/middleware/authentication/authentication.d.ts.map +0 -1
  139. package/dist/middleware/authentication/authentication.js +0 -90
  140. package/dist/middleware/authentication/authentication.js.map +0 -1
  141. package/dist/middleware/authentication/index.d.ts +0 -37
  142. package/dist/middleware/authentication/index.d.ts.map +0 -1
  143. package/dist/middleware/authentication/index.js +0 -37
  144. package/dist/middleware/authentication/index.js.map +0 -1
  145. package/dist/middleware/authentication/types.d.ts +0 -73
  146. package/dist/middleware/authentication/types.d.ts.map +0 -1
  147. package/dist/middleware/authentication/types.js +0 -5
  148. package/dist/middleware/authentication/types.js.map +0 -1
  149. package/dist/middleware/authorization/authorization.d.ts +0 -30
  150. package/dist/middleware/authorization/authorization.d.ts.map +0 -1
  151. package/dist/middleware/authorization/authorization.js +0 -79
  152. package/dist/middleware/authorization/authorization.js.map +0 -1
  153. package/dist/middleware/authorization/index.d.ts +0 -36
  154. package/dist/middleware/authorization/index.d.ts.map +0 -1
  155. package/dist/middleware/authorization/index.js +0 -36
  156. package/dist/middleware/authorization/index.js.map +0 -1
  157. package/dist/middleware/authorization/types.d.ts +0 -67
  158. package/dist/middleware/authorization/types.d.ts.map +0 -1
  159. package/dist/middleware/authorization/types.js +0 -5
  160. package/dist/middleware/authorization/types.js.map +0 -1
  161. package/dist/middleware/cache/cache.d.ts +0 -41
  162. package/dist/middleware/cache/cache.d.ts.map +0 -1
  163. package/dist/middleware/cache/cache.js +0 -186
  164. package/dist/middleware/cache/cache.js.map +0 -1
  165. package/dist/middleware/cache/index.d.ts +0 -44
  166. package/dist/middleware/cache/index.d.ts.map +0 -1
  167. package/dist/middleware/cache/index.js +0 -44
  168. package/dist/middleware/cache/index.js.map +0 -1
  169. package/dist/middleware/cache/types.d.ts +0 -89
  170. package/dist/middleware/cache/types.d.ts.map +0 -1
  171. package/dist/middleware/cache/types.js +0 -5
  172. package/dist/middleware/cache/types.js.map +0 -1
  173. package/dist/middleware/csrf/csrf.d.ts +0 -34
  174. package/dist/middleware/csrf/csrf.d.ts.map +0 -1
  175. package/dist/middleware/csrf/csrf.js +0 -91
  176. package/dist/middleware/csrf/csrf.js.map +0 -1
  177. package/dist/middleware/csrf/index.d.ts +0 -57
  178. package/dist/middleware/csrf/index.d.ts.map +0 -1
  179. package/dist/middleware/csrf/index.js +0 -57
  180. package/dist/middleware/csrf/index.js.map +0 -1
  181. package/dist/middleware/csrf/types.d.ts +0 -57
  182. package/dist/middleware/csrf/types.d.ts.map +0 -1
  183. package/dist/middleware/csrf/types.js +0 -5
  184. package/dist/middleware/csrf/types.js.map +0 -1
  185. package/dist/middleware/index.d.ts +0 -115
  186. package/dist/middleware/index.d.ts.map +0 -1
  187. package/dist/middleware/index.js +0 -134
  188. package/dist/middleware/index.js.map +0 -1
  189. package/dist/middleware/logging/index.d.ts +0 -42
  190. package/dist/middleware/logging/index.d.ts.map +0 -1
  191. package/dist/middleware/logging/index.js +0 -42
  192. package/dist/middleware/logging/index.js.map +0 -1
  193. package/dist/middleware/logging/logging.d.ts +0 -29
  194. package/dist/middleware/logging/logging.d.ts.map +0 -1
  195. package/dist/middleware/logging/logging.js +0 -168
  196. package/dist/middleware/logging/logging.js.map +0 -1
  197. package/dist/middleware/logging/types.d.ts +0 -90
  198. package/dist/middleware/logging/types.d.ts.map +0 -1
  199. package/dist/middleware/logging/types.js +0 -5
  200. package/dist/middleware/logging/types.js.map +0 -1
  201. package/dist/middleware/rate-limit/index.d.ts +0 -16
  202. package/dist/middleware/rate-limit/index.d.ts.map +0 -1
  203. package/dist/middleware/rate-limit/index.js +0 -16
  204. package/dist/middleware/rate-limit/index.js.map +0 -1
  205. package/dist/middleware/rate-limit/rate-limit.d.ts +0 -14
  206. package/dist/middleware/rate-limit/rate-limit.d.ts.map +0 -1
  207. package/dist/middleware/rate-limit/rate-limit.js +0 -84
  208. package/dist/middleware/rate-limit/rate-limit.js.map +0 -1
  209. package/dist/middleware/rate-limit/types.d.ts +0 -97
  210. package/dist/middleware/rate-limit/types.d.ts.map +0 -1
  211. package/dist/middleware/rate-limit/types.js +0 -5
  212. package/dist/middleware/rate-limit/types.js.map +0 -1
  213. package/dist/middleware/retry/index.d.ts +0 -6
  214. package/dist/middleware/retry/index.d.ts.map +0 -1
  215. package/dist/middleware/retry/index.js +0 -6
  216. package/dist/middleware/retry/index.js.map +0 -1
  217. package/dist/middleware/retry/retry.d.ts +0 -39
  218. package/dist/middleware/retry/retry.d.ts.map +0 -1
  219. package/dist/middleware/retry/retry.js +0 -141
  220. package/dist/middleware/retry/retry.js.map +0 -1
  221. package/dist/middleware/retry/types.d.ts +0 -61
  222. package/dist/middleware/retry/types.d.ts.map +0 -1
  223. package/dist/middleware/retry/types.js +0 -5
  224. package/dist/middleware/retry/types.js.map +0 -1
package/dist/index.d.ts CHANGED
@@ -1,3 +1,1381 @@
1
+ /**
2
+ * @fileoverview Type definitions for the HTTP client.
3
+ *
4
+ * This file contains core TypeScript interfaces and types for FetchClient.
5
+ * Designed for discoverability and type safety.
6
+ */
7
+ /**
8
+ * Typed response wrapper with consistent shape.
9
+ *
10
+ * ✅ Always returns this shape (never throws)
11
+ * ✅ Use `.ok` to check success
12
+ * ✅ Use `.data` for parsed response
13
+ * ✅ Use `.error` for failure details
14
+ *
15
+ * @template T - The expected type of the response data
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * const result = await client.get<User[]>('/api/users');
20
+ * if (result.ok) {
21
+ * console.log(result.data); // Type is User[]
22
+ * } else {
23
+ * console.error(result.error?.message); // Handle error
24
+ * }
25
+ * ```
26
+ */
27
+ interface FetchResponse<T> {
28
+ /** The parsed response data (null if request failed) */
29
+ data: T | null;
30
+ /** HTTP status code (0 for network errors) */
31
+ status: number;
32
+ /** HTTP status text ('Network Error' for network failures) */
33
+ statusText: string;
34
+ /** Response headers */
35
+ headers: Headers;
36
+ /** The request URL */
37
+ url: string;
38
+ /** True if status 200-299, false otherwise */
39
+ ok: boolean;
40
+ /** Error details when ok is false */
41
+ error?: {
42
+ /** Human-readable error message */
43
+ message: string;
44
+ /** Raw error response body */
45
+ body?: unknown;
46
+ };
47
+ }
48
+ /**
49
+ * Configuration options for FetchClient.
50
+ *
51
+ * Optimized for "pit of success" - good defaults, minimal required config.
52
+ */
53
+ interface FetchClientOptions {
54
+ /**
55
+ * Controls credential handling for requests.
56
+ *
57
+ * - 'same-origin' (default): Send cookies for same-origin requests
58
+ * - 'include': Always send cookies
59
+ * - 'omit': Never send cookies
60
+ */
61
+ credentials?: RequestCredentials;
62
+ }
63
+
64
+ /**
65
+ * @fileoverview Enhanced fetch client with intercept middleware architecture.
66
+ */
67
+
68
+ /**
69
+ * Intercept middleware type that allows full control over request/response cycle.
70
+ * Middleware can modify requests, handle responses, implement retries, etc.
71
+ */
72
+ type FetchMiddleware = (request: RequestInit & {
73
+ url?: string;
74
+ }, next: (modifiedRequest?: RequestInit & {
75
+ url?: string;
76
+ }) => Promise<FetchResponse<unknown>>) => Promise<FetchResponse<unknown>>;
77
+ /**
78
+ * Enhanced HTTP client with intercept middleware architecture.
79
+ *
80
+ * Features:
81
+ * - 🎯 Smart defaults (JSON content-type, same-origin credentials)
82
+ * - 🔧 Powerful middleware system for cross-cutting concerns
83
+ * - 🛡️ Consistent error handling (never throws, always returns response)
84
+ * - 📦 TypeScript-first with full type inference
85
+ * - 🚀 Modern async/await API
86
+ *
87
+ * @example Basic usage:
88
+ * ```typescript
89
+ * const client = new FetchClient();
90
+ *
91
+ * // GET request - just works
92
+ * const users = await client.get<User[]>('/api/users');
93
+ * if (users.ok) {
94
+ * console.log(users.data); // Type is User[]
95
+ * }
96
+ *
97
+ * // POST request - JSON by default
98
+ * const result = await client.post('/api/users', { name: 'John' });
99
+ * ```
100
+ *
101
+ * @example With middleware:
102
+ * ```typescript
103
+ * const client = new FetchClient();
104
+ *
105
+ * // Add auth middleware
106
+ * client.use((request, next) => {
107
+ * request.headers = { ...request.headers, Authorization: 'Bearer token' };
108
+ * return next(request);
109
+ * });
110
+ *
111
+ * // Now all requests include auth
112
+ * const data = await client.get('/api/protected');
113
+ * ```
114
+ */
115
+ declare class FetchClient {
116
+ private middlewares;
117
+ private credentials;
118
+ constructor(config?: FetchClientOptions);
119
+ use(middleware: FetchMiddleware): this;
120
+ request<T = unknown>(url: string, init?: RequestInit): Promise<FetchResponse<T>>;
121
+ private coreFetch;
122
+ private parseResponse;
123
+ private buildUrlWithParams;
124
+ /**
125
+ * HEAD request with query parameter support.
126
+ *
127
+ * HEAD requests are used to retrieve metadata about a resource without downloading
128
+ * the response body. Useful for checking if a resource exists, getting content length,
129
+ * last modified date, etc.
130
+ *
131
+ * @template T - Expected response data type (will be null for HEAD requests)
132
+ * @param url - Request URL
133
+ * @param params - Query parameters to append to URL
134
+ * @returns Promise resolving to typed response (data will always be null)
135
+ *
136
+ * @example Check if resource exists:
137
+ * ```typescript
138
+ * const headResponse = await client.head('/api/large-file.zip');
139
+ * if (headResponse.ok) {
140
+ * const contentLength = headResponse.headers.get('content-length');
141
+ * const lastModified = headResponse.headers.get('last-modified');
142
+ * console.log(`File size: ${contentLength} bytes`);
143
+ * }
144
+ * ```
145
+ *
146
+ * @example Check with query parameters:
147
+ * ```typescript
148
+ * const exists = await client.head('/api/users', { id: 123 });
149
+ * if (exists.status === 404) {
150
+ * console.log('User not found');
151
+ * }
152
+ * ```
153
+ */
154
+ head<T = null>(url: string, params?: Record<string, string | number | boolean | undefined>): Promise<FetchResponse<T>>;
155
+ /**
156
+ * HEAD request that returns useful metadata about a resource.
157
+ *
158
+ * This is a convenience method that extracts common metadata from HEAD responses
159
+ * for easier consumption.
160
+ *
161
+ * @param url - Request URL
162
+ * @param params - Query parameters to append to URL
163
+ * @returns Promise resolving to response with extracted metadata
164
+ *
165
+ * @example Get resource metadata:
166
+ * ```typescript
167
+ * const metadata = await client.headMetadata('/api/large-file.zip');
168
+ * if (metadata.ok) {
169
+ * console.log('File exists:', metadata.exists);
170
+ * console.log('Content type:', metadata.contentType);
171
+ * console.log('Size:', metadata.contentLength, 'bytes');
172
+ * console.log('Last modified:', metadata.lastModified);
173
+ * }
174
+ * ```
175
+ */
176
+ headMetadata(url: string, params?: Record<string, string | number | boolean | undefined>): Promise<FetchResponse<null> & {
177
+ exists: boolean;
178
+ contentType: string | undefined;
179
+ contentLength: number | undefined;
180
+ lastModified: Date | undefined;
181
+ etag: string | undefined;
182
+ cacheControl: string | undefined;
183
+ }>;
184
+ /**
185
+ * GET request with query parameter support.
186
+ *
187
+ * @template T - Expected response data type
188
+ * @param url - Request URL
189
+ * @param params - Query parameters to append to URL
190
+ * @returns Promise resolving to typed response
191
+ *
192
+ * @example
193
+ * ```typescript
194
+ * const users = await client.get<User[]>('/api/users');
195
+ * const filteredUsers = await client.get<User[]>('/api/users', { status: 'active', limit: 10 });
196
+ * if (users.ok) console.log(users.data);
197
+ * ```
198
+ */
199
+ get<T>(url: string, params?: Record<string, string | number | boolean | undefined>): Promise<FetchResponse<T>>;
200
+ /**
201
+ * POST request with automatic JSON serialization.
202
+ *
203
+ * @template T - Expected response data type
204
+ * @param url - Request URL
205
+ * @param body - Request body (auto-serialized to JSON)
206
+ * @param headers - Additional headers (Content-Type: application/json is default)
207
+ * @returns Promise resolving to typed response
208
+ *
209
+ * @example
210
+ * ```typescript
211
+ * const result = await client.post<User>('/api/users', { name: 'John' });
212
+ * ```
213
+ */
214
+ post<T>(url: string, body?: unknown, headers?: Record<string, string>): Promise<FetchResponse<T>>;
215
+ /**
216
+ * PUT request with automatic JSON serialization.
217
+ *
218
+ * @template T - Expected response data type
219
+ * @param url - Request URL
220
+ * @param body - Request body (auto-serialized to JSON)
221
+ * @param headers - Additional headers (Content-Type: application/json is default)
222
+ * @returns Promise resolving to typed response
223
+ */
224
+ put<T>(url: string, body?: unknown, headers?: Record<string, string>): Promise<FetchResponse<T>>;
225
+ /**
226
+ * PATCH request with automatic JSON serialization.
227
+ *
228
+ * @template T - Expected response data type
229
+ * @param url - Request URL
230
+ * @param body - Request body (auto-serialized to JSON)
231
+ * @param headers - Additional headers (Content-Type: application/json is default)
232
+ * @returns Promise resolving to typed response
233
+ */
234
+ patch<T>(url: string, body?: unknown, headers?: Record<string, string>): Promise<FetchResponse<T>>;
235
+ /**
236
+ * DELETE request with query parameter support.
237
+ *
238
+ * @template T - Expected response data type
239
+ * @param url - Request URL
240
+ * @param params - Query parameters to append to URL
241
+ * @returns Promise resolving to typed response
242
+ *
243
+ * @example
244
+ * ```typescript
245
+ * const result = await client.del('/api/users/123');
246
+ * const bulkResult = await client.del('/api/users', { status: 'inactive', force: true });
247
+ * if (result.ok) console.log('Deleted successfully');
248
+ * ```
249
+ */
250
+ del<T>(url: string, params?: Record<string, string | number | boolean | undefined>): Promise<FetchResponse<T>>;
251
+ }
252
+
253
+ /**
254
+ * @fileoverview Custom error classes - "Pit of Success" pattern.
255
+ *
256
+ * 🎯 LEVEL 1: HttpError, NetworkError - Most common error types you'll catch
257
+ * 🎯 LEVEL 2: FetchError - Base error class for advanced error handling
258
+ *
259
+ * @example
260
+ * ```typescript
261
+ * try {
262
+ * await client.get('/api/data');
263
+ * } catch (error) {
264
+ * if (error instanceof HttpError) {
265
+ * console.log(`HTTP ${error.status}: ${error.statusText}`);
266
+ * } else if (error instanceof NetworkError) {
267
+ * console.log('Network connection failed');
268
+ * }
269
+ * }
270
+ * ```
271
+ */
272
+ /**
273
+ * Base error class for all fetch client errors.
274
+ */
275
+ declare class FetchError extends Error {
276
+ /** Optional underlying cause */
277
+ readonly cause?: Error;
278
+ /**
279
+ * Creates a new FetchError.
280
+ * @param message - Error message
281
+ * @param cause - Optional underlying cause
282
+ */
283
+ constructor(message: string, cause?: Error);
284
+ }
285
+ /**
286
+ * Error thrown when an HTTP request fails with a non-2xx status code.
287
+ */
288
+ declare class HttpError extends FetchError {
289
+ /** The HTTP status code */
290
+ readonly status: number;
291
+ /** The HTTP status text */
292
+ readonly statusText: string;
293
+ /** The response body (if available) */
294
+ readonly body: unknown;
295
+ /**
296
+ * Creates a new HttpError.
297
+ * @param status - HTTP status code
298
+ * @param statusText - HTTP status text
299
+ * @param body - Response body
300
+ * @param url - The request URL
301
+ */
302
+ constructor(status: number, statusText: string, body: unknown, url: string);
303
+ }
304
+ /**
305
+ * Error thrown when a network request fails completely.
306
+ */
307
+ declare class NetworkError extends FetchError {
308
+ /**
309
+ * Creates a new NetworkError.
310
+ * @param message - Error message
311
+ * @param url - The request URL
312
+ * @param cause - The underlying network error
313
+ */
314
+ constructor(message: string, url: string, cause?: Error);
315
+ }
316
+
317
+ /**
318
+ * @fileoverview Authentication middleware types and configuration.
319
+ */
320
+ /**
321
+ * Authentication token provider function.
322
+ * Should return the current auth token or empty string if not available.
323
+ */
324
+ type AuthTokenProvider = () => string | Promise<string>;
325
+ /**
326
+ * Authentication configuration options - optimized for "pit of success".
327
+ *
328
+ * Smart defaults:
329
+ * - Uses standard Authorization header with Bearer token
330
+ * - Applies to all requests by default
331
+ * - Graceful handling when token is unavailable
332
+ */
333
+ interface AuthenticationOptions {
334
+ /**
335
+ * Function to get the current authentication token.
336
+ * Can be synchronous or asynchronous.
337
+ *
338
+ * @returns The auth token or empty string if not available
339
+ *
340
+ * @example Token from localStorage:
341
+ * ```typescript
342
+ * const getToken = () => localStorage.getItem('auth-token') || '';
343
+ * ```
344
+ *
345
+ * @example Async token refresh:
346
+ * ```typescript
347
+ * const getToken = async () => {
348
+ * const token = localStorage.getItem('auth-token');
349
+ * if (!token || isExpired(token)) {
350
+ * return await refreshToken();
351
+ * }
352
+ * return token;
353
+ * };
354
+ * ```
355
+ */
356
+ tokenProvider: AuthTokenProvider;
357
+ /**
358
+ * Header name for the authentication token (default: 'Authorization')
359
+ * The token will be prefixed with the tokenType
360
+ */
361
+ headerName?: string;
362
+ /**
363
+ * Token type prefix (default: 'Bearer')
364
+ * Common alternatives: 'Token', 'JWT', 'ApiKey'
365
+ */
366
+ tokenType?: string;
367
+ /**
368
+ * Skip authentication for requests matching these URL patterns
369
+ * Useful for public endpoints that don't need auth
370
+ *
371
+ * @example
372
+ * ```typescript
373
+ * skipPatterns: [/^\/public\//, '/health', '/login']
374
+ * ```
375
+ */
376
+ skipPatterns?: (RegExp | string)[];
377
+ /**
378
+ * Only apply authentication to requests matching these patterns
379
+ * If specified, only these patterns will get auth headers
380
+ *
381
+ * @example
382
+ * ```typescript
383
+ * includePatterns: [/^\/api\//, '/graphql']
384
+ * ```
385
+ */
386
+ includePatterns?: (RegExp | string)[];
387
+ }
388
+
389
+ /**
390
+ * @fileoverview Authentication middleware implementation.
391
+ */
392
+
393
+ /**
394
+ * Creates authentication middleware with smart defaults.
395
+ * Automatically adds Bearer tokens to requests.
396
+ *
397
+ * @param options - Authentication configuration options
398
+ * @returns Authentication middleware for use with FetchClient
399
+ *
400
+ * @example Basic usage:
401
+ * ```typescript
402
+ * const authClient = useAuthentication(client, {
403
+ * tokenProvider: () => localStorage.getItem('token') || ''
404
+ * });
405
+ * ```
406
+ *
407
+ * @example Async token provider:
408
+ * ```typescript
409
+ * const authClient = useAuthentication(client, {
410
+ * tokenProvider: async () => {
411
+ * const token = await getAuthToken();
412
+ * return token || '';
413
+ * }
414
+ * });
415
+ * ```
416
+ */
417
+ declare function createAuthenticationMiddleware(options: AuthenticationOptions): FetchMiddleware;
418
+
419
+ /**
420
+ * @fileoverview Authentication middleware - "pit of success" API.
421
+ */
422
+
423
+ /**
424
+ * "Pit of success" API for adding authentication to a FetchClient.
425
+ * Automatically adds Bearer tokens to requests.
426
+ *
427
+ * @param client - The FetchClient to add authentication to
428
+ * @param options - Authentication configuration
429
+ * @returns A new FetchClient with authentication middleware
430
+ *
431
+ * @example Basic token from localStorage:
432
+ * ```typescript
433
+ * const authClient = useAuthentication(client, {
434
+ * tokenProvider: () => localStorage.getItem('auth-token') || ''
435
+ * });
436
+ * ```
437
+ *
438
+ * @example Async token with refresh:
439
+ * ```typescript
440
+ * const authClient = useAuthentication(client, {
441
+ * tokenProvider: async () => {
442
+ * let token = localStorage.getItem('auth-token');
443
+ * if (!token || isExpired(token)) {
444
+ * token = await refreshToken();
445
+ * }
446
+ * return token || '';
447
+ * }
448
+ * });
449
+ * ```
450
+ */
451
+ declare function useAuthentication(client: FetchClient, options: AuthenticationOptions): FetchClient;
452
+
453
+ /**
454
+ * @fileoverview Authorization middleware types and configuration.
455
+ */
456
+
457
+ /**
458
+ * Handler function for unauthorized/forbidden responses.
459
+ */
460
+ type UnauthorizedHandler = (response: FetchResponse<unknown>, request: RequestInit & {
461
+ url?: string;
462
+ }) => void | Promise<void>;
463
+ /**
464
+ * Smart default configuration for redirect-based authorization handling.
465
+ */
466
+ interface RedirectAuthorizationConfig {
467
+ /**
468
+ * Path to redirect to on unauthorized response (default: '/login')
469
+ */
470
+ redirectPath?: string;
471
+ /**
472
+ * Query parameter name for the return URL (default: 'return_url')
473
+ */
474
+ returnUrlParam?: string;
475
+ /**
476
+ * Whether to include the current URL as a return URL (default: true)
477
+ * Set to false if you don't want the return URL functionality
478
+ */
479
+ includeReturnUrl?: boolean;
480
+ }
481
+ /**
482
+ * Authorization configuration options - optimized for "pit of success".
483
+ *
484
+ * Smart defaults:
485
+ * - Handles 401 Unauthorized responses
486
+ * - Optionally handles 403 Forbidden responses
487
+ * - Graceful error handling
488
+ * - When no options provided, defaults to redirecting to /login with return URL
489
+ */
490
+ interface AuthorizationOptions {
491
+ /**
492
+ * Handler called when 401 Unauthorized response is received.
493
+ *
494
+ * @param response - The 401 response object
495
+ * @param request - The original request that was unauthorized
496
+ *
497
+ * @example Redirect to login:
498
+ * ```typescript
499
+ * onUnauthorized: () => {
500
+ * window.location.href = '/login';
501
+ * }
502
+ * ```
503
+ *
504
+ * @example Clear token and reload:
505
+ * ```typescript
506
+ * onUnauthorized: () => {
507
+ * localStorage.removeItem('auth-token');
508
+ * window.location.reload();
509
+ * }
510
+ * ```
511
+ */
512
+ onUnauthorized?: UnauthorizedHandler;
513
+ /**
514
+ * Smart default configuration for redirect-based authorization.
515
+ * When provided, creates a default onUnauthorized handler that redirects
516
+ * to the login page with a return URL.
517
+ *
518
+ * @example Use defaults (redirects to '/login?return_url=current-page'):
519
+ * ```typescript
520
+ * redirectConfig: {}
521
+ * ```
522
+ *
523
+ * @example Custom redirect path:
524
+ * ```typescript
525
+ * redirectConfig: { redirectPath: '/signin' }
526
+ * ```
527
+ */
528
+ redirectConfig?: RedirectAuthorizationConfig;
529
+ /**
530
+ * Handler called when 403 Forbidden response is received.
531
+ * Optional - if not provided, 403 responses are ignored.
532
+ *
533
+ * @param response - The 403 response object
534
+ * @param request - The original request that was forbidden
535
+ */
536
+ onForbidden?: UnauthorizedHandler;
537
+ /**
538
+ * Skip authorization handling for requests matching these URL patterns
539
+ * Useful for login/public endpoints where 401 is expected
540
+ *
541
+ * @example
542
+ * ```typescript
543
+ * skipPatterns: ['/login', '/register', /^\/public\//]
544
+ * ```
545
+ */
546
+ skipPatterns?: (RegExp | string)[];
547
+ /**
548
+ * Status codes to handle (default: [401])
549
+ * You can add 403 if you want to handle forbidden responses
550
+ */
551
+ statusCodes?: number[];
552
+ }
553
+
554
+ /**
555
+ * @fileoverview Authorization middleware implementation.
556
+ */
557
+
558
+ /**
559
+ * Creates authorization middleware with smart defaults.
560
+ * Handles 401/403 responses by calling configured handlers.
561
+ *
562
+ * @param options - Authorization configuration options (optional)
563
+ * @returns Authorization middleware for use with FetchClient
564
+ *
565
+ * @example Smart defaults (no configuration needed):
566
+ * ```typescript
567
+ * const authzClient = useAuthorization(client);
568
+ * // Redirects to '/login?return_url=current-page' on 401
569
+ * ```
570
+ *
571
+ * @example Custom redirect configuration:
572
+ * ```typescript
573
+ * const authzClient = useAuthorization(client, {
574
+ * redirectConfig: {
575
+ * redirectPath: '/signin',
576
+ * returnUrlParam: 'redirect_to'
577
+ * }
578
+ * });
579
+ * ```
580
+ *
581
+ * @example Manual handler (full control):
582
+ * ```typescript
583
+ * const authzClient = useAuthorization(client, {
584
+ * onUnauthorized: () => window.location.href = '/login'
585
+ * });
586
+ * ```
587
+ *
588
+ * @example Handle both 401 and 403:
589
+ * ```typescript
590
+ * const authzClient = useAuthorization(client, {
591
+ * onForbidden: () => showAccessDeniedMessage(),
592
+ * statusCodes: [401, 403]
593
+ * });
594
+ * ```
595
+ */
596
+ declare function createAuthorizationMiddleware(options?: AuthorizationOptions): FetchMiddleware;
597
+
598
+ /**
599
+ * @fileoverview Authorization middleware - "pit of success" API.
600
+ */
601
+
602
+ /**
603
+ * "Pit of success" API for adding authorization handling to a FetchClient.
604
+ * Automatically handles 401 Unauthorized responses.
605
+ *
606
+ * @param client - The FetchClient to add authorization handling to
607
+ * @param options - Authorization configuration (optional)
608
+ * @returns A new FetchClient with authorization middleware
609
+ *
610
+ * @example Smart defaults - no configuration needed:
611
+ * ```typescript
612
+ * const authzClient = useAuthorization(client);
613
+ * // Redirects to '/login?return_url=current-page' on 401
614
+ * ```
615
+ *
616
+ * @example Custom redirect path:
617
+ * ```typescript
618
+ * const authzClient = useAuthorization(client, {
619
+ * redirectConfig: { redirectPath: '/signin', returnUrlParam: 'redirect_to' }
620
+ * });
621
+ * ```
622
+ *
623
+ * @example Manual handler (full control):
624
+ * ```typescript
625
+ * const authzClient = useAuthorization(client, {
626
+ * onUnauthorized: () => {
627
+ * localStorage.removeItem('auth-token');
628
+ * window.location.href = '/login';
629
+ * }
630
+ * });
631
+ * ```
632
+ *
633
+ * @example Handle multiple status codes:
634
+ * ```typescript
635
+ * const authzClient = useAuthorization(client, {
636
+ * onForbidden: () => showAccessDenied(),
637
+ * statusCodes: [401, 403]
638
+ * });
639
+ * ```
640
+ */
641
+ declare function useAuthorization(client: FetchClient, options?: AuthorizationOptions): FetchClient;
642
+
643
+ /**
644
+ * @fileoverview Cache middleware types and configuration.
645
+ */
646
+ /**
647
+ * Cache key generator function.
648
+ * Should return a unique key for the request.
649
+ */
650
+ type CacheKeyGenerator = (request: RequestInit & {
651
+ url?: string;
652
+ }) => string;
653
+ /**
654
+ * Cache storage interface.
655
+ * Allows custom cache implementations.
656
+ */
657
+ interface CacheStorage {
658
+ get(key: string): Promise<CacheEntry | null>;
659
+ getWithExpiry?(key: string): Promise<{
660
+ entry: CacheEntry | null;
661
+ isExpired: boolean;
662
+ }>;
663
+ set(key: string, entry: CacheEntry): Promise<void>;
664
+ delete(key: string): Promise<void>;
665
+ clear(): Promise<void>;
666
+ }
667
+ /**
668
+ * Cached response entry.
669
+ */
670
+ interface CacheEntry {
671
+ response: {
672
+ status: number;
673
+ statusText: string;
674
+ headers: Record<string, string>;
675
+ data: unknown;
676
+ };
677
+ timestamp: number;
678
+ expiresAt: number;
679
+ }
680
+ /**
681
+ * Cache configuration options - optimized for "pit of success".
682
+ *
683
+ * Smart defaults:
684
+ * - Only caches GET requests
685
+ * - 5 minute default TTL
686
+ * - Memory-based storage
687
+ * - Automatic cache key generation
688
+ */
689
+ interface CacheOptions {
690
+ /**
691
+ * Time to live in milliseconds (default: 300000 = 5 minutes)
692
+ * How long responses should be cached
693
+ */
694
+ ttl?: number;
695
+ /**
696
+ * HTTP methods to cache (default: ['GET'])
697
+ * Only these methods will be cached
698
+ */
699
+ methods?: string[];
700
+ /**
701
+ * Cache storage implementation (default: in-memory)
702
+ * Can be replaced with localStorage, IndexedDB, etc.
703
+ */
704
+ storage?: CacheStorage;
705
+ /**
706
+ * Custom cache key generator (default: URL + method + headers)
707
+ * Should return a unique key for each request
708
+ *
709
+ * @example Custom key generator:
710
+ * ```typescript
711
+ * keyGenerator: (request) => `${request.method}:${request.url}`
712
+ * ```
713
+ */
714
+ keyGenerator?: CacheKeyGenerator;
715
+ /**
716
+ * Skip caching for requests matching these URL patterns
717
+ *
718
+ * @example
719
+ * ```typescript
720
+ * skipPatterns: [/\/api\/user/, '/dynamic-data']
721
+ * ```
722
+ */
723
+ skipPatterns?: (RegExp | string)[];
724
+ /**
725
+ * Whether to serve stale cache entries while revalidating
726
+ * When true, returns cached data immediately and updates cache in background
727
+ */
728
+ staleWhileRevalidate?: boolean;
729
+ }
730
+
731
+ /**
732
+ * @fileoverview Cache middleware implementation.
733
+ */
734
+
735
+ /**
736
+ * Creates cache middleware with smart defaults.
737
+ * Caches GET responses for faster subsequent requests.
738
+ *
739
+ * @param options - Cache configuration options
740
+ * @returns Cache middleware for use with FetchClient
741
+ *
742
+ * @example Basic caching:
743
+ * ```typescript
744
+ * const cachedClient = useCache(client);
745
+ * // GET requests will be cached for 5 minutes
746
+ * ```
747
+ *
748
+ * @example Custom TTL:
749
+ * ```typescript
750
+ * const cachedClient = useCache(client, {
751
+ * ttl: 10 * 60 * 1000 // 10 minutes
752
+ * });
753
+ * ```
754
+ */
755
+ declare function createCacheMiddleware(options?: CacheOptions): FetchMiddleware;
756
+
757
+ /**
758
+ * @fileoverview Cache middleware - "pit of success" API.
759
+ */
760
+
761
+ /**
762
+ * "Pit of success" API for adding response caching to a FetchClient.
763
+ * Caches GET responses for faster subsequent requests.
764
+ *
765
+ * @param client - The FetchClient to add caching to
766
+ * @param options - Cache configuration options
767
+ * @returns A new FetchClient with cache middleware
768
+ *
769
+ * @example Basic caching (5 minute TTL):
770
+ * ```typescript
771
+ * const cachedClient = useCache(client);
772
+ *
773
+ * // First call hits the network
774
+ * await cachedClient.get('/api/data');
775
+ *
776
+ * // Second call returns cached data
777
+ * await cachedClient.get('/api/data');
778
+ * ```
779
+ *
780
+ * @example Custom TTL and methods:
781
+ * ```typescript
782
+ * const cachedClient = useCache(client, {
783
+ * ttl: 10 * 60 * 1000, // 10 minutes
784
+ * methods: ['GET', 'HEAD']
785
+ * });
786
+ * ```
787
+ *
788
+ * @example Stale-while-revalidate:
789
+ * ```typescript
790
+ * const cachedClient = useCache(client, {
791
+ * staleWhileRevalidate: true
792
+ * });
793
+ * // Returns stale data immediately, updates cache in background
794
+ * ```
795
+ */
796
+ declare function useCache(client: FetchClient, options?: CacheOptions): FetchClient;
797
+
798
+ /**
799
+ * @fileoverview CSRF protection middleware types and configuration.
800
+ */
801
+ /**
802
+ * CSRF token provider function.
803
+ * Should return the current CSRF token or empty string if not available.
804
+ */
805
+ type CSRFTokenProvider = () => string;
806
+ /**
807
+ * CSRF configuration options - optimized for "pit of success".
808
+ *
809
+ * Smart defaults:
810
+ * - Uses standard X-XSRF-TOKEN header
811
+ * - Automatically extracts token from XSRF-TOKEN cookie
812
+ * - Only adds token to state-changing methods (POST, PUT, PATCH, DELETE)
813
+ */
814
+ interface CSRFOptions {
815
+ /**
816
+ * Function to get the current CSRF token.
817
+ * Default: extracts from XSRF-TOKEN cookie (standard Rails/Laravel convention)
818
+ *
819
+ * @returns The CSRF token or empty string if not available
820
+ *
821
+ * @example Custom token provider:
822
+ * ```typescript
823
+ * const getToken = () => localStorage.getItem('csrf-token') || '';
824
+ * ```
825
+ */
826
+ tokenProvider?: CSRFTokenProvider;
827
+ /**
828
+ * Header name to use for CSRF token (default: 'X-XSRF-TOKEN')
829
+ * Common alternatives: 'X-CSRF-Token', 'X-CSRFToken'
830
+ */
831
+ headerName?: string;
832
+ /**
833
+ * Cookie name to read token from when using default provider (default: 'XSRF-TOKEN')
834
+ * Common alternatives: 'csrf-token', '_token'
835
+ */
836
+ cookieName?: string;
837
+ /**
838
+ * HTTP methods that require CSRF protection (default: ['POST', 'PUT', 'PATCH', 'DELETE'])
839
+ * GET and HEAD requests typically don't need CSRF tokens
840
+ */
841
+ protectedMethods?: string[];
842
+ /**
843
+ * Skip CSRF protection for requests matching these URL patterns
844
+ * Useful for external API calls that don't need CSRF tokens
845
+ *
846
+ * @example
847
+ * ```typescript
848
+ * skipPatterns: [/^https:\/\/api\.external\.com\//, '/public-api/']
849
+ * ```
850
+ */
851
+ skipPatterns?: (RegExp | string)[];
852
+ }
853
+
854
+ /**
855
+ * @fileoverview CSRF protection middleware - "pit of success" API.
856
+ */
857
+
858
+ /**
859
+ * "Pit of success" API for adding CSRF protection to a FetchClient.
860
+ * Uses smart defaults that work with most web frameworks out of the box.
861
+ *
862
+ * Default behavior:
863
+ * - Reads CSRF token from XSRF-TOKEN cookie
864
+ * - Adds X-XSRF-TOKEN header to POST, PUT, PATCH, DELETE requests
865
+ * - Skips GET/HEAD requests (they don't need CSRF protection)
866
+ *
867
+ * @param client - The FetchClient to add CSRF protection to
868
+ * @param options - Optional CSRF configuration
869
+ * @returns A new FetchClient with CSRF protection
870
+ *
871
+ * @example Basic usage (automatic cookie-based CSRF):
872
+ * ```typescript
873
+ * const client = new FetchClient();
874
+ * const protectedClient = useCSRF(client);
875
+ *
876
+ * // CSRF token automatically added to POST requests
877
+ * await protectedClient.post('/api/users', { name: 'John' });
878
+ * ```
879
+ *
880
+ * @example Custom token provider:
881
+ * ```typescript
882
+ * const protectedClient = useCSRF(client, {
883
+ * tokenProvider: () => localStorage.getItem('csrf-token') || ''
884
+ * });
885
+ * ```
886
+ *
887
+ * @example Custom header and cookie names:
888
+ * ```typescript
889
+ * const protectedClient = useCSRF(client, {
890
+ * headerName: 'X-CSRF-Token',
891
+ * cookieName: 'csrf-token'
892
+ * });
893
+ * ```
894
+ *
895
+ * @example Skip patterns for external APIs:
896
+ * ```typescript
897
+ * const protectedClient = useCSRF(client, {
898
+ * skipPatterns: [
899
+ * /^https:\/\/api\.external\.com\//, // Skip external API
900
+ * '/webhook/', // Skip webhook endpoints
901
+ * '/public-api/' // Skip public API endpoints
902
+ * ]
903
+ * });
904
+ * ```
905
+ */
906
+ declare function useCSRF(client: FetchClient, options?: CSRFOptions): FetchClient;
907
+
908
+ /**
909
+ * @fileoverview Logging middleware types and configuration.
910
+ */
911
+ /**
912
+ * Log levels for filtering log output.
913
+ */
914
+ type LogLevel = 'debug' | 'info' | 'warn' | 'error';
915
+ /**
916
+ * Log entry structure.
917
+ */
918
+ interface LogEntry {
919
+ level: LogLevel;
920
+ timestamp: number;
921
+ method: string;
922
+ url: string;
923
+ status?: number;
924
+ duration?: number;
925
+ error?: Error;
926
+ requestHeaders?: Record<string, string>;
927
+ responseHeaders?: Record<string, string>;
928
+ requestBody?: unknown;
929
+ responseBody?: unknown;
930
+ }
931
+ /**
932
+ * Custom logger interface.
933
+ */
934
+ interface Logger {
935
+ debug(message: string, data?: unknown): void;
936
+ info(message: string, data?: unknown): void;
937
+ warn(message: string, data?: unknown): void;
938
+ error(message: string, data?: unknown): void;
939
+ }
940
+ /**
941
+ * Logging configuration options - optimized for "pit of success".
942
+ *
943
+ * Smart defaults:
944
+ * - Logs to console
945
+ * - Info level by default
946
+ * - Excludes request/response bodies by default
947
+ * - Includes timing information
948
+ */
949
+ interface LoggingOptions {
950
+ /**
951
+ * Minimum log level to output (default: 'info')
952
+ * Logs at this level and above will be output
953
+ */
954
+ level?: LogLevel;
955
+ /**
956
+ * Custom logger implementation (default: console)
957
+ * Can be replaced with winston, pino, etc.
958
+ */
959
+ logger?: Logger;
960
+ /**
961
+ * Include request headers in logs (default: false)
962
+ * May contain sensitive information
963
+ */
964
+ includeRequestHeaders?: boolean;
965
+ /**
966
+ * Include response headers in logs (default: false)
967
+ * May contain sensitive information
968
+ */
969
+ includeResponseHeaders?: boolean;
970
+ /**
971
+ * Include request body in logs (default: false)
972
+ * May contain sensitive information and increase log size
973
+ */
974
+ includeRequestBody?: boolean;
975
+ /**
976
+ * Include response body in logs (default: false)
977
+ * May contain sensitive information and increase log size
978
+ */
979
+ includeResponseBody?: boolean;
980
+ /**
981
+ * Skip logging for requests matching these URL patterns
982
+ * Useful for health checks, metrics endpoints, etc.
983
+ *
984
+ * @example
985
+ * ```typescript
986
+ * skipPatterns: ['/health', '/metrics', /\/static\//]
987
+ * ```
988
+ */
989
+ skipPatterns?: (RegExp | string)[];
990
+ /**
991
+ * Custom log formatter function
992
+ * Allows complete customization of log output
993
+ */
994
+ formatter?: (entry: LogEntry) => string;
995
+ }
996
+
997
+ /**
998
+ * @fileoverview Logging middleware implementation.
999
+ */
1000
+
1001
+ /**
1002
+ * Creates logging middleware with smart defaults.
1003
+ * Logs HTTP requests and responses for debugging and monitoring.
1004
+ *
1005
+ * @param options - Logging configuration options
1006
+ * @returns Logging middleware for use with FetchClient
1007
+ *
1008
+ * @example Basic logging:
1009
+ * ```typescript
1010
+ * const loggedClient = useLogging(client);
1011
+ * // Logs all requests to console
1012
+ * ```
1013
+ *
1014
+ * @example Custom logger:
1015
+ * ```typescript
1016
+ * const loggedClient = useLogging(client, {
1017
+ * logger: winston.createLogger({...}),
1018
+ * level: 'debug',
1019
+ * includeRequestHeaders: true
1020
+ * });
1021
+ * ```
1022
+ */
1023
+ declare function createLoggingMiddleware(options?: LoggingOptions): FetchMiddleware;
1024
+
1025
+ /**
1026
+ * @fileoverview Logging middleware - "pit of success" API.
1027
+ */
1028
+
1029
+ /**
1030
+ * "Pit of success" API for adding logging to a FetchClient.
1031
+ * Logs HTTP requests and responses for debugging and monitoring.
1032
+ *
1033
+ * @param client - The FetchClient to add logging to
1034
+ * @param options - Logging configuration options
1035
+ * @returns A new FetchClient with logging middleware
1036
+ *
1037
+ * @example Basic logging to console:
1038
+ * ```typescript
1039
+ * const loggedClient = useLogging(client);
1040
+ *
1041
+ * // Logs: → GET /api/users
1042
+ * // Logs: ← GET /api/users → 200 (245ms)
1043
+ * await loggedClient.get('/api/users');
1044
+ * ```
1045
+ *
1046
+ * @example Custom log level and headers:
1047
+ * ```typescript
1048
+ * const loggedClient = useLogging(client, {
1049
+ * level: 'debug',
1050
+ * includeRequestHeaders: true,
1051
+ * includeResponseHeaders: true
1052
+ * });
1053
+ * ```
1054
+ *
1055
+ * @example Skip health check endpoints:
1056
+ * ```typescript
1057
+ * const loggedClient = useLogging(client, {
1058
+ * skipPatterns: ['/health', '/metrics', '/ping']
1059
+ * });
1060
+ * ```
1061
+ */
1062
+ declare function useLogging(client: FetchClient, options?: LoggingOptions): FetchClient;
1063
+
1064
+ /**
1065
+ * @fileoverview Rate limiting middleware types and configuration.
1066
+ */
1067
+ /**
1068
+ * Rate limiting algorithm types.
1069
+ */
1070
+ type RateLimitAlgorithm = 'token-bucket' | 'sliding-window' | 'fixed-window';
1071
+ /**
1072
+ * Rate limiting configuration options - optimized for "pit of success".
1073
+ *
1074
+ * Smart defaults:
1075
+ * - 60 requests per minute
1076
+ * - Token bucket algorithm
1077
+ * - Per-client limiting
1078
+ * - Graceful handling when rate limit exceeded
1079
+ */
1080
+ interface RateLimitOptions {
1081
+ /**
1082
+ * Maximum number of requests allowed (default: 60)
1083
+ */
1084
+ maxRequests?: number;
1085
+ /**
1086
+ * Time window in milliseconds (default: 60000 = 1 minute)
1087
+ */
1088
+ windowMs?: number;
1089
+ /**
1090
+ * Rate limiting algorithm (default: 'token-bucket')
1091
+ * - 'token-bucket': Allows bursts up to maxRequests, refills over time
1092
+ * - 'sliding-window': Smooth rate limiting over rolling window
1093
+ * - 'fixed-window': Fixed number of requests per fixed time window
1094
+ */
1095
+ algorithm?: RateLimitAlgorithm;
1096
+ /**
1097
+ * Custom key generator for rate limiting scope
1098
+ * Default: single global rate limit for all requests
1099
+ *
1100
+ * @example Per-endpoint rate limiting:
1101
+ * ```typescript
1102
+ * keyGenerator: (request) => request.url || 'default'
1103
+ * ```
1104
+ *
1105
+ * @example Per-user rate limiting:
1106
+ * ```typescript
1107
+ * keyGenerator: (request) => {
1108
+ * const auth = request.headers?.get('Authorization');
1109
+ * return auth ? `user:${auth}` : 'anonymous';
1110
+ * }
1111
+ * ```
1112
+ */
1113
+ keyGenerator?: (request: RequestInit & {
1114
+ url?: string;
1115
+ }) => string;
1116
+ /**
1117
+ * Skip rate limiting for requests matching these URL patterns
1118
+ *
1119
+ * @example
1120
+ * ```typescript
1121
+ * skipPatterns: ['/health', /^\/public\//]
1122
+ * ```
1123
+ */
1124
+ skipPatterns?: (RegExp | string)[];
1125
+ /**
1126
+ * Custom handler called when rate limit is exceeded
1127
+ * Can return a custom response or void to use default behavior
1128
+ *
1129
+ * @param retryAfter - Milliseconds until next request is allowed
1130
+ * @param request - The rate-limited request
1131
+ * @returns Custom response or void for default behavior
1132
+ */
1133
+ onRateLimitExceeded?: (retryAfter: number, request: RequestInit & {
1134
+ url?: string;
1135
+ }) => void | Promise<void> | {
1136
+ data: unknown;
1137
+ status: number;
1138
+ statusText: string;
1139
+ headers: Headers;
1140
+ url: string;
1141
+ ok: boolean;
1142
+ error?: {
1143
+ message: string;
1144
+ body?: unknown;
1145
+ };
1146
+ } | Promise<{
1147
+ data: unknown;
1148
+ status: number;
1149
+ statusText: string;
1150
+ headers: Headers;
1151
+ url: string;
1152
+ ok: boolean;
1153
+ error?: {
1154
+ message: string;
1155
+ body?: unknown;
1156
+ };
1157
+ }>;
1158
+ }
1159
+
1160
+ /**
1161
+ * @fileoverview Rate limiting middleware implementation.
1162
+ */
1163
+
1164
+ /**
1165
+ * Creates rate limiting middleware - mainly for API quota management.
1166
+ * Note: Rate limiting is typically a server concern, but this can help with:
1167
+ * - Respecting API provider limits
1168
+ * - Preventing runaway requests in bulk operations
1169
+ * - Cost management for pay-per-request APIs
1170
+ */
1171
+ declare function createRateLimitMiddleware(options?: RateLimitOptions): FetchMiddleware;
1172
+
1173
+ /**
1174
+ * @fileoverview Rate limiting middleware - specialized use cases.
1175
+ */
1176
+
1177
+ /**
1178
+ * Rate limiting middleware - mainly for API quota management.
1179
+ * Note: This is primarily useful for specific scenarios like:
1180
+ * - Respecting third-party API limits
1181
+ * - Bulk operations that need throttling
1182
+ * - Pay-per-request API cost management
1183
+ */
1184
+ declare function useRateLimit(client: FetchClient, options?: RateLimitOptions): FetchClient;
1185
+
1186
+ /**
1187
+ * @fileoverview Retry middleware types and configuration.
1188
+ */
1189
+ /**
1190
+ * Retry configuration options - optimized for "pit of success".
1191
+ *
1192
+ * Smart defaults:
1193
+ * - 3 retries (4 total attempts)
1194
+ * - Exponential backoff starting at 1000ms
1195
+ * - Only retry on network errors and 5xx status codes
1196
+ */
1197
+ interface RetryOptions {
1198
+ /**
1199
+ * Maximum number of retry attempts (default: 3)
1200
+ * Total attempts will be maxRetries + 1
1201
+ */
1202
+ maxRetries?: number;
1203
+ /**
1204
+ * Initial delay in milliseconds (default: 1000)
1205
+ * Subsequent delays use exponential backoff
1206
+ */
1207
+ delay?: number;
1208
+ /**
1209
+ * Backoff strategy (default: 'exponential')
1210
+ * - 'exponential': delay * (2 ^ attempt)
1211
+ * - 'linear': delay * attempt
1212
+ * - 'fixed': always use delay
1213
+ */
1214
+ backoff?: 'exponential' | 'linear' | 'fixed';
1215
+ /**
1216
+ * Maximum delay cap in milliseconds (default: 30000 = 30s)
1217
+ * Prevents exponential backoff from getting too large
1218
+ */
1219
+ maxDelay?: number;
1220
+ /**
1221
+ * Custom function to determine if a response should be retried
1222
+ * Default: retry on network errors (status 0) and server errors (5xx)
1223
+ *
1224
+ * @param response - The fetch response or error
1225
+ * @param attempt - Current attempt number (1-based)
1226
+ * @returns true if request should be retried
1227
+ */
1228
+ shouldRetry?: (response: {
1229
+ status: number;
1230
+ ok: boolean;
1231
+ }, attempt: number) => boolean;
1232
+ /**
1233
+ * Optional callback called before each retry attempt
1234
+ * Useful for logging or analytics
1235
+ *
1236
+ * @param attempt - Current attempt number (1-based)
1237
+ * @param delay - Delay before this retry in ms
1238
+ * @param lastResponse - The failed response that triggered the retry
1239
+ */
1240
+ onRetry?: (attempt: number, delay: number, lastResponse: {
1241
+ status: number;
1242
+ statusText: string;
1243
+ }) => void;
1244
+ }
1245
+
1246
+ /**
1247
+ * @fileoverview Retry middleware implementation with enhanced architecture.
1248
+ */
1249
+
1250
+ /**
1251
+ * Creates a retry middleware with smart defaults.
1252
+ *
1253
+ * 🎯 PIT OF SUCCESS: Works great with no config, customizable when needed.
1254
+ *
1255
+ * Features:
1256
+ * - ✅ Preserves full middleware chain on retries (unlike old implementation)
1257
+ * - ✅ Exponential backoff with jitter
1258
+ * - ✅ Smart retry conditions (network errors + 5xx)
1259
+ * - ✅ Configurable but sensible defaults
1260
+ * - ✅ Type-safe configuration
1261
+ *
1262
+ * @param options - Retry configuration (all optional)
1263
+ * @returns Middleware function
1264
+ *
1265
+ * @example Basic usage:
1266
+ * ```typescript
1267
+ * const client = new FetchClient();
1268
+ * client.use(createRetryMiddleware()); // 3 retries with exponential backoff
1269
+ * ```
1270
+ *
1271
+ * @example Custom configuration:
1272
+ * ```typescript
1273
+ * const client = new FetchClient();
1274
+ * client.use(createRetryMiddleware({
1275
+ * maxRetries: 5,
1276
+ * delay: 500,
1277
+ * backoff: 'linear',
1278
+ * onRetry: (attempt, delay) => console.log(`Retry ${attempt} in ${delay}ms`)
1279
+ * }));
1280
+ * ```
1281
+ */
1282
+ declare function createRetryMiddleware(options?: RetryOptions): FetchMiddleware;
1283
+
1284
+ declare function useRetry(client: FetchClient, options?: RetryOptions): FetchClient;
1285
+
1286
+ /**
1287
+ * @fileoverview Complete middleware collection for FetchClient - "pit of success" APIs.
1288
+ *
1289
+ * This module provides a comprehensive set of middleware for common HTTP client concerns:
1290
+ * - 🔐 Authentication: Bearer token injection
1291
+ * - 🛡️ Authorization: 401/403 response handling
1292
+ * - 💾 Cache: Response caching with TTL
1293
+ * - 🔒 CSRF: Cross-site request forgery protection
1294
+ * - 📝 Logging: Request/response logging
1295
+ * - 🚦 Rate Limiting: Request rate limiting with token bucket
1296
+ * - 🔄 Retry: Automatic retry with backoff
1297
+ *
1298
+ * Each middleware follows the "pit of success" pattern with:
1299
+ * - Smart defaults for common scenarios
1300
+ * - Simple `use{Middleware}()` convenience functions
1301
+ * - Advanced `create{Middleware}Middleware()` for custom scenarios
1302
+ * - Comprehensive TypeScript support
1303
+ *
1304
+ * @example Quick setup with multiple middleware:
1305
+ * ```typescript
1306
+ * import { FetchClient } from '@fgrzl/fetch';
1307
+ * import { useAuthentication, useRetry, useLogging } from '@fgrzl/fetch/middleware';
1308
+ *
1309
+ * const client = new FetchClient();
1310
+ * const enhancedClient = useAuthentication(client, {
1311
+ * tokenProvider: () => localStorage.getItem('auth-token') || ''
1312
+ * })
1313
+ * .pipe(useRetry, { retries: 3 })
1314
+ * .pipe(useLogging);
1315
+ * ```
1316
+ */
1317
+
1318
+ /**
1319
+ * Production-ready middleware stack with authentication, retry, logging, and caching.
1320
+ * Perfect for API clients that need reliability and observability.
1321
+ *
1322
+ * @param client - The FetchClient to enhance
1323
+ * @param config - Configuration for each middleware
1324
+ * @returns Enhanced FetchClient with production middleware stack
1325
+ *
1326
+ * @example
1327
+ * ```typescript
1328
+ * const apiClient = useProductionStack(new FetchClient(), {
1329
+ * auth: { tokenProvider: () => getAuthToken() },
1330
+ * cache: { ttl: 5 * 60 * 1000 }, // 5 minutes
1331
+ * logging: { level: 'info' }
1332
+ * });
1333
+ * ```
1334
+ */
1335
+ declare function useProductionStack(client: FetchClient, config?: {
1336
+ auth?: Parameters<typeof useAuthentication>[1];
1337
+ retry?: Parameters<typeof useRetry>[1];
1338
+ cache?: Parameters<typeof useCache>[1];
1339
+ logging?: Parameters<typeof useLogging>[1];
1340
+ rateLimit?: Parameters<typeof useRateLimit>[1];
1341
+ }): FetchClient;
1342
+ /**
1343
+ * Development-friendly middleware stack with comprehensive logging and retries.
1344
+ * Perfect for local development and debugging.
1345
+ *
1346
+ * @param client - The FetchClient to enhance
1347
+ * @param config - Configuration for development middleware
1348
+ * @returns Enhanced FetchClient with development middleware stack
1349
+ *
1350
+ * @example
1351
+ * ```typescript
1352
+ * const devClient = useDevelopmentStack(new FetchClient(), {
1353
+ * auth: { tokenProvider: () => 'dev-token' }
1354
+ * });
1355
+ * ```
1356
+ */
1357
+ declare function useDevelopmentStack(client: FetchClient, config?: {
1358
+ auth?: Parameters<typeof useAuthentication>[1];
1359
+ }): FetchClient;
1360
+ /**
1361
+ * Basic middleware stack with just authentication and retry.
1362
+ * Perfect for simple API clients that need minimal overhead.
1363
+ *
1364
+ * @param client - The FetchClient to enhance
1365
+ * @param config - Basic configuration
1366
+ * @returns Enhanced FetchClient with basic middleware stack
1367
+ *
1368
+ * @example
1369
+ * ```typescript
1370
+ * const basicClient = useBasicStack(new FetchClient(), {
1371
+ * auth: { tokenProvider: () => getToken() }
1372
+ * });
1373
+ * ```
1374
+ */
1375
+ declare function useBasicStack(client: FetchClient, config: {
1376
+ auth: Parameters<typeof useAuthentication>[1];
1377
+ }): FetchClient;
1378
+
1
1379
  /**
2
1380
  * @fileoverview Main library entry point with "pit of success" architecture.
3
1381
  *
@@ -8,7 +1386,7 @@
8
1386
  * 4. Pre-built middleware stacks for common scenarios
9
1387
  * 5. Types for TypeScript users
10
1388
  */
11
- import { FetchClient } from './client/fetch-client';
1389
+
12
1390
  /**
13
1391
  * 🎯 PIT OF SUCCESS: Pre-configured fetch client (Level 1 - 80% of users)
14
1392
  *
@@ -54,12 +1432,5 @@ import { FetchClient } from './client/fetch-client';
54
1432
  * ```
55
1433
  */
56
1434
  declare const api: FetchClient;
57
- export default api;
58
- export { FetchClient } from './client/fetch-client';
59
- export { FetchError, HttpError, NetworkError } from './errors';
60
- export { useAuthentication, createAuthenticationMiddleware, useAuthorization, createAuthorizationMiddleware, useCache, createCacheMiddleware, useCSRF, useLogging, createLoggingMiddleware, useRateLimit, createRateLimitMiddleware, useRetry, createRetryMiddleware, } from './middleware';
61
- export { useProductionStack, useDevelopmentStack, useBasicStack, } from './middleware';
62
- export type { FetchMiddleware as InterceptMiddleware } from './client/fetch-client';
63
- export type { FetchResponse, FetchClientOptions } from './client/types';
64
- export type { AuthenticationOptions, AuthTokenProvider, AuthorizationOptions, UnauthorizedHandler, CacheOptions, CacheStorage, CacheEntry, CacheKeyGenerator, LoggingOptions, Logger, LogLevel, RateLimitOptions, RateLimitAlgorithm, RetryOptions, } from './middleware';
65
- //# sourceMappingURL=index.d.ts.map
1435
+
1436
+ export { type AuthTokenProvider, type AuthenticationOptions, type AuthorizationOptions, type CacheEntry, type CacheKeyGenerator, type CacheOptions, type CacheStorage, FetchClient, type FetchClientOptions, FetchError, type FetchResponse, HttpError, type FetchMiddleware as InterceptMiddleware, type LogLevel, type Logger, type LoggingOptions, NetworkError, type RateLimitAlgorithm, type RateLimitOptions, type RetryOptions, type UnauthorizedHandler, createAuthenticationMiddleware, createAuthorizationMiddleware, createCacheMiddleware, createLoggingMiddleware, createRateLimitMiddleware, createRetryMiddleware, api as default, useAuthentication, useAuthorization, useBasicStack, useCSRF, useCache, useDevelopmentStack, useLogging, useProductionStack, useRateLimit, useRetry };