@fgrzl/fetch 1.1.0-alpha.8 → 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/cjs/index.js CHANGED
@@ -1,118 +1,1123 @@
1
1
  "use strict";
2
- /**
3
- * @fileoverview Main library entry point with "pit of success" architecture.
4
- *
5
- * This module exports everything users need in order of discoverability:
6
- * 1. Pre-configured client with smart defaults (80% of users start here)
7
- * 2. FetchClient for custom configurations
8
- * 3. Individual middleware functions for specific needs
9
- * 4. Pre-built middleware stacks for common scenarios
10
- * 5. Types for TypeScript users
11
- */
12
- Object.defineProperty(exports, "__esModule", { value: true });
13
- exports.useBasicStack = exports.useDevelopmentStack = exports.useProductionStack = exports.createRetryMiddleware = exports.useRetry = exports.createRateLimitMiddleware = exports.useRateLimit = exports.createLoggingMiddleware = exports.useLogging = exports.useCSRF = exports.createCacheMiddleware = exports.useCache = exports.createAuthorizationMiddleware = exports.useAuthorization = exports.createAuthenticationMiddleware = exports.useAuthentication = exports.NetworkError = exports.HttpError = exports.FetchError = exports.FetchClient = void 0;
14
- const fetch_client_1 = require("./client/fetch-client");
15
- const middleware_1 = require("./middleware");
16
- /**
17
- * 🎯 PIT OF SUCCESS: Pre-configured fetch client (Level 1 - 80% of users)
18
- *
19
- * This client is ready to use out of the box with production-ready middleware:
20
- * - Authentication support (configure your token provider)
21
- * - Automatic retries with exponential backoff
22
- * - Response caching for GET requests
23
- * - Request/response logging
24
- * - Rate limiting protection
25
- * - Same-origin credentials for session-based auth (cookies)
26
- *
27
- * @example Just import and use:
28
- * ```typescript
29
- * import api from '@fgrzl/fetch';
30
- *
31
- * // Works immediately - no setup required!
32
- * const users = await api.get('/api/users');
33
- * const newUser = await api.post('/api/users', { name: 'John' });
34
- *
35
- * // With query parameters
36
- * const activeUsers = await api.get('/api/users', { status: 'active', limit: 10 });
37
- * ```
38
- *
39
- * @example Configure authentication:
40
- * ```typescript
41
- * import api from '@fgrzl/fetch';
42
- * import { useAuthentication } from '@fgrzl/fetch/middleware';
43
- *
44
- * const authClient = useAuthentication(api, {
45
- * tokenProvider: () => localStorage.getItem('auth-token') || ''
46
- * });
47
- * ```
48
- *
49
- * @example For token-only auth (no cookies):
50
- * ```typescript
51
- * import { FetchClient, useAuthentication } from '@fgrzl/fetch';
52
- *
53
- * const tokenClient = useAuthentication(new FetchClient({
54
- * credentials: 'omit' // Don't send cookies
55
- * }), {
56
- * tokenProvider: () => getJWTToken()
57
- * });
58
- * ```
59
- */
60
- const api = (0, middleware_1.useProductionStack)(new fetch_client_1.FetchClient({
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ FetchClient: () => FetchClient,
24
+ FetchError: () => FetchError,
25
+ HttpError: () => HttpError,
26
+ NetworkError: () => NetworkError,
27
+ createAuthenticationMiddleware: () => createAuthenticationMiddleware,
28
+ createAuthorizationMiddleware: () => createAuthorizationMiddleware,
29
+ createCacheMiddleware: () => createCacheMiddleware,
30
+ createLoggingMiddleware: () => createLoggingMiddleware,
31
+ createRateLimitMiddleware: () => createRateLimitMiddleware,
32
+ createRetryMiddleware: () => createRetryMiddleware,
33
+ default: () => index_default,
34
+ useAuthentication: () => useAuthentication,
35
+ useAuthorization: () => useAuthorization,
36
+ useBasicStack: () => useBasicStack,
37
+ useCSRF: () => useCSRF,
38
+ useCache: () => useCache,
39
+ useDevelopmentStack: () => useDevelopmentStack,
40
+ useLogging: () => useLogging,
41
+ useProductionStack: () => useProductionStack,
42
+ useRateLimit: () => useRateLimit,
43
+ useRetry: () => useRetry
44
+ });
45
+ module.exports = __toCommonJS(index_exports);
46
+
47
+ // src/client/fetch-client.ts
48
+ var FetchClient = class {
49
+ constructor(config = {}) {
50
+ this.middlewares = [];
51
+ this.credentials = config.credentials ?? "same-origin";
52
+ }
53
+ use(middleware) {
54
+ this.middlewares.push(middleware);
55
+ return this;
56
+ }
57
+ async request(url, init = {}) {
58
+ let index = 0;
59
+ const execute = async (request) => {
60
+ const currentRequest = request || { ...init, url };
61
+ const currentUrl = currentRequest.url || url;
62
+ if (index >= this.middlewares.length) {
63
+ const { url: _, ...requestInit } = currentRequest;
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
+ if (finalInit.headers instanceof Headers) {
83
+ const headersObj = {};
84
+ finalInit.headers.forEach((value, key) => {
85
+ headersObj[key] = value;
86
+ });
87
+ finalInit.headers = headersObj;
88
+ }
89
+ const response = await fetch(url, finalInit);
90
+ const data = await this.parseResponse(response);
91
+ return {
92
+ data: response.ok ? data : null,
93
+ status: response.status,
94
+ statusText: response.statusText,
95
+ headers: response.headers,
96
+ url: response.url,
97
+ ok: response.ok,
98
+ ...response.ok ? {} : {
99
+ error: {
100
+ message: response.statusText,
101
+ body: data
102
+ }
103
+ }
104
+ };
105
+ } catch (error) {
106
+ if (error instanceof TypeError && error.message.includes("fetch")) {
107
+ return {
108
+ data: null,
109
+ status: 0,
110
+ statusText: "Network Error",
111
+ headers: new Headers(),
112
+ url,
113
+ ok: false,
114
+ error: {
115
+ message: "Failed to fetch",
116
+ body: error
117
+ }
118
+ };
119
+ }
120
+ throw error;
121
+ }
122
+ }
123
+ async parseResponse(res) {
124
+ const contentType = res.headers.get("content-type") || "";
125
+ if (contentType.includes("application/json")) {
126
+ return res.json();
127
+ }
128
+ if (contentType.includes("text/")) {
129
+ return res.text();
130
+ }
131
+ if (contentType.includes("application/octet-stream") || contentType.includes("image/") || contentType.includes("video/") || contentType.includes("audio/")) {
132
+ return res.blob();
133
+ }
134
+ if (res.body) {
135
+ const text = await res.text();
136
+ return text || null;
137
+ }
138
+ return null;
139
+ }
140
+ // Helper method to build URL with query parameters
141
+ buildUrlWithParams(url, params) {
142
+ if (!params) {
143
+ return url;
144
+ }
145
+ const urlObj = new URL(
146
+ url,
147
+ url.startsWith("http") ? void 0 : "http://localhost"
148
+ );
149
+ Object.entries(params).forEach(([key, value]) => {
150
+ if (value !== void 0 && value !== null) {
151
+ urlObj.searchParams.set(key, String(value));
152
+ }
153
+ });
154
+ if (!url.startsWith("http")) {
155
+ return urlObj.pathname + urlObj.search;
156
+ }
157
+ return urlObj.toString();
158
+ }
159
+ // 🎯 PIT OF SUCCESS: Convenience methods with smart defaults
160
+ /**
161
+ * HEAD request with query parameter support.
162
+ *
163
+ * HEAD requests are used to retrieve metadata about a resource without downloading
164
+ * the response body. Useful for checking if a resource exists, getting content length,
165
+ * last modified date, etc.
166
+ *
167
+ * @template T - Expected response data type (will be null for HEAD requests)
168
+ * @param url - Request URL
169
+ * @param params - Query parameters to append to URL
170
+ * @returns Promise resolving to typed response (data will always be null)
171
+ *
172
+ * @example Check if resource exists:
173
+ * ```typescript
174
+ * const headResponse = await client.head('/api/large-file.zip');
175
+ * if (headResponse.ok) {
176
+ * const contentLength = headResponse.headers.get('content-length');
177
+ * const lastModified = headResponse.headers.get('last-modified');
178
+ * console.log(`File size: ${contentLength} bytes`);
179
+ * }
180
+ * ```
181
+ *
182
+ * @example Check with query parameters:
183
+ * ```typescript
184
+ * const exists = await client.head('/api/users', { id: 123 });
185
+ * if (exists.status === 404) {
186
+ * console.log('User not found');
187
+ * }
188
+ * ```
189
+ */
190
+ head(url, params) {
191
+ const finalUrl = this.buildUrlWithParams(url, params);
192
+ return this.request(finalUrl, { method: "HEAD" });
193
+ }
194
+ /**
195
+ * HEAD request that returns useful metadata about a resource.
196
+ *
197
+ * This is a convenience method that extracts common metadata from HEAD responses
198
+ * for easier consumption.
199
+ *
200
+ * @param url - Request URL
201
+ * @param params - Query parameters to append to URL
202
+ * @returns Promise resolving to response with extracted metadata
203
+ *
204
+ * @example Get resource metadata:
205
+ * ```typescript
206
+ * const metadata = await client.headMetadata('/api/large-file.zip');
207
+ * if (metadata.ok) {
208
+ * console.log('File exists:', metadata.exists);
209
+ * console.log('Content type:', metadata.contentType);
210
+ * console.log('Size:', metadata.contentLength, 'bytes');
211
+ * console.log('Last modified:', metadata.lastModified);
212
+ * }
213
+ * ```
214
+ */
215
+ async headMetadata(url, params) {
216
+ const response = await this.head(url, params);
217
+ const contentLengthHeader = response.headers.get("content-length");
218
+ const lastModifiedHeader = response.headers.get("last-modified");
219
+ return {
220
+ ...response,
221
+ exists: response.ok,
222
+ contentType: response.headers.get("content-type") || void 0,
223
+ contentLength: contentLengthHeader ? parseInt(contentLengthHeader, 10) : void 0,
224
+ lastModified: lastModifiedHeader ? new Date(lastModifiedHeader) : void 0,
225
+ etag: response.headers.get("etag") || void 0,
226
+ cacheControl: response.headers.get("cache-control") || void 0
227
+ };
228
+ }
229
+ /**
230
+ * GET request with query parameter support.
231
+ *
232
+ * @template T - Expected response data type
233
+ * @param url - Request URL
234
+ * @param params - Query parameters to append to URL
235
+ * @returns Promise resolving to typed response
236
+ *
237
+ * @example
238
+ * ```typescript
239
+ * const users = await client.get<User[]>('/api/users');
240
+ * const filteredUsers = await client.get<User[]>('/api/users', { status: 'active', limit: 10 });
241
+ * if (users.ok) console.log(users.data);
242
+ * ```
243
+ */
244
+ get(url, params) {
245
+ const finalUrl = this.buildUrlWithParams(url, params);
246
+ return this.request(finalUrl, { method: "GET" });
247
+ }
248
+ /**
249
+ * POST request with automatic JSON serialization.
250
+ *
251
+ * @template T - Expected response data type
252
+ * @param url - Request URL
253
+ * @param body - Request body (auto-serialized to JSON)
254
+ * @param headers - Additional headers (Content-Type: application/json is default)
255
+ * @returns Promise resolving to typed response
256
+ *
257
+ * @example
258
+ * ```typescript
259
+ * const result = await client.post<User>('/api/users', { name: 'John' });
260
+ * ```
261
+ */
262
+ post(url, body, headers) {
263
+ const requestHeaders = {
264
+ "Content-Type": "application/json",
265
+ ...headers ?? {}
266
+ };
267
+ return this.request(url, {
268
+ method: "POST",
269
+ headers: requestHeaders,
270
+ ...body !== void 0 ? { body: JSON.stringify(body) } : {}
271
+ });
272
+ }
273
+ /**
274
+ * PUT request with automatic JSON serialization.
275
+ *
276
+ * @template T - Expected response data type
277
+ * @param url - Request URL
278
+ * @param body - Request body (auto-serialized to JSON)
279
+ * @param headers - Additional headers (Content-Type: application/json is default)
280
+ * @returns Promise resolving to typed response
281
+ */
282
+ put(url, body, headers) {
283
+ const requestHeaders = {
284
+ "Content-Type": "application/json",
285
+ ...headers ?? {}
286
+ };
287
+ return this.request(url, {
288
+ method: "PUT",
289
+ headers: requestHeaders,
290
+ ...body !== void 0 ? { body: JSON.stringify(body) } : {}
291
+ });
292
+ }
293
+ /**
294
+ * PATCH request with automatic JSON serialization.
295
+ *
296
+ * @template T - Expected response data type
297
+ * @param url - Request URL
298
+ * @param body - Request body (auto-serialized to JSON)
299
+ * @param headers - Additional headers (Content-Type: application/json is default)
300
+ * @returns Promise resolving to typed response
301
+ */
302
+ patch(url, body, headers) {
303
+ const requestHeaders = {
304
+ "Content-Type": "application/json",
305
+ ...headers ?? {}
306
+ };
307
+ return this.request(url, {
308
+ method: "PATCH",
309
+ headers: requestHeaders,
310
+ ...body !== void 0 ? { body: JSON.stringify(body) } : {}
311
+ });
312
+ }
313
+ /**
314
+ * DELETE request with query parameter support.
315
+ *
316
+ * @template T - Expected response data type
317
+ * @param url - Request URL
318
+ * @param params - Query parameters to append to URL
319
+ * @returns Promise resolving to typed response
320
+ *
321
+ * @example
322
+ * ```typescript
323
+ * const result = await client.del('/api/users/123');
324
+ * const bulkResult = await client.del('/api/users', { status: 'inactive', force: true });
325
+ * if (result.ok) console.log('Deleted successfully');
326
+ * ```
327
+ */
328
+ del(url, params) {
329
+ const finalUrl = this.buildUrlWithParams(url, params);
330
+ return this.request(finalUrl, { method: "DELETE" });
331
+ }
332
+ };
333
+
334
+ // src/middleware/authentication/authentication.ts
335
+ function shouldSkipAuth(url, skipPatterns = []) {
336
+ return skipPatterns.some((pattern) => {
337
+ if (typeof pattern === "string") {
338
+ return url.includes(pattern);
339
+ }
340
+ return pattern.test(url);
341
+ });
342
+ }
343
+ function shouldIncludeAuth(url, includePatterns) {
344
+ if (!includePatterns || includePatterns.length === 0) {
345
+ return true;
346
+ }
347
+ return includePatterns.some((pattern) => {
348
+ if (typeof pattern === "string") {
349
+ return url.includes(pattern);
350
+ }
351
+ return pattern.test(url);
352
+ });
353
+ }
354
+ function createAuthenticationMiddleware(options) {
355
+ const {
356
+ tokenProvider,
357
+ headerName = "Authorization",
358
+ tokenType = "Bearer",
359
+ skipPatterns = [],
360
+ includePatterns
361
+ } = options;
362
+ return async (request, next) => {
363
+ const url = request.url || "";
364
+ const parsedUrl = new URL(url);
365
+ const pathname = parsedUrl.pathname;
366
+ if (shouldSkipAuth(pathname, skipPatterns) || !shouldIncludeAuth(pathname, includePatterns)) {
367
+ return next(request);
368
+ }
369
+ try {
370
+ const token = await tokenProvider();
371
+ if (!token) {
372
+ return next(request);
373
+ }
374
+ const headers = new Headers(request.headers);
375
+ headers.set(headerName, `${tokenType} ${token}`);
376
+ const modifiedRequest = {
377
+ ...request,
378
+ headers
379
+ };
380
+ return next(modifiedRequest);
381
+ } catch {
382
+ return next(request);
383
+ }
384
+ };
385
+ }
386
+
387
+ // src/middleware/authentication/index.ts
388
+ function useAuthentication(client, options) {
389
+ return client.use(createAuthenticationMiddleware(options));
390
+ }
391
+
392
+ // src/middleware/authorization/authorization.ts
393
+ function createRedirectHandler(config = {}) {
394
+ const {
395
+ redirectPath = "/login",
396
+ returnUrlParam = "return_url",
397
+ includeReturnUrl = true
398
+ } = config;
399
+ return () => {
400
+ let redirectUrl = redirectPath;
401
+ if (includeReturnUrl && typeof window !== "undefined") {
402
+ const currentUrl = encodeURIComponent(window.location.href);
403
+ const separator = redirectPath.includes("?") ? "&" : "?";
404
+ redirectUrl = `${redirectPath}${separator}${returnUrlParam}=${currentUrl}`;
405
+ }
406
+ if (typeof window !== "undefined") {
407
+ window.location.href = redirectUrl;
408
+ }
409
+ };
410
+ }
411
+ function selectUnauthorizedHandler(providedHandler, redirectConfig) {
412
+ if (providedHandler) {
413
+ return providedHandler;
414
+ }
415
+ return createRedirectHandler(redirectConfig);
416
+ }
417
+ function shouldSkipAuth2(url, skipPatterns = []) {
418
+ let pathname;
419
+ try {
420
+ pathname = new URL(url).pathname;
421
+ } catch {
422
+ pathname = url;
423
+ }
424
+ return skipPatterns.some((pattern) => {
425
+ if (typeof pattern === "string") {
426
+ return pathname.includes(pattern);
427
+ }
428
+ return pattern.test(pathname);
429
+ });
430
+ }
431
+ function createAuthorizationMiddleware(options = {}) {
432
+ const {
433
+ onUnauthorized: providedOnUnauthorized,
434
+ redirectConfig,
435
+ onForbidden,
436
+ skipPatterns = [],
437
+ statusCodes = [401]
438
+ } = options;
439
+ const onUnauthorized = selectUnauthorizedHandler(
440
+ providedOnUnauthorized,
441
+ redirectConfig
442
+ );
443
+ return async (request, next) => {
444
+ const url = request.url || "";
445
+ if (shouldSkipAuth2(url, skipPatterns)) {
446
+ return next(request);
447
+ }
448
+ const response = await next(request);
449
+ if (statusCodes.includes(response.status)) {
450
+ try {
451
+ if (response.status === 401 && onUnauthorized) {
452
+ await onUnauthorized(response, request);
453
+ } else if (response.status === 403 && onForbidden) {
454
+ await onForbidden(response, request);
455
+ } else if (onUnauthorized) {
456
+ await onUnauthorized(response, request);
457
+ }
458
+ } catch (error) {
459
+ console.warn("Authorization handler failed:", error);
460
+ }
461
+ }
462
+ return response;
463
+ };
464
+ }
465
+
466
+ // src/middleware/authorization/index.ts
467
+ function useAuthorization(client, options = {}) {
468
+ return client.use(createAuthorizationMiddleware(options));
469
+ }
470
+
471
+ // src/middleware/cache/cache.ts
472
+ var MemoryStorage = class {
473
+ constructor() {
474
+ this.cache = /* @__PURE__ */ new Map();
475
+ }
476
+ async get(key) {
477
+ const entry = this.cache.get(key);
478
+ if (!entry) {
479
+ return null;
480
+ }
481
+ if (Date.now() > entry.expiresAt) {
482
+ this.cache.delete(key);
483
+ return null;
484
+ }
485
+ return entry;
486
+ }
487
+ async getWithExpiry(key) {
488
+ const entry = this.cache.get(key);
489
+ if (!entry) {
490
+ return { entry: null, isExpired: false };
491
+ }
492
+ const isExpired = Date.now() > entry.expiresAt;
493
+ return { entry, isExpired };
494
+ }
495
+ async set(key, entry) {
496
+ this.cache.set(key, entry);
497
+ }
498
+ async delete(key) {
499
+ this.cache.delete(key);
500
+ }
501
+ async clear() {
502
+ this.cache.clear();
503
+ }
504
+ };
505
+ var defaultKeyGenerator = (request) => {
506
+ const url = request.url || "";
507
+ const method = request.method || "GET";
508
+ const headers = request.headers ? JSON.stringify(request.headers) : "";
509
+ return `${method}:${url}:${headers}`;
510
+ };
511
+ function shouldSkipCache(url, skipPatterns = []) {
512
+ return skipPatterns.some((pattern) => {
513
+ if (typeof pattern === "string") {
514
+ return url.includes(pattern);
515
+ }
516
+ return pattern.test(url);
517
+ });
518
+ }
519
+ function createCacheMiddleware(options = {}) {
520
+ const {
521
+ ttl = 5 * 60 * 1e3,
522
+ // 5 minutes
523
+ methods = ["GET"],
524
+ storage = new MemoryStorage(),
525
+ keyGenerator = defaultKeyGenerator,
526
+ skipPatterns = [],
527
+ staleWhileRevalidate = false
528
+ } = options;
529
+ return async (request, next) => {
530
+ const method = (request.method || "GET").toUpperCase();
531
+ const url = request.url || "";
532
+ if (!methods.includes(method) || shouldSkipCache(url, skipPatterns)) {
533
+ return next(request);
534
+ }
535
+ const cacheKey = keyGenerator(request);
536
+ try {
537
+ const { entry: cached, isExpired } = storage.getWithExpiry ? await storage.getWithExpiry(cacheKey) : await (async () => {
538
+ const entry = await storage.get(cacheKey);
539
+ return { entry, isExpired: false };
540
+ })();
541
+ if (cached && !isExpired) {
542
+ return {
543
+ ...cached.response,
544
+ headers: new Headers(cached.response.headers),
545
+ data: cached.response.data
546
+ };
547
+ }
548
+ if (cached && staleWhileRevalidate) {
549
+ const cachedResponse = {
550
+ ...cached.response,
551
+ headers: new Headers(cached.response.headers),
552
+ data: cached.response.data
553
+ };
554
+ if (isExpired) {
555
+ next(request).then(async (freshResponse) => {
556
+ const headersObj = {};
557
+ freshResponse.headers.forEach((value, key) => {
558
+ headersObj[key] = value;
559
+ });
560
+ const cacheEntry = {
561
+ response: {
562
+ status: freshResponse.status,
563
+ statusText: freshResponse.statusText,
564
+ headers: headersObj,
565
+ data: freshResponse.data
566
+ },
567
+ timestamp: Date.now(),
568
+ expiresAt: Date.now() + ttl
569
+ };
570
+ await storage.set(cacheKey, cacheEntry);
571
+ }).catch(() => {
572
+ });
573
+ }
574
+ return cachedResponse;
575
+ }
576
+ const response = await next(request);
577
+ if (response.ok) {
578
+ try {
579
+ const headersObj = {};
580
+ response.headers.forEach((value, key) => {
581
+ headersObj[key] = value;
582
+ });
583
+ const cacheEntry = {
584
+ response: {
585
+ status: response.status,
586
+ statusText: response.statusText,
587
+ headers: headersObj,
588
+ data: response.data
589
+ },
590
+ timestamp: Date.now(),
591
+ expiresAt: Date.now() + ttl
592
+ };
593
+ await storage.set(cacheKey, cacheEntry);
594
+ } catch {
595
+ }
596
+ }
597
+ return response;
598
+ } catch (error) {
599
+ if (error && typeof error === "object" && "message" in error) {
600
+ const errorMessage = error.message;
601
+ if (errorMessage.includes("Network") || errorMessage.includes("fetch")) {
602
+ throw error;
603
+ }
604
+ }
605
+ return next(request);
606
+ }
607
+ };
608
+ }
609
+
610
+ // src/middleware/cache/index.ts
611
+ function useCache(client, options = {}) {
612
+ return client.use(createCacheMiddleware(options));
613
+ }
614
+
615
+ // src/middleware/csrf/csrf.ts
616
+ function getTokenFromCookie(cookieName = "XSRF-TOKEN") {
617
+ if (typeof document === "undefined") {
618
+ return "";
619
+ }
620
+ const name = `${cookieName}=`;
621
+ const decodedCookie = decodeURIComponent(document.cookie);
622
+ const cookies = decodedCookie.split(";");
623
+ for (const cookie of cookies) {
624
+ const c = cookie.trim();
625
+ if (c.indexOf(name) === 0) {
626
+ return c.substring(name.length);
627
+ }
628
+ }
629
+ return "";
630
+ }
631
+ function shouldSkipCSRF(url, skipPatterns = []) {
632
+ return skipPatterns.some((pattern) => {
633
+ if (typeof pattern === "string") {
634
+ return url.includes(pattern);
635
+ }
636
+ return pattern.test(url);
637
+ });
638
+ }
639
+ function createCSRFMiddleware(options = {}) {
640
+ const {
641
+ headerName = "X-XSRF-TOKEN",
642
+ cookieName = "XSRF-TOKEN",
643
+ protectedMethods = ["POST", "PUT", "PATCH", "DELETE"],
644
+ skipPatterns = [],
645
+ tokenProvider = () => getTokenFromCookie(cookieName)
646
+ } = options;
647
+ return async (request, next) => {
648
+ const method = (request.method || "GET").toUpperCase();
649
+ const url = request.url || "";
650
+ if (!protectedMethods.includes(method) || shouldSkipCSRF(url, skipPatterns)) {
651
+ return next(request);
652
+ }
653
+ const token = tokenProvider();
654
+ if (!token) {
655
+ return next(request);
656
+ }
657
+ const headers = new Headers(request.headers);
658
+ headers.set(headerName, token);
659
+ const modifiedRequest = {
660
+ ...request,
661
+ headers
662
+ };
663
+ return next(modifiedRequest);
664
+ };
665
+ }
666
+
667
+ // src/middleware/csrf/index.ts
668
+ function useCSRF(client, options = {}) {
669
+ return client.use(createCSRFMiddleware(options));
670
+ }
671
+
672
+ // src/middleware/logging/logging.ts
673
+ var defaultLogger = {
674
+ // eslint-disable-next-line no-console -- allow console.debug in logger implementation
675
+ debug: (message, data) => console.debug(message, data),
676
+ // eslint-disable-next-line no-console -- allow console.info in logger implementation
677
+ info: (message, data) => console.info(message, data),
678
+ // eslint-disable-next-line no-console -- allow console.warn in logger implementation
679
+ warn: (message, data) => console.warn(message, data),
680
+ // eslint-disable-next-line no-console -- allow console.error in logger implementation
681
+ error: (message, data) => console.error(message, data)
682
+ };
683
+ var LOG_LEVELS = {
684
+ debug: 0,
685
+ info: 1,
686
+ warn: 2,
687
+ error: 3
688
+ };
689
+ var defaultFormatter = (entry) => {
690
+ const { method, url, status, duration } = entry;
691
+ let message = `${method} ${url}`;
692
+ if (status) {
693
+ message += ` \u2192 ${status}`;
694
+ }
695
+ if (duration) {
696
+ message += ` (${duration}ms)`;
697
+ }
698
+ return message;
699
+ };
700
+ function shouldSkipLogging(url, skipPatterns = []) {
701
+ return skipPatterns.some((pattern) => {
702
+ if (typeof pattern === "string") {
703
+ return url.includes(pattern);
704
+ }
705
+ return pattern.test(url);
706
+ });
707
+ }
708
+ function createLoggingMiddleware(options = {}) {
709
+ const {
710
+ level = "info",
711
+ logger = defaultLogger,
712
+ includeRequestHeaders = false,
713
+ includeResponseHeaders = false,
714
+ includeRequestBody = false,
715
+ includeResponseBody = false,
716
+ skipPatterns = [],
717
+ formatter = defaultFormatter
718
+ } = options;
719
+ const minLevel = LOG_LEVELS[level];
720
+ return async (request, next) => {
721
+ const url = request.url || "";
722
+ const method = (request.method || "GET").toUpperCase();
723
+ if (shouldSkipLogging(url, skipPatterns)) {
724
+ return next(request);
725
+ }
726
+ const startTime = Date.now();
727
+ if (LOG_LEVELS.debug >= minLevel) {
728
+ const requestHeaders = includeRequestHeaders ? getHeadersObject(
729
+ request.headers
730
+ ) : void 0;
731
+ const requestBody = includeRequestBody ? request.body : void 0;
732
+ const requestEntry = {
733
+ level: "debug",
734
+ timestamp: startTime,
735
+ method,
736
+ url,
737
+ ...requestHeaders && { requestHeaders },
738
+ ...requestBody && { requestBody }
739
+ };
740
+ logger.debug(`\u2192 ${formatter(requestEntry)}`, requestEntry);
741
+ }
742
+ try {
743
+ const response = await next(request);
744
+ const duration = Date.now() - startTime;
745
+ const logLevel = response.status >= 400 ? "error" : "info";
746
+ if (LOG_LEVELS[logLevel] >= minLevel) {
747
+ const responseHeaders = includeResponseHeaders ? getHeadersObject(response.headers) : void 0;
748
+ const responseBody = includeResponseBody ? response.data : void 0;
749
+ const responseEntry = {
750
+ level: logLevel,
751
+ timestamp: Date.now(),
752
+ method,
753
+ url,
754
+ status: response.status,
755
+ duration,
756
+ ...responseHeaders ? { responseHeaders } : {},
757
+ ...responseBody !== void 0 ? { responseBody } : {}
758
+ };
759
+ const logMessage = `\u2190 ${formatter(responseEntry)}`;
760
+ if (logLevel === "error") {
761
+ logger.error(logMessage, responseEntry);
762
+ } else {
763
+ logger.info(logMessage, responseEntry);
764
+ }
765
+ }
766
+ return response;
767
+ } catch (error) {
768
+ const duration = Date.now() - startTime;
769
+ if (LOG_LEVELS.error >= minLevel) {
770
+ const errorEntry = {
771
+ level: "error",
772
+ timestamp: Date.now(),
773
+ method,
774
+ url,
775
+ duration,
776
+ error: error instanceof Error ? error : new Error(String(error))
777
+ };
778
+ logger.error(`\u2717 ${formatter(errorEntry)}`, errorEntry);
779
+ }
780
+ throw error;
781
+ }
782
+ };
783
+ }
784
+ function getHeadersObject(headers) {
785
+ if (!headers) {
786
+ return void 0;
787
+ }
788
+ const obj = {};
789
+ if (headers instanceof Headers) {
790
+ headers.forEach((value, key) => {
791
+ obj[key] = value;
792
+ });
793
+ return obj;
794
+ } else {
795
+ return headers;
796
+ }
797
+ }
798
+
799
+ // src/middleware/logging/index.ts
800
+ function useLogging(client, options = {}) {
801
+ return client.use(createLoggingMiddleware(options));
802
+ }
803
+
804
+ // src/middleware/rate-limit/rate-limit.ts
805
+ var TokenBucket = class {
806
+ constructor(maxTokens, refillRate, timeProvider = () => Date.now()) {
807
+ this.maxTokens = maxTokens;
808
+ this.refillRate = refillRate;
809
+ this.timeProvider = timeProvider;
810
+ this.tokens = maxTokens;
811
+ this.lastRefill = this.timeProvider();
812
+ }
813
+ tryConsume() {
814
+ this.refill();
815
+ if (this.tokens >= 1) {
816
+ this.tokens--;
817
+ return { allowed: true };
818
+ }
819
+ const retryAfter = (1 - this.tokens) / this.refillRate;
820
+ return { allowed: false, retryAfter: Math.ceil(retryAfter) };
821
+ }
822
+ refill() {
823
+ const now = this.timeProvider();
824
+ const timePassed = now - this.lastRefill;
825
+ const tokensToAdd = timePassed * this.refillRate;
826
+ this.tokens = Math.min(this.maxTokens, this.tokens + tokensToAdd);
827
+ this.lastRefill = now;
828
+ }
829
+ };
830
+ function createRateLimitMiddleware(options = {}) {
831
+ const {
832
+ maxRequests = 60,
833
+ windowMs = 6e4,
834
+ keyGenerator = () => "default",
835
+ skipPatterns = [],
836
+ onRateLimitExceeded
837
+ } = options;
838
+ const buckets = /* @__PURE__ */ new Map();
839
+ const refillRate = maxRequests / windowMs;
840
+ return async (request, next) => {
841
+ const url = request.url || "";
842
+ if (skipPatterns.some(
843
+ (pattern) => typeof pattern === "string" ? url.includes(pattern) : pattern.test(url)
844
+ )) {
845
+ return next(request);
846
+ }
847
+ const key = keyGenerator(request);
848
+ if (!buckets.has(key)) {
849
+ buckets.set(key, new TokenBucket(maxRequests, refillRate));
850
+ }
851
+ const bucket = buckets.get(key);
852
+ const result = bucket.tryConsume();
853
+ if (!result.allowed) {
854
+ if (onRateLimitExceeded) {
855
+ const customResponse = await onRateLimitExceeded(
856
+ result.retryAfter || 0,
857
+ request
858
+ );
859
+ if (customResponse) {
860
+ return customResponse;
861
+ }
862
+ }
863
+ return {
864
+ data: null,
865
+ status: 429,
866
+ statusText: "Too Many Requests",
867
+ headers: new Headers({
868
+ "Retry-After": Math.ceil((result.retryAfter || 0) / 1e3).toString()
869
+ }),
870
+ url: request.url || "",
871
+ ok: false,
872
+ error: {
873
+ message: `Rate limit exceeded. Retry after ${result.retryAfter}ms`,
874
+ body: { retryAfter: result.retryAfter }
875
+ }
876
+ };
877
+ }
878
+ return next(request);
879
+ };
880
+ }
881
+
882
+ // src/middleware/rate-limit/index.ts
883
+ function useRateLimit(client, options = {}) {
884
+ return client.use(createRateLimitMiddleware(options));
885
+ }
886
+
887
+ // src/middleware/retry/retry.ts
888
+ var defaultShouldRetry = (response) => {
889
+ return response.status === 0 || response.status >= 500 && response.status < 600;
890
+ };
891
+ var calculateDelay = (attempt, baseDelay, backoff, maxDelay) => {
892
+ let delay;
893
+ switch (backoff) {
894
+ case "exponential":
895
+ delay = baseDelay * Math.pow(2, attempt - 1);
896
+ break;
897
+ case "linear":
898
+ delay = baseDelay * attempt;
899
+ break;
900
+ case "fixed":
901
+ default:
902
+ delay = baseDelay;
903
+ break;
904
+ }
905
+ return Math.min(delay, maxDelay);
906
+ };
907
+ var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
908
+ function createRetryMiddleware(options = {}) {
909
+ const {
910
+ maxRetries = 3,
911
+ delay = 1e3,
912
+ backoff = "exponential",
913
+ maxDelay = 3e4,
914
+ shouldRetry = defaultShouldRetry,
915
+ onRetry
916
+ } = options;
917
+ return async (request, next) => {
918
+ let lastResponse;
919
+ let attempt = 0;
920
+ while (attempt <= maxRetries) {
921
+ try {
922
+ const response = await next(request);
923
+ if (response.ok) {
924
+ return response;
925
+ }
926
+ if (!shouldRetry(
927
+ { status: response.status, ok: response.ok },
928
+ attempt + 1
929
+ )) {
930
+ return response;
931
+ }
932
+ if (attempt >= maxRetries) {
933
+ return response;
934
+ }
935
+ lastResponse = response;
936
+ attempt++;
937
+ const retryDelay = calculateDelay(attempt, delay, backoff, maxDelay);
938
+ if (onRetry) {
939
+ onRetry(attempt, retryDelay, {
940
+ status: response.status,
941
+ statusText: response.statusText
942
+ });
943
+ }
944
+ await sleep(retryDelay);
945
+ } catch (error) {
946
+ const errorResponse = {
947
+ data: null,
948
+ status: 0,
949
+ statusText: "Network Error",
950
+ headers: new Headers(),
951
+ url: request.url || "",
952
+ ok: false,
953
+ error: {
954
+ message: error instanceof Error ? error.message : "Unknown error",
955
+ body: error
956
+ }
957
+ };
958
+ if (!shouldRetry(errorResponse, attempt + 1)) {
959
+ return errorResponse;
960
+ }
961
+ if (attempt >= maxRetries) {
962
+ return errorResponse;
963
+ }
964
+ lastResponse = errorResponse;
965
+ attempt++;
966
+ const retryDelay = calculateDelay(attempt, delay, backoff, maxDelay);
967
+ if (onRetry) {
968
+ onRetry(attempt, retryDelay, {
969
+ status: errorResponse.status,
970
+ statusText: errorResponse.statusText
971
+ });
972
+ }
973
+ await sleep(retryDelay);
974
+ }
975
+ }
976
+ return lastResponse;
977
+ };
978
+ }
979
+
980
+ // src/middleware/retry/index.ts
981
+ function useRetry(client, options = {}) {
982
+ return client.use(createRetryMiddleware(options));
983
+ }
984
+
985
+ // src/middleware/index.ts
986
+ function useProductionStack(client, config = {}) {
987
+ let enhanced = client;
988
+ if (config.auth) {
989
+ enhanced = useAuthentication(enhanced, config.auth);
990
+ }
991
+ if (config.cache !== void 0) {
992
+ enhanced = useCache(enhanced, config.cache);
993
+ }
994
+ if (config.retry !== void 0) {
995
+ enhanced = useRetry(enhanced, config.retry);
996
+ }
997
+ if (config.rateLimit !== void 0) {
998
+ enhanced = useRateLimit(enhanced, config.rateLimit);
999
+ }
1000
+ if (config.logging !== void 0) {
1001
+ enhanced = useLogging(enhanced, config.logging);
1002
+ }
1003
+ return enhanced;
1004
+ }
1005
+ function useDevelopmentStack(client, config = {}) {
1006
+ let enhanced = client;
1007
+ if (config.auth) {
1008
+ enhanced = useAuthentication(enhanced, config.auth);
1009
+ }
1010
+ enhanced = useRetry(enhanced, {
1011
+ maxRetries: 1,
1012
+ delay: 100
1013
+ });
1014
+ enhanced = useLogging(enhanced, {
1015
+ level: "debug",
1016
+ includeRequestHeaders: true,
1017
+ includeResponseHeaders: true,
1018
+ includeRequestBody: true,
1019
+ includeResponseBody: true
1020
+ });
1021
+ return enhanced;
1022
+ }
1023
+ function useBasicStack(client, config) {
1024
+ return useRetry(useAuthentication(client, config.auth), { maxRetries: 2 });
1025
+ }
1026
+
1027
+ // src/errors/index.ts
1028
+ var FetchError = class extends Error {
1029
+ /**
1030
+ * Creates a new FetchError.
1031
+ * @param message - Error message
1032
+ * @param cause - Optional underlying cause
1033
+ */
1034
+ constructor(message, cause) {
1035
+ super(message);
1036
+ this.name = "FetchError";
1037
+ if (cause !== void 0) {
1038
+ this.cause = cause;
1039
+ }
1040
+ }
1041
+ };
1042
+ var HttpError = class extends FetchError {
1043
+ /**
1044
+ * Creates a new HttpError.
1045
+ * @param status - HTTP status code
1046
+ * @param statusText - HTTP status text
1047
+ * @param body - Response body
1048
+ * @param url - The request URL
1049
+ */
1050
+ constructor(status, statusText, body, url) {
1051
+ super(`HTTP ${status} ${statusText} at ${url}`);
1052
+ this.name = "HttpError";
1053
+ this.status = status;
1054
+ this.statusText = statusText;
1055
+ this.body = body;
1056
+ }
1057
+ };
1058
+ var NetworkError = class extends FetchError {
1059
+ /**
1060
+ * Creates a new NetworkError.
1061
+ * @param message - Error message
1062
+ * @param url - The request URL
1063
+ * @param cause - The underlying network error
1064
+ */
1065
+ constructor(message, url, cause) {
1066
+ super(`Network error for ${url}: ${message}`, cause);
1067
+ this.name = "NetworkError";
1068
+ }
1069
+ };
1070
+
1071
+ // src/index.ts
1072
+ var api = useProductionStack(
1073
+ new FetchClient({
61
1074
  // Smart default: include cookies for session-based auth
62
1075
  // Can be overridden by creating a custom FetchClient
63
- credentials: 'same-origin',
64
- }), {
1076
+ credentials: "same-origin"
1077
+ }),
1078
+ {
65
1079
  // Smart defaults - users can override as needed
66
1080
  retry: {
67
- maxRetries: 2,
68
- delay: 1000,
1081
+ maxRetries: 2,
1082
+ delay: 1e3
69
1083
  },
70
1084
  cache: {
71
- ttl: 5 * 60 * 1000, // 5 minutes
72
- methods: ['GET'],
1085
+ ttl: 5 * 60 * 1e3,
1086
+ // 5 minutes
1087
+ methods: ["GET"]
73
1088
  },
74
1089
  logging: {
75
- level: 'info',
1090
+ level: "info"
76
1091
  },
77
1092
  rateLimit: {
78
- maxRequests: 100,
79
- windowMs: 60 * 1000, // 100 requests per minute
80
- },
1093
+ maxRequests: 100,
1094
+ windowMs: 60 * 1e3
1095
+ // 100 requests per minute
1096
+ }
1097
+ }
1098
+ );
1099
+ var index_default = api;
1100
+ // Annotate the CommonJS export names for ESM import in node:
1101
+ 0 && (module.exports = {
1102
+ FetchClient,
1103
+ FetchError,
1104
+ HttpError,
1105
+ NetworkError,
1106
+ createAuthenticationMiddleware,
1107
+ createAuthorizationMiddleware,
1108
+ createCacheMiddleware,
1109
+ createLoggingMiddleware,
1110
+ createRateLimitMiddleware,
1111
+ createRetryMiddleware,
1112
+ useAuthentication,
1113
+ useAuthorization,
1114
+ useBasicStack,
1115
+ useCSRF,
1116
+ useCache,
1117
+ useDevelopmentStack,
1118
+ useLogging,
1119
+ useProductionStack,
1120
+ useRateLimit,
1121
+ useRetry
81
1122
  });
