zlient 3.0.0 → 3.0.2
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 +98 -28
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,28 +6,36 @@
|
|
|
6
6
|

|
|
7
7
|

|
|
8
8
|
|
|
9
|
-
Build robust, type-safe API clients with
|
|
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
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
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
|
|
26
|
+
npm install zlient
|
|
26
27
|
# or
|
|
27
|
-
bun add zlient
|
|
28
|
+
bun add zlient
|
|
28
29
|
```
|
|
29
30
|
|
|
30
|
-
|
|
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
|
|
|
@@ -48,15 +56,16 @@ const client = new HttpClient({
|
|
|
48
56
|
|
|
49
57
|
### 2. Define Endpoint
|
|
50
58
|
|
|
51
|
-
Use `createEndpoint`
|
|
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.
|
|
@@ -104,6 +146,8 @@ client.setAuth(new ApiKeyAuth({ header: 'X-API-KEY', value: 'secret' }));
|
|
|
104
146
|
Handle different responses for different status codes.
|
|
105
147
|
|
|
106
148
|
```typescript
|
|
149
|
+
import { z } from 'zod';
|
|
150
|
+
|
|
107
151
|
const createPost = client.createEndpoint({
|
|
108
152
|
method: 'POST',
|
|
109
153
|
path: '/posts',
|
|
@@ -118,40 +162,46 @@ const result = await createPost({ data: { title: 'Hello' } });
|
|
|
118
162
|
// `result` type is the union of the 201 and 400 schemas
|
|
119
163
|
```
|
|
120
164
|
|
|
165
|
+
### Error Handling
|
|
166
|
+
|
|
167
|
+
Validation errors are thrown as `ApiError` with detailed issues:
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
import { ApiError } from 'zlient';
|
|
171
|
+
|
|
172
|
+
try {
|
|
173
|
+
await getUser({ pathParams: { id: '123' } });
|
|
174
|
+
} catch (error) {
|
|
175
|
+
if (error instanceof ApiError && error.validationIssues) {
|
|
176
|
+
// Handle validation error
|
|
177
|
+
console.log(error.validationIssues);
|
|
178
|
+
// [{ message: 'Expected string, got number', path: ['id'] }]
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
121
183
|
### FormData Support
|
|
122
184
|
|
|
123
|
-
Upload files and send multipart form data seamlessly.
|
|
185
|
+
Upload files and send multipart form data seamlessly.
|
|
124
186
|
|
|
125
187
|
```typescript
|
|
126
|
-
|
|
188
|
+
import { z } from 'zod';
|
|
189
|
+
|
|
127
190
|
const uploadFile = client.createEndpoint({
|
|
128
191
|
method: 'POST',
|
|
129
192
|
path: '/upload',
|
|
130
193
|
response: z.object({ fileId: z.string(), url: z.string() }),
|
|
131
194
|
advanced: {
|
|
132
|
-
skipRequestValidation: true, // FormData can't be validated
|
|
195
|
+
skipRequestValidation: true, // FormData can't be validated
|
|
133
196
|
},
|
|
134
197
|
});
|
|
135
198
|
|
|
136
199
|
const formData = new FormData();
|
|
137
200
|
formData.append('file', fileBlob, 'document.pdf');
|
|
138
|
-
formData.append('description', 'My document');
|
|
139
201
|
|
|
140
202
|
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
203
|
```
|
|
152
204
|
|
|
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
205
|
### Metrics & Logging
|
|
156
206
|
|
|
157
207
|
Integrate with any monitoring stack (Datadog, Prometheus, etc.).
|
|
@@ -168,6 +218,26 @@ const client = new HttpClient({
|
|
|
168
218
|
|
|
169
219
|
---
|
|
170
220
|
|
|
221
|
+
## Migration from v2
|
|
222
|
+
|
|
223
|
+
v3 introduces Standard Schema support. Key changes:
|
|
224
|
+
|
|
225
|
+
```diff
|
|
226
|
+
- import { z } from 'zod'; // Required peer dependency
|
|
227
|
+
+ // Use any Standard Schema library (Zod, Valibot, ArkType)
|
|
228
|
+
|
|
229
|
+
- catch (e) { if (e instanceof ZodError) { ... } }
|
|
230
|
+
+ catch (e) { if (e instanceof ApiError && e.validationIssues) { ... } }
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## Documentation
|
|
236
|
+
|
|
237
|
+
📖 [Full Documentation](https://zlient.dev)
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
171
241
|
## License
|
|
172
242
|
|
|
173
243
|
MIT © [Emirhan Gumus](https://github.com/emirhangumus)
|