@ioka-technologies/asyncapi-ts-client-template 0.0.7 → 0.0.10

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.
@@ -0,0 +1,384 @@
1
+ # TypeScript Client Auth and Retry Example
2
+
3
+ This example demonstrates how to use the authentication and retry features in the TypeScript AsyncAPI client.
4
+
5
+ ## Features
6
+
7
+ - **Authentication Support**: JWT, Basic Auth, and API Key authentication
8
+ - **Retry Logic**: Exponential backoff with configurable presets
9
+ - **Type Safety**: Full TypeScript support with proper error handling
10
+ - **Clean API**: Same method signatures regardless of auth requirements
11
+
12
+ ## Basic Usage
13
+
14
+ ### Simple Client Setup
15
+
16
+ ```typescript
17
+ import { UserServiceClient } from './generated-client';
18
+
19
+ // Basic client without auth or retry
20
+ const client = new UserServiceClient({
21
+ type: 'http',
22
+ url: 'https://api.example.com'
23
+ });
24
+
25
+ await client.connect();
26
+ const user = await client.userSignup({ email: 'user@example.com', password: 'secret' });
27
+ ```
28
+
29
+ ### Client with JWT Authentication
30
+
31
+ ```typescript
32
+ const client = new UserServiceClient({
33
+ type: 'http',
34
+ url: 'https://api.example.com',
35
+ auth: {
36
+ jwt: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
37
+ }
38
+ });
39
+
40
+ // Auth headers are automatically added to all requests
41
+ const user = await client.userSignup(signupData);
42
+ ```
43
+
44
+ ### Client with Basic Authentication
45
+
46
+ ```typescript
47
+ const client = new UserServiceClient({
48
+ type: 'http',
49
+ url: 'https://api.example.com',
50
+ auth: {
51
+ basic: {
52
+ username: 'myuser',
53
+ password: 'mypassword'
54
+ }
55
+ }
56
+ });
57
+ ```
58
+
59
+ ### Client with API Key Authentication
60
+
61
+ ```typescript
62
+ // API Key in header
63
+ const client = new UserServiceClient({
64
+ type: 'http',
65
+ url: 'https://api.example.com',
66
+ auth: {
67
+ apikey: {
68
+ key: 'my-api-key-123',
69
+ location: 'header',
70
+ name: 'X-API-Key'
71
+ }
72
+ }
73
+ });
74
+
75
+ // API Key in query parameter
76
+ const client2 = new UserServiceClient({
77
+ type: 'http',
78
+ url: 'https://api.example.com',
79
+ auth: {
80
+ apikey: {
81
+ key: 'my-api-key-123',
82
+ location: 'query',
83
+ name: 'apikey'
84
+ }
85
+ }
86
+ });
87
+ ```
88
+
89
+ ## Retry Configuration
90
+
91
+ ### Using Retry Presets
92
+
93
+ ```typescript
94
+ // Conservative retry (3 attempts, longer delays)
95
+ const client = new UserServiceClient({
96
+ type: 'http',
97
+ url: 'https://api.example.com',
98
+ retry: 'conservative'
99
+ });
100
+
101
+ // Balanced retry (5 attempts, moderate delays)
102
+ const client2 = new UserServiceClient({
103
+ type: 'http',
104
+ url: 'https://api.example.com',
105
+ retry: 'balanced'
106
+ });
107
+
108
+ // Aggressive retry (10 attempts, shorter delays)
109
+ const client3 = new UserServiceClient({
110
+ type: 'http',
111
+ url: 'https://api.example.com',
112
+ retry: 'aggressive'
113
+ });
114
+
115
+ // No retry
116
+ const client4 = new UserServiceClient({
117
+ type: 'http',
118
+ url: 'https://api.example.com',
119
+ retry: 'none'
120
+ });
121
+ ```
122
+
123
+ ### Custom Retry Configuration
124
+
125
+ ```typescript
126
+ const client = new UserServiceClient({
127
+ type: 'http',
128
+ url: 'https://api.example.com',
129
+ retry: {
130
+ enabled: true,
131
+ maxAttempts: 3,
132
+ baseDelay: 1000, // 1 second initial delay
133
+ maxDelay: 30000, // 30 seconds max delay
134
+ backoffMultiplier: 2, // Double delay each attempt
135
+ jitter: true, // Add randomization
136
+ retryableStatusCodes: [429, 500, 502, 503, 504],
137
+ retryableErrors: ['NETWORK_ERROR', 'TIMEOUT', 'ECONNRESET']
138
+ }
139
+ });
140
+ ```
141
+
142
+ ## Advanced Features
143
+
144
+ ### Auth and Retry Combined
145
+
146
+ ```typescript
147
+ const client = new UserServiceClient({
148
+ type: 'http',
149
+ url: 'https://api.example.com',
150
+ auth: {
151
+ jwt: 'your-jwt-token'
152
+ },
153
+ retry: 'balanced',
154
+ authCallbacks: {
155
+ onAuthError: async () => {
156
+ // Handle 401 errors - refresh token, etc.
157
+ console.log('Authentication failed, attempting to refresh token...');
158
+ // Return true to retry the request with updated auth
159
+ return false;
160
+ },
161
+ onTokenRefresh: async (oldToken) => {
162
+ // Refresh the JWT token
163
+ const newToken = await refreshJwtToken(oldToken);
164
+ return newToken;
165
+ }
166
+ },
167
+ retryCallbacks: {
168
+ onRetry: (attempt, error, delay) => {
169
+ console.log(`Retry attempt ${attempt} after ${delay}ms due to:`, error.message);
170
+ },
171
+ onRetryExhausted: (operation, finalError) => {
172
+ console.error(`All retry attempts exhausted for ${operation}:`, finalError);
173
+ }
174
+ }
175
+ });
176
+ ```
177
+
178
+ ### Per-Request Retry Override
179
+
180
+ ```typescript
181
+ // Override retry config for specific requests
182
+ const user = await client.userSignup(signupData, {
183
+ retry: 'aggressive', // Use aggressive retry for this request only
184
+ timeout: 10000 // 10 second timeout
185
+ });
186
+
187
+ // Disable retry for a specific request
188
+ const quickResult = await client.getUserProfile(userId, {
189
+ retry: 'none'
190
+ });
191
+ ```
192
+
193
+ ### WebSocket with Auth
194
+
195
+ ```typescript
196
+ const client = new UserServiceClient({
197
+ type: 'websocket',
198
+ url: 'wss://api.example.com/ws',
199
+ auth: {
200
+ jwt: 'your-jwt-token'
201
+ }
202
+ });
203
+
204
+ await client.connect();
205
+
206
+ // Subscribe to events (auth is handled automatically)
207
+ const unsubscribe = client.userNotifications((notification) => {
208
+ console.log('Received notification:', notification);
209
+ });
210
+
211
+ // Clean up
212
+ unsubscribe();
213
+ await client.disconnect();
214
+ ```
215
+
216
+ ## Error Handling
217
+
218
+ ```typescript
219
+ import { AuthError, UnauthorizedError, RetryError, MaxRetriesExceededError } from './generated-client';
220
+
221
+ try {
222
+ const user = await client.userSignup(signupData);
223
+ } catch (error) {
224
+ if (error instanceof UnauthorizedError) {
225
+ console.error('Authentication failed:', error.message);
226
+ // Redirect to login page
227
+ } else if (error instanceof MaxRetriesExceededError) {
228
+ console.error('Request failed after all retry attempts:', error.lastError);
229
+ // Show user-friendly error message
230
+ } else if (error instanceof AuthError) {
231
+ console.error('Auth configuration error:', error.message);
232
+ } else {
233
+ console.error('Unexpected error:', error);
234
+ }
235
+ }
236
+ ```
237
+
238
+ ## Login Flow and JWT Token Management
239
+
240
+ ### Basic Login Flow
241
+
242
+ ```typescript
243
+ // Step 1: Create client without auth for login
244
+ const client = new UserServiceClient({
245
+ type: 'http',
246
+ url: 'https://api.example.com',
247
+ retry: 'balanced'
248
+ });
249
+
250
+ await client.connect();
251
+
252
+ // Step 2: Login (no auth required)
253
+ const loginResponse = await client.userLogin({
254
+ email: 'user@example.com',
255
+ password: 'mypassword'
256
+ });
257
+
258
+ // Step 3: Update client with JWT token
259
+ client.updateAuth({
260
+ jwt: loginResponse.token
261
+ });
262
+
263
+ // Step 4: Make authenticated requests
264
+ const userProfile = await client.getUserProfile({
265
+ userId: loginResponse.user.id
266
+ });
267
+ ```
268
+
269
+ ### Advanced Login with Token Refresh
270
+
271
+ ```typescript
272
+ const client = new UserServiceClient({
273
+ type: 'http',
274
+ url: 'https://api.example.com',
275
+ retry: 'balanced',
276
+ authCallbacks: {
277
+ onAuthError: async () => {
278
+ // Handle 401 errors by refreshing token
279
+ if (refreshToken) {
280
+ try {
281
+ const refreshResponse = await refreshJwtToken(refreshToken);
282
+ client.updateAuth({ jwt: refreshResponse.token });
283
+ return true; // Retry the original request
284
+ } catch (error) {
285
+ // Redirect to login page
286
+ return false;
287
+ }
288
+ }
289
+ return false;
290
+ }
291
+ }
292
+ });
293
+
294
+ // Login and store tokens
295
+ const loginResponse = await client.userLogin(credentials);
296
+ client.updateAuth({ jwt: loginResponse.token });
297
+ refreshToken = loginResponse.refreshToken;
298
+ ```
299
+
300
+ ### WebSocket Login Flow
301
+
302
+ ```typescript
303
+ // For WebSocket, you may need to reconnect after auth update
304
+ const client = new UserServiceClient({
305
+ type: 'websocket',
306
+ url: 'wss://api.example.com/ws'
307
+ });
308
+
309
+ await client.connect();
310
+
311
+ // Login
312
+ const loginResponse = await client.userLogin(credentials);
313
+
314
+ // Disconnect and reconnect with auth
315
+ await client.disconnect();
316
+ client.updateAuth({ jwt: loginResponse.token });
317
+ await client.connect();
318
+
319
+ // Now subscribe to authenticated events
320
+ const unsubscribe = client.userNotifications((notification) => {
321
+ console.log('Notification:', notification);
322
+ });
323
+ ```
324
+
325
+ ### React Hook Example
326
+
327
+ ```typescript
328
+ function useAuthenticatedClient() {
329
+ const [client, setClient] = useState(null);
330
+ const [isAuthenticated, setIsAuthenticated] = useState(false);
331
+
332
+ const login = useCallback(async (email, password) => {
333
+ const loginResponse = await client.userLogin({ email, password });
334
+
335
+ client.updateAuth({ jwt: loginResponse.token });
336
+ setIsAuthenticated(true);
337
+
338
+ return loginResponse;
339
+ }, [client]);
340
+
341
+ const logout = useCallback(async () => {
342
+ client.updateAuth({});
343
+ setIsAuthenticated(false);
344
+ }, [client]);
345
+
346
+ return { client, isAuthenticated, login, logout };
347
+ }
348
+ ```
349
+
350
+ ## Best Practices
351
+
352
+ 1. **Configure Once**: Set up auth and retry at the client level rather than per-request
353
+ 2. **Use Presets**: Start with retry presets (`balanced` is recommended) before customizing
354
+ 3. **Handle Auth Errors**: Implement `onAuthError` callback for token refresh scenarios
355
+ 4. **Monitor Retries**: Use retry callbacks to log and monitor retry behavior
356
+ 5. **Graceful Degradation**: Handle `MaxRetriesExceededError` with user-friendly messages
357
+ 6. **Security**: Never log auth credentials or tokens in production
358
+ 7. **Login Flow**: Use `updateAuth()` to set JWT tokens after login
359
+ 8. **WebSocket Auth**: Reconnect WebSocket connections after updating auth
360
+
361
+ ## Environment-Specific Configuration
362
+
363
+ ```typescript
364
+ // Development
365
+ const devClient = new UserServiceClient({
366
+ type: 'http',
367
+ url: 'http://localhost:3000',
368
+ retry: 'aggressive', // Fast feedback during development
369
+ auth: { jwt: 'dev-token' }
370
+ });
371
+
372
+ // Production
373
+ const prodClient = new UserServiceClient({
374
+ type: 'https',
375
+ url: 'https://api.production.com',
376
+ retry: 'balanced', // Balanced approach for production
377
+ auth: { jwt: process.env.JWT_TOKEN },
378
+ retryCallbacks: {
379
+ onRetryExhausted: (operation, error) => {
380
+ // Log to monitoring service
381
+ logger.error('Request failed after retries', { operation, error });
382
+ }
383
+ }
384
+ });