82
- // 🎯 LEVEL 1: Export the production-ready client as default
83
- exports.default = api;
84
- // 🎯 LEVEL 2: FetchClient for custom configurations
85
- var fetch_client_2 = require("./client/fetch-client");
86
- Object.defineProperty(exports, "FetchClient", { enumerable: true, get: function () { return fetch_client_2.FetchClient; } });
87
- var errors_1 = require("./errors");
88
- Object.defineProperty(exports, "FetchError", { enumerable: true, get: function () { return errors_1.FetchError; } });
89
- Object.defineProperty(exports, "HttpError", { enumerable: true, get: function () { return errors_1.HttpError; } });
90
- Object.defineProperty(exports, "NetworkError", { enumerable: true, get: function () { return errors_1.NetworkError; } });
91
- // 🎯 LEVEL 3: Individual middleware functions (import from our comprehensive middleware index)
92
- var middleware_2 = require("./middleware");
93
- // Authentication
94
- Object.defineProperty(exports, "useAuthentication", { enumerable: true, get: function () { return middleware_2.useAuthentication; } });
95
- Object.defineProperty(exports, "createAuthenticationMiddleware", { enumerable: true, get: function () { return middleware_2.createAuthenticationMiddleware; } });
96
- // Authorization
97
- Object.defineProperty(exports, "useAuthorization", { enumerable: true, get: function () { return middleware_2.useAuthorization; } });
98
- Object.defineProperty(exports, "createAuthorizationMiddleware", { enumerable: true, get: function () { return middleware_2.createAuthorizationMiddleware; } });
99
- // Cache
100
- Object.defineProperty(exports, "useCache", { enumerable: true, get: function () { return middleware_2.useCache; } });
101
- Object.defineProperty(exports, "createCacheMiddleware", { enumerable: true, get: function () { return middleware_2.createCacheMiddleware; } });
102
- // CSRF
103
- Object.defineProperty(exports, "useCSRF", { enumerable: true, get: function () { return middleware_2.useCSRF; } });
104
- // Logging
105
- Object.defineProperty(exports, "useLogging", { enumerable: true, get: function () { return middleware_2.useLogging; } });
106
- Object.defineProperty(exports, "createLoggingMiddleware", { enumerable: true, get: function () { return middleware_2.createLoggingMiddleware; } });
107
- // Rate Limiting
108
- Object.defineProperty(exports, "useRateLimit", { enumerable: true, get: function () { return middleware_2.useRateLimit; } });
109
- Object.defineProperty(exports, "createRateLimitMiddleware", { enumerable: true, get: function () { return middleware_2.createRateLimitMiddleware; } });
110
- // Retry
111
- Object.defineProperty(exports, "useRetry", { enumerable: true, get: function () { return middleware_2.useRetry; } });
112
- Object.defineProperty(exports, "createRetryMiddleware", { enumerable: true, get: function () { return middleware_2.createRetryMiddleware; } });
113
- // 🎯 LEVEL 4: Pre-built middleware stacks for common scenarios
114
- var middleware_3 = require("./middleware");
115
- Object.defineProperty(exports, "useProductionStack", { enumerable: true, get: function () { return middleware_3.useProductionStack; } });
116
- Object.defineProperty(exports, "useDevelopmentStack", { enumerable: true, get: function () { return middleware_3.useDevelopmentStack; } });
117
- Object.defineProperty(exports, "useBasicStack", { enumerable: true, get: function () { return middleware_3.useBasicStack; } });
118
1123
  //# sourceMappingURL=index.js.map