zlient 3.0.0 → 3.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.
package/README.md CHANGED
@@ -6,28 +6,36 @@
6
6
  ![License](https://img.shields.io/npm/l/zlient?style=flat-square)
7
7
  ![Downloads](https://img.shields.io/npm/dm/zlient?style=flat-square)
8
8
 
9
- Build robust, type-safe API clients with automatic Zod validation, retry logic, and zero boilerplate.
9
+ Build robust, type-safe API clients with runtime validation, retry logic, and zero boilerplate. Use **any** [Standard Schema](https://standardschema.dev) library — Zod, Valibot, ArkType, and more.
10
10
 
11
11
  ## Features
12
12
 
13
- - **Functional API**: Define endpoints with pure functions and automatic type inference.
14
- - **Type-Safe**: Full TypeScript support. Arguments and responses are strictly typed.
15
- - **Zod Validation**: Runtime validation for requests, responses, query params, and path params.
16
- - **Resilience**: Built-in exponential backoff retries and timeouts.
17
- - **Auth**: Logic-safe authentication providers (Bearer, API Key, Custom) that handle edge cases.
18
- - **Observability**: Hooks for structured logging and metrics.
13
+ - **Standard Schema**: Use Zod, Valibot, ArkType, or any compatible validator. No lock-in.
14
+ - **Functional API**: Define endpoints with pure functions and automatic type inference.
15
+ - **Type-Safe**: Full TypeScript support. Arguments and responses are strictly typed.
16
+ - **Runtime Validation**: Validate requests, responses, query params, and path params.
17
+ - **Resilience**: Built-in exponential backoff retries and timeouts.
18
+ - **Auth**: Logic-safe authentication providers (Bearer, API Key, Custom).
19
+ - **Observability**: Hooks for structured logging and metrics.
19
20
 
20
21
  ---
21
22
 
22
23
  ## Installation
23
24
 
24
25
  ```bash
25
- npm install zlient zod
26
+ npm install zlient
26
27
  # or
27
- bun add zlient zod
28
+ bun add zlient
28
29
  ```
29
30
 
30
- > **Note**: `zod` is a peer dependency. You must install it alongside `zlient`.
31
+ Then install your preferred validation library:
32
+
33
+ ```bash
34
+ # Pick one (or more!)
35
+ npm install zod # Zod
36
+ npm install valibot # Valibot
37
+ npm install arktype # ArkType
38
+ ```
31
39
 
32
40
  ---
33
41
 
@@ -42,21 +50,22 @@ const client = new HttpClient({
42
50
  baseUrls: {
43
51
  default: 'https://api.example.com',
44
52
  },
45
- retry: { maxRetries: 3 },
53
+ retry: { maxAttempts: 3, baseDelayMs: 1000 },
46
54
  });
47
55
  ```
48
56
 
49
57
  ### 2. Define Endpoint
50
58
 
51
- Use `createEndpoint` to build a type-safe definition. No classes required.
59
+ Use `createEndpoint` with your favorite schema library:
52
60
 
61
+ <!-- tabs:start -->
62
+ #### **Zod**
53
63
  ```typescript
54
64
  import { z } from 'zod';
55
65
 
56
66
  const getUser = client.createEndpoint({
57
67
  method: 'GET',
58
68
  path: (params) => `/users/${params.id}`,
59
- // Strict schemas for all inputs
60
69
  pathParams: z.object({ id: z.string() }),
61
70
  response: z.object({
62
71
  id: z.string(),
@@ -66,6 +75,39 @@ const getUser = client.createEndpoint({
66
75
  });
67
76
  ```
68
77
 
78
+ #### **Valibot**
79
+ ```typescript
80
+ import * as v from 'valibot';
81
+
82
+ const getUser = client.createEndpoint({
83
+ method: 'GET',
84
+ path: (params) => `/users/${params.id}`,
85
+ pathParams: v.object({ id: v.string() }),
86
+ response: v.object({
87
+ id: v.string(),
88
+ name: v.string(),
89
+ email: v.pipe(v.string(), v.email()),
90
+ }),
91
+ });
92
+ ```
93
+
94
+ #### **ArkType**
95
+ ```typescript
96
+ import { type } from 'arktype';
97
+
98
+ const getUser = client.createEndpoint({
99
+ method: 'GET',
100
+ path: (params) => `/users/${params.id}`,
101
+ pathParams: type({ id: 'string' }),
102
+ response: type({
103
+ id: 'string',
104
+ name: 'string',
105
+ email: 'string.email',
106
+ }),
107
+ });
108
+ ```
109
+ <!-- tabs:end -->
110
+
69
111
  ### 3. Call It
70
112
 
71
113
  TypeScript will enforce inputs and infer the response type automatically.
@@ -83,6 +125,23 @@ console.log(user.name);
83
125
 
84
126
  ## Advanced Usage
85
127
 
128
+ ### Retry Configuration
129
+
130
+ Zlient automatically retries failed requests with exponential backoff. Customize the retry behavior:
131
+
132
+ ```typescript
133
+ const client = new HttpClient({
134
+ baseUrls: { default: 'https://api.example.com' },
135
+ retry: {
136
+ maxAttempts: 3, // Total attempts (including initial request)
137
+ baseDelayMs: 1000, // Base delay for exponential backoff
138
+ retryMethods: ['GET', 'POST', 'PUT'], // Methods to retry
139
+ retryStatusCodes: [500, 502, 503, 504], // Status codes to retry
140
+ respectRetryAfter: true, // Honor Retry-After header
141
+ },
142
+ });
143
+ ```
144
+
86
145
  ### Authentication
87
146
 
88
147
  Zlient provides built-in auth providers that safely handle headers.
@@ -104,6 +163,8 @@ client.setAuth(new ApiKeyAuth({ header: 'X-API-KEY', value: 'secret' }));
104
163
  Handle different responses for different status codes.
105
164
 
106
165
  ```typescript
166
+ import { z } from 'zod';
167
+
107
168
  const createPost = client.createEndpoint({
108
169
  method: 'POST',
109
170
  path: '/posts',
@@ -118,40 +179,46 @@ const result = await createPost({ data: { title: 'Hello' } });
118
179
  // `result` type is the union of the 201 and 400 schemas
119
180
  ```
120
181
 
182
+ ### Error Handling
183
+
184
+ Validation errors are thrown as `ApiError` with detailed issues:
185
+
186
+ ```typescript
187
+ import { ApiError } from 'zlient';
188
+
189
+ try {
190
+ await getUser({ pathParams: { id: '123' } });
191
+ } catch (error) {
192
+ if (error instanceof ApiError && error.validationIssues) {
193
+ // Handle validation error
194
+ console.log(error.validationIssues);
195
+ // [{ message: 'Expected string, got number', path: ['id'] }]
196
+ }
197
+ }
198
+ ```
199
+
121
200
  ### FormData Support
122
201
 
123
- Upload files and send multipart form data seamlessly. Zlient automatically detects `FormData`, `Blob`, and `ArrayBuffer` bodies and handles them correctly.
202
+ Upload files and send multipart form data seamlessly.
124
203
 
125
204
  ```typescript
126
- // File upload with FormData
205
+ import { z } from 'zod';
206
+
127
207
  const uploadFile = client.createEndpoint({
128
208
  method: 'POST',
129
209
  path: '/upload',
130
210
  response: z.object({ fileId: z.string(), url: z.string() }),
131
211
  advanced: {
132
- skipRequestValidation: true, // FormData can't be validated with Zod
212
+ skipRequestValidation: true, // FormData can't be validated
133
213
  },
134
214
  });
135
215
 
136
216
  const formData = new FormData();
137
217
  formData.append('file', fileBlob, 'document.pdf');
138
- formData.append('description', 'My document');
139
218
 
140
219
  const result = await uploadFile({ data: formData });
141
- console.log(result.url);
142
- ```
143
-
144
- You can also use the low-level `request` method directly:
145
-
146
- ```typescript
147
- const formData = new FormData();
148
- formData.append('avatar', imageFile);
149
-
150
- const { data } = await client.post('/users/avatar', formData);
151
220
  ```
152
221
 
153
- > **Note**: When using `FormData`, the `Content-Type` header is automatically removed so the browser can set it with the proper multipart boundary.
154
-
155
222
  ### Metrics & Logging
156
223
 
157
224
  Integrate with any monitoring stack (Datadog, Prometheus, etc.).
@@ -168,6 +235,26 @@ const client = new HttpClient({
168
235
 
169
236
  ---
170
237
 
238
+ ## Migration from v2
239
+
240
+ v3 introduces Standard Schema support. Key changes:
241
+
242
+ ```diff
243
+ - import { z } from 'zod'; // Required peer dependency
244
+ + // Use any Standard Schema library (Zod, Valibot, ArkType)
245
+
246
+ - catch (e) { if (e instanceof ZodError) { ... } }
247
+ + catch (e) { if (e instanceof ApiError && e.validationIssues) { ... } }
248
+ ```
249
+
250
+ ---
251
+
252
+ ## Documentation
253
+
254
+ 📖 [Full Documentation](https://zlient.dev)
255
+
256
+ ---
257
+
171
258
  ## License
172
259
 
173
260
  MIT © [Emirhan Gumus](https://github.com/emirhangumus)
package/dist/auth.d.ts CHANGED
@@ -36,7 +36,7 @@ export interface AuthProvider {
36
36
  * Use this when you don't need authentication.
37
37
  */
38
38
  export declare class NoAuth implements AuthProvider {
39
- apply(): Promise<void>;
39
+ apply(_req: AuthContext): Promise<void>;
40
40
  }
41
41
  /**
42
42
  * API Key authentication provider.
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../lib/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,IAAI,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzD;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,WAAW,GAAG;QAAE,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;;OAKG;IACH,KAAK,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAC/C;AAED;;;GAGG;AACH,qBAAa,MAAO,YAAW,YAAY;IACnC,KAAK;CAGZ;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,UAAW,YAAW,YAAY;IACjC,OAAO,CAAC,IAAI;gBAAJ,IAAI,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE;IAQ5E,KAAK,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,WAAW;CAgBjC;AACD;;;;;;;;;;;;;;GAcG;AACH,qBAAa,eAAgB,YAAW,YAAY;IACtC,OAAO,CAAC,QAAQ;gBAAR,QAAQ,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM;IACtD,KAAK,CAAC,EAAE,IAAI,EAAE,EAAE,WAAW;CAclC"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../lib/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,IAAI,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzD;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,WAAW,GAAG;QAAE,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;;OAKG;IACH,KAAK,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAC/C;AAED;;;GAGG;AACH,qBAAa,MAAO,YAAW,YAAY;IACnC,KAAK,CAAC,IAAI,EAAE,WAAW;CAG9B;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,UAAW,YAAW,YAAY;IACjC,OAAO,CAAC,IAAI;gBAAJ,IAAI,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE;IAQ5E,KAAK,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,WAAW;CAgBjC;AACD;;;;;;;;;;;;;;GAcG;AACH,qBAAa,eAAgB,YAAW,YAAY;IACtC,OAAO,CAAC,QAAQ;gBAAR,QAAQ,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM;IACtD,KAAK,CAAC,EAAE,IAAI,EAAE,EAAE,WAAW;CAclC"}
@@ -1 +1 @@
1
- {"version":3,"file":"base-endpoint.d.ts","sourceRoot":"","sources":["../../lib/endpoint/base-endpoint.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"base-endpoint.d.ts","sourceRoot":"","sources":["../../lib/endpoint/base-endpoint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EACL,UAAU,EACV,cAAc,EAEd,SAAS,EACT,gBAAgB,EACjB,MAAM,UAAU,CAAC;AAGlB,MAAM,MAAM,cAAc,CACxB,SAAS,SAAS,cAAc,EAChC,SAAS,SAAS,gBAAgB,GAAG,SAAS,GAAG,SAAS,EAC1D,WAAW,SAAS,gBAAgB,GAAG,SAAS,GAAG,SAAS,EAC5D,UAAU,SAAS,gBAAgB,GAAG,SAAS,GAAG,SAAS,EAC3D,cAAc,SAAS,SAAS,MAAM,EAAE,GAAG,SAAS,EAAE,IACpD;IACF,MAAM,EAAE,MAAM,OAAO,UAAU,CAAC;IAChC,IAAI,EAAE,MAAM,GAAG,CAAC,CAAC,MAAM,EAAE,gBAAgB,CAAC,WAAW,CAAC,OAAO,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC;IAClG,QAAQ,EAAE,SAAS,CAAC;IACpB,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,EAAE;QACT,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,qBAAqB,CAAC,EAAE,OAAO,CAAC;QAChC,sBAAsB,CAAC,EAAE,OAAO,CAAC;QACjC,SAAS,CAAC,EAAE,OAAO,CAAC;KACrB,CAAC;IACF,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAGF,KAAK,eAAe,CAAC,IAAI,SAAS,SAAS,MAAM,EAAE,IAAI,IAAI,SAAS,SAAS,EAAE,GAC3E,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,GAClC;KAAG,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,MAAM;CAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE7D,MAAM,MAAM,kBAAkB,CAC5B,SAAS,SAAS,gBAAgB,GAAG,SAAS,EAC9C,WAAW,SAAS,gBAAgB,GAAG,SAAS,EAChD,UAAU,SAAS,gBAAgB,GAAG,SAAS,EAC/C,cAAc,SAAS,SAAS,MAAM,EAAE,GAAG,SAAS,EAAE,IACpD;IACF,IAAI,CAAC,EAAE,SAAS,SAAS,gBAAgB,GAAG,gBAAgB,CAAC,UAAU,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC;IAC3F,KAAK,CAAC,EAAE,WAAW,SAAS,gBAAgB,GAAG,gBAAgB,CAAC,UAAU,CAAC,WAAW,CAAC,GAAG,KAAK,CAAC;IAChG,UAAU,CAAC,EAAE,UAAU,SAAS,gBAAgB,GAC5C,gBAAgB,CAAC,UAAU,CAAC,UAAU,CAAC,GACvC,KAAK,CAAC;IACV,MAAM,CAAC,EAAE,UAAU,CAAC,WAAW,CAAC;CACjC,GAAG,CAAC,cAAc,SAAS,SAAS,EAAE,GACnC;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GACpC;IAAE,OAAO,EAAE,eAAe,CAAC,cAAc,CAAC,CAAA;CAAE,CAAC,CAAC;AAGlD,KAAK,aAAa,CAAC,CAAC,IAAI,CAAC,SAAS,gBAAgB,GAC9C,gBAAgB,CAAC,WAAW,CAAC,CAAC,CAAC,GAC/B,CAAC,SAAS,SAAS,GACjB;KACG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,gBAAgB,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK;CAC3F,CAAC,MAAM,CAAC,CAAC,GACV,KAAK,CAAC;AAEZ,MAAM,MAAM,YAAY,CACtB,SAAS,SAAS,cAAc,EAChC,SAAS,SAAS,gBAAgB,GAAG,SAAS,EAC9C,WAAW,SAAS,gBAAgB,GAAG,SAAS,EAChD,UAAU,SAAS,gBAAgB,GAAG,SAAS,EAC/C,cAAc,SAAS,SAAS,MAAM,EAAE,GAAG,SAAS,EAAE,IACpD,CACF,MAAM,EAAE,kBAAkB,CAAC,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,CAAC,KAC3E,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC;AAEvC,qBAAa,YAAY,CACvB,SAAS,SAAS,cAAc,EAChC,SAAS,SAAS,gBAAgB,GAAG,SAAS,EAC9C,WAAW,SAAS,gBAAgB,GAAG,SAAS,EAChD,UAAU,SAAS,gBAAgB,GAAG,SAAS,EAC/C,cAAc,SAAS,SAAS,MAAM,EAAE,GAAG,SAAS,EAAE;IAGpD,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,MAAM;gBADN,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,cAAc,CAAC,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,CAAC;IAGzF,IAAI,CACR,MAAM,EAAE,kBAAkB,CAAC,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,CAAC,GAC7E,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;CAsFrC"}
@@ -2,7 +2,7 @@ import type { AuthProvider } from '../auth';
2
2
  import { EndpointCall, EndpointConfig } from '../endpoint/base-endpoint';
3
3
  import { ClientOptions, HTTPMethod, HTTPStatusCodeNumber, RequestOptions, ResponseSchema, StandardSchemaV1 } from '../types';
4
4
  /**
5
- * HTTP client with built-in retry logic, authentication, and interceptors.
5
+ * HTTP client with built-in authentication, and interceptors.
6
6
  * Supports multiple base URLs, type-safe requests, and comprehensive error handling.
7
7
  *
8
8
  * @example
@@ -10,7 +10,6 @@ import { ClientOptions, HTTPMethod, HTTPStatusCodeNumber, RequestOptions, Respon
10
10
  * const client = new HttpClient({
11
11
  * baseUrls: { default: 'https://api.example.com' },
12
12
  * headers: { 'Content-Type': 'application/json' },
13
- * retry: { maxRetries: 3, baseDelayMs: 1000 },
14
13
  * timeout: { requestTimeoutMs: 30000 }
15
14
  * });
16
15
  *
@@ -22,7 +21,7 @@ export declare class HttpClient {
22
21
  private baseUrls;
23
22
  private headers;
24
23
  private interceptors;
25
- private retry;
24
+ private retryPolicy;
26
25
  private timeoutMs?;
27
26
  private auth;
28
27
  private logger;
@@ -46,16 +45,6 @@ export declare class HttpClient {
46
45
  */
47
46
  setAuth(auth: AuthProvider): void;
48
47
  private resolveBaseUrl;
49
- /**
50
- * Sleep for a specified duration (used for retry backoff).
51
- * @private
52
- */
53
- private sleep;
54
- /**
55
- * Execute a function with retry logic and exponential backoff.
56
- * @private
57
- */
58
- private withRetry;
59
48
  /**
60
49
  * Run all registered before-request hooks.
61
50
  * @private
@@ -1 +1 @@
1
- {"version":3,"file":"http-client.d.ts","sourceRoot":"","sources":["../../lib/http/http-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,OAAO,EAAE,YAAY,EAAE,cAAc,EAAgB,MAAM,2BAA2B,CAAC;AAGvF,OAAO,EAEH,aAAa,EAEb,UAAU,EAGV,oBAAoB,EAEpB,cAAc,EACd,cAAc,EAEd,gBAAgB,EAEnB,MAAM,UAAU,CAAC;AAElB;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,QAAQ,CAA4B;IAC5C,OAAO,CAAC,OAAO,CAAyB;IACxC,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,SAAS,CAAC,CAAS;IAC3B,OAAO,CAAC,IAAI,CAAe;IAC3B,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,iBAAiB,CAAC,CAAqD;IAE/E;;;;;OAKG;gBACS,IAAI,EAAE,aAAa;IAuD/B;;;;;;;;OAQG;IACH,OAAO,CAAC,IAAI,EAAE,YAAY;IAI1B,OAAO,CAAC,cAAc;IAUtB;;;OAGG;IACH,OAAO,CAAC,KAAK;IAIb;;;OAGG;YACW,SAAS;IAmBvB;;;OAGG;YACW,cAAc;IAM5B;;;OAGG;YACW,aAAa;IAM3B;;;;OAIG;IACI,WAAW;IAIlB;;;;;OAKG;IACI,UAAU,CAAC,GAAG,EAAE,MAAM;IAI7B;;;;;;;;;;;;;;;;;OAiBG;IACG,OAAO,CAAC,CAAC,GAAG,OAAO,EACvB,MAAM,EAAE,MAAM,OAAO,UAAU,EAC/B,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,OAAO,EACd,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC;QAAE,IAAI,EAAE,CAAC,CAAC;QAAC,MAAM,EAAE,oBAAoB,CAAA;KAAE,CAAC;IA+KrD;;;;;;;OAOG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EACnB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC;QAAE,IAAI,EAAE,CAAC,CAAC;QAAC,MAAM,EAAE,oBAAoB,CAAA;KAAE,CAAC;IAIrD;;;;;;;OAOG;IACG,IAAI,CAAC,CAAC,GAAG,OAAO,EACpB,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,OAAO,EACd,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC;QAAE,IAAI,EAAE,CAAC,CAAC;QAAC,MAAM,EAAE,oBAAoB,CAAA;KAAE,CAAC;IAIrD;;;;;;;OAOG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EACnB,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,OAAO,EACd,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC;QAAE,IAAI,EAAE,CAAC,CAAC;QAAC,MAAM,EAAE,oBAAoB,CAAA;KAAE,CAAC;IAIrD;;;;;;;OAOG;IACG,KAAK,CAAC,CAAC,GAAG,OAAO,EACrB,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,OAAO,EACd,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC;QAAE,IAAI,EAAE,CAAC,CAAC;QAAC,MAAM,EAAE,oBAAoB,CAAA;KAAE,CAAC;IAIrD;;;;;;;OAOG;IACG,MAAM,CAAC,CAAC,GAAG,OAAO,EACtB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC;QAAE,IAAI,EAAE,CAAC,CAAC;QAAC,MAAM,EAAE,oBAAoB,CAAA;KAAE,CAAC;IAIrD;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,cAAc,CACZ,SAAS,SAAS,cAAc,EAChC,SAAS,SAAS,gBAAgB,GAAG,SAAS,GAAG,SAAS,EAC1D,WAAW,SAAS,gBAAgB,GAAG,SAAS,GAAG,SAAS,EAC5D,UAAU,SAAS,gBAAgB,GAAG,SAAS,GAAG,SAAS,EAC3D,cAAc,SAAS,SAAS,MAAM,EAAE,GAAG,SAAS,EAAE,EAEtD,MAAM,EAAE,cAAc,CAAC,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,CAAC,GACpF,YAAY,CAAC,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,CAAC;CAI/E"}
1
+ {"version":3,"file":"http-client.d.ts","sourceRoot":"","sources":["../../lib/http/http-client.ts"],"names":[],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -5,7 +5,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
5
5
  * Use this when you don't need authentication.
6
6
  */
7
7
  var NoAuth = class {
8
- async apply() {}
8
+ async apply(_req) {}
9
9
  };
10
10
  /**
11
11
  * API Key authentication provider.
@@ -539,7 +539,7 @@ var ConsoleMetricsCollector = class {
539
539
  //#endregion
540
540
  //#region lib/http/http-client.ts
541
541
  /**
542
- * HTTP client with built-in retry logic, authentication, and interceptors.
542
+ * HTTP client with built-in authentication, and interceptors.
543
543
  * Supports multiple base URLs, type-safe requests, and comprehensive error handling.
544
544
  *
545
545
  * @example
@@ -547,7 +547,6 @@ var ConsoleMetricsCollector = class {
547
547
  * const client = new HttpClient({
548
548
  * baseUrls: { default: 'https://api.example.com' },
549
549
  * headers: { 'Content-Type': 'application/json' },
550
- * retry: { maxRetries: 3, baseDelayMs: 1000 },
551
550
  * timeout: { requestTimeoutMs: 30000 }
552
551
  * });
553
552
  *
@@ -569,19 +568,12 @@ var HttpClient = class {
569
568
  this.baseUrls = opts.baseUrls;
570
569
  this.headers = opts.headers ?? { "Content-Type": "application/json" };
571
570
  this.interceptors = opts.interceptors ?? {};
572
- this.retry = opts.retry ?? {
573
- maxRetries: 2,
574
- baseDelayMs: 250,
575
- jitter: .2,
576
- retryMethods: ["GET", "HEAD"]
571
+ this.retryPolicy = opts.retry ?? {
572
+ maxAttempts: 0,
573
+ baseDelayMs: 1e3
577
574
  };
578
- if (!this.retry.retryStatusCodes) this.retry.retryStatusCodes = Object.keys(HTTPStatusCode).filter((key) => {
579
- const code = HTTPStatusCode[key];
580
- return typeof code === "number" && code >= 500;
581
- });
582
- if (this.retry.maxRetries < 0) throw new Error("retry.maxRetries must be non-negative");
583
- if (this.retry.baseDelayMs < 0) throw new Error("retry.baseDelayMs must be non-negative");
584
- if (this.retry.jitter !== void 0 && (this.retry.jitter < 0 || this.retry.jitter > 1)) throw new Error("retry.jitter must be between 0 and 1");
575
+ if (!Number.isFinite(this.retryPolicy.maxAttempts) || this.retryPolicy.maxAttempts < 0) throw new Error("retry.maxAttempts must be a non-negative finite number");
576
+ if (this.retryPolicy.baseDelayMs < 0) throw new Error("retry.baseDelayMs must be non-negative");
585
577
  this.timeoutMs = opts.timeout?.requestTimeoutMs;
586
578
  if (this.timeoutMs !== void 0 && this.timeoutMs < 0) throw new Error("timeout.requestTimeoutMs must be non-negative");
587
579
  this.auth = opts["auth"] ?? new NoAuth();
@@ -611,33 +603,6 @@ var HttpClient = class {
611
603
  return url.replace(/\/$/, "");
612
604
  }
613
605
  /**
614
- * Sleep for a specified duration (used for retry backoff).
615
- * @private
616
- */
617
- sleep(ms) {
618
- return new Promise((res) => setTimeout(res, ms));
619
- }
620
- /**
621
- * Execute a function with retry logic and exponential backoff.
622
- * @private
623
- */
624
- async withRetry(fn, canRetry) {
625
- let attempt = 0;
626
- const { maxRetries, baseDelayMs, jitter = .2 } = this.retry;
627
- while (true) try {
628
- return await fn();
629
- } catch (err) {
630
- if (attempt >= maxRetries || !canRetry({
631
- attempt,
632
- error: err
633
- })) throw err;
634
- const backoff = baseDelayMs * 2 ** attempt;
635
- const j = 1 + (Math.random() * 2 - 1) * jitter;
636
- await this.sleep(backoff * j);
637
- attempt++;
638
- }
639
- }
640
- /**
641
606
  * Run all registered before-request hooks.
642
607
  * @private
643
608
  */
@@ -729,6 +694,7 @@ var HttpClient = class {
729
694
  if (init.__urlOverride) url = init.__urlOverride;
730
695
  await this.runBeforeHooks(url, init);
731
696
  let refreshAttempted = false;
697
+ let retryAttempt = 0;
732
698
  const doFetch = async () => {
733
699
  while (true) {
734
700
  let timeoutId;
@@ -739,7 +705,10 @@ var HttpClient = class {
739
705
  }, this.timeoutMs);
740
706
  try {
741
707
  if (refreshAttempted && !options?.skipAuth) {
742
- const freshInit = { ...init };
708
+ const freshInit = {
709
+ ...init,
710
+ headers: typeof init.headers === "object" && !(init.headers instanceof Headers) && !Array.isArray(init.headers) ? { ...init.headers } : init.headers
711
+ };
743
712
  await this.auth.apply({
744
713
  url,
745
714
  init: freshInit,
@@ -758,6 +727,41 @@ var HttpClient = class {
758
727
  }
759
728
  const status = res.status;
760
729
  const contentType = res.headers.get("content-type") || "";
730
+ if (!res.ok) {
731
+ if (!options?.skipRetry && this.retryPolicy.maxAttempts > 0 && retryAttempt < this.retryPolicy.maxAttempts && this.retryPolicy.retryStatusCodes?.includes(status) && this.retryPolicy.retryMethods?.includes(method)) {
732
+ let shouldRetry = true;
733
+ if (this.retryPolicy.shouldRetry) shouldRetry = await this.retryPolicy.shouldRetry({
734
+ url,
735
+ method,
736
+ status,
737
+ attempt: retryAttempt,
738
+ response: res.clone()
739
+ });
740
+ if (shouldRetry) {
741
+ retryAttempt++;
742
+ let delay = this.retryPolicy.baseDelayMs * 2 ** (retryAttempt - 1);
743
+ if (this.retryPolicy.respectRetryAfter) {
744
+ const retryAfter = res.headers.get("Retry-After") || res.headers.get("retry-after");
745
+ if (retryAfter) {
746
+ delay = parseInt(retryAfter, 10) * 1e3;
747
+ this.logger.warn(`Request failed with status ${status}. Retrying after ${delay}ms due to Retry-After header...`, {
748
+ method,
749
+ url,
750
+ status,
751
+ retryAttempt: retryAttempt + 1
752
+ });
753
+ }
754
+ } else this.logger.warn(`Request failed with status ${status}. Retrying attempt ${retryAttempt} after ${delay}ms...`, {
755
+ method,
756
+ url,
757
+ status,
758
+ retryAttempt
759
+ });
760
+ await new Promise((resolve) => setTimeout(resolve, delay));
761
+ continue;
762
+ }
763
+ }
764
+ }
761
765
  let data;
762
766
  if (contentType.includes("json")) data = await res.json();
763
767
  else if (contentType.includes("application/octet-stream") || contentType.includes("application/pdf") || contentType.includes("image/") || contentType.includes("video/") || contentType.includes("audio/") || contentType.startsWith("application/zip") || contentType.startsWith("application/x-")) data = await res.blob();
@@ -804,18 +808,7 @@ var HttpClient = class {
804
808
  }
805
809
  }
806
810
  };
807
- const canRetry = ({ error }) => {
808
- if (error && typeof error === "object" && "name" in error) {
809
- const errorName = error.name;
810
- if (errorName === "AbortError" || errorName === "TimeoutError") return false;
811
- }
812
- if (error instanceof ApiError && error.status) {
813
- if (this.retry.retryStatusCodes?.some((codeKey) => HTTPStatusCode[codeKey] === error.status)) return true;
814
- }
815
- return false;
816
- };
817
- if (options?.skipRetry || !this.retry.retryMethods?.includes(method)) return doFetch();
818
- return this.withRetry(doFetch, canRetry);
811
+ return doFetch();
819
812
  }
820
813
  /**
821
814
  * Convenience method for GET requests.