zod-codegen 1.0.3 → 1.1.1

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/EXAMPLES.md ADDED
@@ -0,0 +1,730 @@
1
+ # Usage Examples
2
+
3
+ ## Extending the Generated Client for Authentication and Configuration
4
+
5
+ The generated client class includes a protected `getBaseRequestOptions()` method that you can override to customize request options. This method returns `Partial<Omit<RequestInit, 'method' | 'body'>>`, allowing you to set:
6
+
7
+ - **Headers**: Authentication tokens, User-Agent, custom headers
8
+ - **CORS**: `mode`, `credentials` for cross-origin requests
9
+ - **Request Options**: `signal` (AbortController), `cache`, `redirect`, `referrer`, etc.
10
+
11
+ All examples below demonstrate how to extend the generated client class to add these features.
12
+
13
+ ### Example: Adding Bearer Token Authentication
14
+
15
+ ```typescript
16
+ import {SwaggerPetstoreOpenAPI30, ClientOptions} from './generated/type.js';
17
+
18
+ class AuthenticatedPetstoreAPI extends SwaggerPetstoreOpenAPI30 {
19
+ private accessToken: string | null = null;
20
+
21
+ constructor(options: ClientOptions = {}) {
22
+ super(options);
23
+ }
24
+
25
+ // Override getBaseRequestOptions to add Authorization header
26
+ protected getBaseRequestOptions(): Partial<Omit<RequestInit, 'method' | 'body'>> {
27
+ const options = super.getBaseRequestOptions();
28
+ return {
29
+ ...options,
30
+ headers: {
31
+ ...((options.headers as Record<string, string>) || {}),
32
+ ...(this.accessToken ? {Authorization: `Bearer ${this.accessToken}`} : {}),
33
+ },
34
+ };
35
+ }
36
+
37
+ // Helper method to set the access token
38
+ setAccessToken(token: string): void {
39
+ this.accessToken = token;
40
+ }
41
+
42
+ // Helper method to clear the token
43
+ clearAccessToken(): void {
44
+ this.accessToken = null;
45
+ }
46
+ }
47
+
48
+ // Usage
49
+ async function main() {
50
+ const client = new AuthenticatedPetstoreAPI({});
51
+
52
+ // Set authentication token
53
+ client.setAccessToken('your-token-here');
54
+
55
+ // All subsequent requests will include the Authorization header
56
+ const pets = await client.findPetsByStatus('available');
57
+ console.log(pets);
58
+
59
+ // You can also manually set/update the token
60
+ client.setAccessToken('new-token-here');
61
+
62
+ // Or clear it
63
+ client.clearAccessToken();
64
+ }
65
+
66
+ void main();
67
+ ```
68
+
69
+ ### Example: Session Management with Token Refresh
70
+
71
+ ```typescript
72
+ import {SwaggerPetstoreOpenAPI30} from './generated/type.js';
73
+
74
+ class SessionManagedPetstoreAPI extends SwaggerPetstoreOpenAPI30 {
75
+ private accessToken: string | null = null;
76
+ private refreshToken: string | null = null;
77
+ private tokenExpiry: Date | null = null;
78
+
79
+ protected getBaseRequestOptions(): Partial<Omit<RequestInit, 'method' | 'body'>> {
80
+ const options = super.getBaseRequestOptions();
81
+
82
+ // Check if token is expired and refresh if needed
83
+ if (this.tokenExpiry && this.tokenExpiry <= new Date()) {
84
+ this.refreshAccessToken().catch(console.error);
85
+ }
86
+
87
+ return {
88
+ ...options,
89
+ headers: {
90
+ ...((options.headers as Record<string, string>) || {}),
91
+ ...(this.accessToken ? {Authorization: `Bearer ${this.accessToken}`} : {}),
92
+ },
93
+ };
94
+ }
95
+
96
+ async login(username: string, password: string): Promise<void> {
97
+ // Example: If your API has a login endpoint
98
+ // const response = await this.loginUser({ username, password });
99
+ // this.setTokens(response.access_token, response.refresh_token, response.expires_in);
100
+
101
+ // For demonstration, setting tokens directly
102
+ this.setTokens('access-token-here', 'refresh-token-here', 3600);
103
+ }
104
+
105
+ private async refreshAccessToken(): Promise<void> {
106
+ if (!this.refreshToken) {
107
+ throw new Error('No refresh token available');
108
+ }
109
+
110
+ // Example: If your API has a refresh endpoint
111
+ // const response = await this.refreshToken({ refresh_token: this.refreshToken });
112
+ // this.setTokens(response.access_token, response.refresh_token, response.expires_in);
113
+
114
+ // For demonstration
115
+ this.setTokens('new-access-token', this.refreshToken, 3600);
116
+ }
117
+
118
+ private setTokens(accessToken: string, refreshToken?: string, expiresIn?: number): void {
119
+ this.accessToken = accessToken;
120
+ if (refreshToken) {
121
+ this.refreshToken = refreshToken;
122
+ }
123
+ if (expiresIn) {
124
+ this.tokenExpiry = new Date(Date.now() + expiresIn * 1000);
125
+ }
126
+ }
127
+ }
128
+ ```
129
+
130
+ ### Example: Custom Headers Per Request
131
+
132
+ If you need to pass custom headers for specific requests, you can extend the client and add helper methods:
133
+
134
+ ```typescript
135
+ import {SwaggerPetstoreOpenAPI30, ClientOptions} from './generated/type.js';
136
+
137
+ class CustomHeadersPetstoreAPI extends SwaggerPetstoreOpenAPI30 {
138
+ constructor(options: ClientOptions = {}) {
139
+ super(options);
140
+ }
141
+ protected getBaseRequestOptions(): Partial<Omit<RequestInit, 'method' | 'body'>> {
142
+ const options = super.getBaseRequestOptions();
143
+ return {
144
+ ...options,
145
+ headers: {
146
+ ...((options.headers as Record<string, string>) || {}),
147
+ 'X-Custom-Header': 'custom-value',
148
+ 'X-Request-ID': this.generateRequestId(),
149
+ },
150
+ };
151
+ }
152
+
153
+ private generateRequestId(): string {
154
+ return `req-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
155
+ }
156
+ }
157
+ ```
158
+
159
+ ### Example: API Key Authentication
160
+
161
+ ```typescript
162
+ import {SwaggerPetstoreOpenAPI30, ClientOptions} from './generated/type.js';
163
+
164
+ class ApiKeyAuthenticatedPetstoreAPI extends SwaggerPetstoreOpenAPI30 {
165
+ constructor(options: ClientOptions & {apiKey: string}) {
166
+ super(options);
167
+ this.apiKey = options.apiKey;
168
+ }
169
+
170
+ private apiKey: string;
171
+
172
+ protected getBaseRequestOptions(): Partial<Omit<RequestInit, 'method' | 'body'>> {
173
+ const options = super.getBaseRequestOptions();
174
+ return {
175
+ ...options,
176
+ headers: {
177
+ ...((options.headers as Record<string, string>) || {}),
178
+ 'X-API-Key': this.apiKey,
179
+ },
180
+ };
181
+ }
182
+ }
183
+ ```
184
+
185
+ ### Example: Using AbortController for Request Cancellation
186
+
187
+ ```typescript
188
+ import {SwaggerPetstoreOpenAPI30, ClientOptions} from './generated/type.js';
189
+
190
+ class CancellablePetstoreAPI extends SwaggerPetstoreOpenAPI30 {
191
+ constructor(options: ClientOptions = {}) {
192
+ super(options);
193
+ }
194
+ private abortController: AbortController | null = null;
195
+
196
+ protected getBaseRequestOptions(): Partial<Omit<RequestInit, 'method' | 'body'>> {
197
+ const options = super.getBaseRequestOptions();
198
+ this.abortController = new AbortController();
199
+ return {
200
+ ...options,
201
+ signal: this.abortController.signal,
202
+ };
203
+ }
204
+
205
+ cancelRequests(): void {
206
+ if (this.abortController) {
207
+ this.abortController.abort();
208
+ this.abortController = null;
209
+ }
210
+ }
211
+ }
212
+
213
+ // Usage
214
+ const client = new CancellablePetstoreAPI();
215
+ const promise = client.findPetsByStatus('available');
216
+ // Later, cancel the request
217
+ client.cancelRequests();
218
+ ```
219
+
220
+ ### Example: Custom Credentials and CORS Mode
221
+
222
+ ```typescript
223
+ import {SwaggerPetstoreOpenAPI30, ClientOptions} from './generated/type.js';
224
+
225
+ class CustomCorsPetstoreAPI extends SwaggerPetstoreOpenAPI30 {
226
+ constructor(options: ClientOptions = {}) {
227
+ super(options);
228
+ }
229
+
230
+ protected getBaseRequestOptions(): Partial<Omit<RequestInit, 'method' | 'body'>> {
231
+ const options = super.getBaseRequestOptions();
232
+ return {
233
+ ...options,
234
+ credentials: 'include', // Include cookies in CORS requests
235
+ mode: 'cors', // Enable CORS
236
+ };
237
+ }
238
+ }
239
+
240
+ // Usage
241
+ const client = new CustomCorsPetstoreAPI({});
242
+ ```
243
+
244
+ <|tool▁call▁begin|>
245
+ grep
246
+
247
+ ### Example: Complete Configuration (CORS, User-Agent, Authentication)
248
+
249
+ Here's a comprehensive example showing how to combine CORS settings, custom User-Agent, and authentication:
250
+
251
+ ```typescript
252
+ import {SwaggerPetstoreOpenAPI30, ClientOptions} from './generated/type.js';
253
+
254
+ class FullyConfiguredPetstoreAPI extends SwaggerPetstoreOpenAPI30 {
255
+ private accessToken: string | null = null;
256
+ private readonly userAgent: string;
257
+
258
+ constructor(options: ClientOptions & {userAgent?: string} = {}) {
259
+ super(options);
260
+ this.userAgent = options.userAgent || 'MyApp/1.0.0 (https://myapp.com)';
261
+ }
262
+
263
+ protected getBaseRequestOptions(): Partial<Omit<RequestInit, 'method' | 'body'>> {
264
+ const options = super.getBaseRequestOptions();
265
+
266
+ // Build headers object
267
+ const headers: Record<string, string> = {
268
+ ...((options.headers as Record<string, string>) || {}),
269
+ 'User-Agent': this.userAgent,
270
+ ...(this.accessToken ? {Authorization: `Bearer ${this.accessToken}`} : {}),
271
+ };
272
+
273
+ return {
274
+ ...options,
275
+ headers,
276
+ // CORS configuration
277
+ mode: 'cors', // Enable CORS
278
+ credentials: 'include', // Include cookies and credentials in CORS requests
279
+ // Cache control
280
+ cache: 'no-cache', // Don't cache requests
281
+ // Redirect handling
282
+ redirect: 'follow', // Follow redirects automatically
283
+ };
284
+ }
285
+
286
+ setAccessToken(token: string): void {
287
+ this.accessToken = token;
288
+ }
289
+
290
+ clearAccessToken(): void {
291
+ this.accessToken = null;
292
+ }
293
+ }
294
+
295
+ // Usage
296
+ const client = new FullyConfiguredPetstoreAPI({
297
+ userAgent: 'MyCustomApp/2.0.0 (Custom User Agent)',
298
+ });
299
+
300
+ // Set authentication token
301
+ client.setAccessToken('your-bearer-token-here');
302
+
303
+ // All requests will now include:
304
+ // - Custom User-Agent header
305
+ // - Authorization header (Bearer token)
306
+ // - CORS mode enabled
307
+ // - Credentials included
308
+ // - No caching
309
+ // - Automatic redirect following
310
+ const pets = await client.findPetsByStatus('available');
311
+ ```
312
+
313
+ ### Example: Environment-Specific Configuration
314
+
315
+ You can also create different configurations for different environments:
316
+
317
+ ```typescript
318
+ import {SwaggerPetstoreOpenAPI30, ClientOptions} from './generated/type.js';
319
+
320
+ interface ClientConfig {
321
+ userAgent?: string;
322
+ enableCors?: boolean;
323
+ includeCredentials?: boolean;
324
+ cachePolicy?: RequestCache;
325
+ }
326
+
327
+ class ConfigurablePetstoreAPI extends SwaggerPetstoreOpenAPI30 {
328
+ private accessToken: string | null = null;
329
+ private readonly config: Required<ClientConfig>;
330
+
331
+ constructor(options: ClientOptions & {config?: ClientConfig} = {}) {
332
+ super(options);
333
+ const config = options.config || {};
334
+ this.config = {
335
+ userAgent: config.userAgent || 'PetstoreAPIClient/1.0.0',
336
+ enableCors: config.enableCors ?? true,
337
+ includeCredentials: config.includeCredentials ?? true,
338
+ cachePolicy: config.cachePolicy || 'no-cache',
339
+ };
340
+ }
341
+
342
+ protected getBaseRequestOptions(): Partial<Omit<RequestInit, 'method' | 'body'>> {
343
+ const options = super.getBaseRequestOptions();
344
+
345
+ const headers: Record<string, string> = {
346
+ ...((options.headers as Record<string, string>) || {}),
347
+ 'User-Agent': this.config.userAgent,
348
+ ...(this.accessToken ? {Authorization: `Bearer ${this.accessToken}`} : {}),
349
+ };
350
+
351
+ const requestOptions: Partial<Omit<RequestInit, 'method' | 'body'>> = {
352
+ ...options,
353
+ headers,
354
+ cache: this.config.cachePolicy,
355
+ };
356
+
357
+ // Conditionally add CORS options
358
+ if (this.config.enableCors) {
359
+ requestOptions.mode = 'cors';
360
+ if (this.config.includeCredentials) {
361
+ requestOptions.credentials = 'include';
362
+ }
363
+ }
364
+
365
+ return requestOptions;
366
+ }
367
+
368
+ setAccessToken(token: string): void {
369
+ this.accessToken = token;
370
+ }
371
+ }
372
+
373
+ // Usage for production
374
+ const productionClient = new ConfigurablePetstoreAPI({
375
+ config: {
376
+ userAgent: 'MyApp/1.0.0 Production',
377
+ enableCors: true,
378
+ includeCredentials: true,
379
+ cachePolicy: 'default',
380
+ },
381
+ });
382
+
383
+ // Usage for development
384
+ const devClient = new ConfigurablePetstoreAPI({
385
+ config: {
386
+ userAgent: 'MyApp/1.0.0 Development',
387
+ enableCors: true,
388
+ includeCredentials: false, // Don't send credentials in dev
389
+ cachePolicy: 'no-cache',
390
+ },
391
+ });
392
+ ```
393
+
394
+ ## How It Works
395
+
396
+ ### Architecture Overview
397
+
398
+ The generated client uses a layered approach to request configuration:
399
+
400
+ 1. **Base Options Layer**: `getBaseRequestOptions()` - Override this to set default options for all requests
401
+ 2. **Request-Specific Layer**: Options passed to individual endpoint methods (via `options.headers`)
402
+ 3. **Generated Layer**: Method, body, and Content-Type headers are set automatically
403
+
404
+ ### Request Options Merging Order
405
+
406
+ When a request is made, options are merged in this order (later values override earlier ones):
407
+
408
+ 1. **Base Options** from `getBaseRequestOptions()` - All RequestInit options (headers, signal, credentials, mode, cache, etc.)
409
+ 2. **Content-Type Header** - Automatically set based on request body (`application/json` or `application/x-www-form-urlencoded`)
410
+ 3. **Request-Specific Headers** - From `options.headers` parameter (if provided)
411
+ 4. **Method and Body** - Always set by generated code (cannot be overridden)
412
+
413
+ **Important**: `getBaseRequestOptions()` returns **base options that are merged with**, not replaced by, request-specific options. This means:
414
+
415
+ - ✅ Base options like `mode`, `credentials`, `signal` are preserved
416
+ - ✅ Headers are merged (base headers + Content-Type + request headers)
417
+ - ✅ Request-specific headers override base headers
418
+ - ✅ Method and body always come from the request (not from baseOptions)
419
+
420
+ ### Type Safety
421
+
422
+ The `getBaseRequestOptions()` method returns `Partial<Omit<RequestInit, 'method' | 'body'>>`, which means:
423
+
424
+ - ✅ **You CAN set**: `headers`, `signal`, `credentials`, `mode`, `cache`, `redirect`, `referrer`, `referrerPolicy`, `integrity`, `keepalive`
425
+ - ❌ **You CANNOT set**: `method` (controlled by endpoint), `body` (controlled by request data)
426
+
427
+ This ensures type safety while preventing accidental overrides of critical request properties.
428
+
429
+ ### Complete Options Merging Details
430
+
431
+ The final fetch request uses `Object.assign()` to merge options:
432
+
433
+ ```typescript
434
+ // Headers are merged first:
435
+ const finalHeaders = Object.assign(
436
+ {}, // Start with empty object
437
+ baseOptions.headers || {}, // 1. Base headers from getBaseRequestOptions()
438
+ {'Content-Type': contentType}, // 2. Content-Type (may override base)
439
+ options.headers || {}, // 3. Request-specific headers (highest priority)
440
+ );
441
+
442
+ // Then all options are merged:
443
+ const finalOptions = Object.assign(
444
+ {}, // Start with empty object
445
+ baseOptions, // 1. All base options (mode, credentials, signal, cache, etc.)
446
+ {
447
+ // 2. Request-specific options (override base)
448
+ method, // Always from endpoint
449
+ headers: finalHeaders, // Merged headers
450
+ body, // Always from request data
451
+ },
452
+ );
453
+
454
+ fetch(url, finalOptions);
455
+ ```
456
+
457
+ **Important**:
458
+
459
+ - Always return `Record<string, string>` for headers in `getBaseRequestOptions()` for predictable merging behavior
460
+ - Base options (like `mode`, `credentials`, `signal`) are preserved unless explicitly overridden
461
+ - Headers are merged, not replaced - base headers + Content-Type + request headers
462
+
463
+ ### Request Flow
464
+
465
+ ```
466
+ User calls endpoint method
467
+
468
+ getBaseRequestOptions() called → Returns base options
469
+
470
+ #makeRequest() merges:
471
+ - Base options (headers, signal, credentials, etc.)
472
+ - Content-Type header
473
+ - Request-specific headers
474
+ - Method and body
475
+
476
+ fetch() called with merged options
477
+
478
+ Response returned and validated with Zod
479
+ ```
480
+
481
+ ## Best Practices
482
+
483
+ ### 1. Always Call Super Method
484
+
485
+ ```typescript
486
+ protected getBaseRequestOptions() {
487
+ const options = super.getBaseRequestOptions(); // ✅ Preserve base options
488
+ return { ...options, /* your additions */ };
489
+ }
490
+ ```
491
+
492
+ ### 2. Proper Header Merging
493
+
494
+ ```typescript
495
+ protected getBaseRequestOptions() {
496
+ const options = super.getBaseRequestOptions();
497
+ return {
498
+ ...options,
499
+ headers: {
500
+ ...(options.headers as Record<string, string> || {}), // ✅ Handle undefined
501
+ 'Authorization': `Bearer ${this.token}`,
502
+ },
503
+ };
504
+ }
505
+ ```
506
+
507
+ ### 3. Store Sensitive Data Privately
508
+
509
+ ```typescript
510
+ class SecureAPI extends YourAPI {
511
+ private accessToken: string | null = null; // ✅ Private property
512
+ // Never expose tokens in public methods
513
+ }
514
+ ```
515
+
516
+ ### 4. Handle Token Expiration
517
+
518
+ ```typescript
519
+ protected getBaseRequestOptions() {
520
+ // ✅ Check expiration before using token
521
+ if (this.tokenExpiry && this.tokenExpiry <= new Date()) {
522
+ this.refreshToken();
523
+ }
524
+ // ... rest of implementation
525
+ }
526
+ ```
527
+
528
+ ### 5. Provide Helper Methods
529
+
530
+ ```typescript
531
+ class UserFriendlyAPI extends YourAPI {
532
+ // ✅ Provide convenient methods
533
+ async login(username: string, password: string) {
534
+ const response = await this.auth_login_post({username, password});
535
+ this.setAccessToken(response.token);
536
+ }
537
+
538
+ logout() {
539
+ this.clearAccessToken();
540
+ }
541
+ }
542
+ ```
543
+
544
+ ### 6. Use TypeScript Strictly
545
+
546
+ ```typescript
547
+ // ✅ Type your headers explicitly
548
+ const headers: Record<string, string> = {
549
+ 'User-Agent': this.userAgent,
550
+ ...(this.token ? {Authorization: `Bearer ${this.token}`} : {}),
551
+ };
552
+ ```
553
+
554
+ ### 7. Environment-Specific Configuration
555
+
556
+ ```typescript
557
+ // ✅ Different configs for different environments
558
+ const prodClient = new ConfigurableAPI({
559
+ config: {
560
+ userAgent: 'MyApp/1.0.0 Production',
561
+ enableCors: true,
562
+ },
563
+ });
564
+
565
+ const devClient = new ConfigurableAPI({
566
+ config: {
567
+ userAgent: 'MyApp/1.0.0 Development',
568
+ enableCors: false,
569
+ },
570
+ });
571
+ ```
572
+
573
+ ### 8. Error Handling
574
+
575
+ ```typescript
576
+ class RobustAPI extends YourAPI {
577
+ protected getBaseRequestOptions() {
578
+ const options = super.getBaseRequestOptions();
579
+ return {
580
+ ...options,
581
+ signal: this.createAbortSignal(), // ✅ Handle cancellation
582
+ };
583
+ }
584
+
585
+ private createAbortSignal(): AbortSignal {
586
+ const controller = new AbortController();
587
+ // Set timeout, etc.
588
+ return controller.signal;
589
+ }
590
+ }
591
+ ```
592
+
593
+ ## Common Patterns
594
+
595
+ ### Pattern 1: Simple Authentication
596
+
597
+ ```typescript
598
+ import {YourAPI, ClientOptions} from './generated/type.js';
599
+
600
+ class SimpleAuthAPI extends YourAPI {
601
+ private token: string | null = null;
602
+
603
+ constructor(options: ClientOptions = {}) {
604
+ super(options);
605
+ }
606
+
607
+ protected getBaseRequestOptions() {
608
+ const options = super.getBaseRequestOptions();
609
+ return {
610
+ ...options,
611
+ headers: {
612
+ ...((options.headers as Record<string, string>) || {}),
613
+ ...(this.token ? {Authorization: `Bearer ${this.token}`} : {}),
614
+ },
615
+ };
616
+ }
617
+ }
618
+ ```
619
+
620
+ ### Pattern 2: Multiple Headers
621
+
622
+ ```typescript
623
+ import {YourAPI, ClientOptions} from './generated/type.js';
624
+
625
+ class MultiHeaderAPI extends YourAPI {
626
+ constructor(options: ClientOptions = {}) {
627
+ super(options);
628
+ }
629
+
630
+ protected getBaseRequestOptions() {
631
+ const options = super.getBaseRequestOptions();
632
+ return {
633
+ ...options,
634
+ headers: {
635
+ ...((options.headers as Record<string, string>) || {}),
636
+ 'User-Agent': 'MyApp/1.0.0',
637
+ 'X-API-Version': 'v2',
638
+ 'X-Request-ID': this.generateId(),
639
+ },
640
+ };
641
+ }
642
+ }
643
+ ```
644
+
645
+ ### Pattern 3: Conditional Options
646
+
647
+ ```typescript
648
+ import {YourAPI, ClientOptions} from './generated/type.js';
649
+
650
+ class ConditionalAPI extends YourAPI {
651
+ constructor(options: ClientOptions = {}) {
652
+ super(options);
653
+ }
654
+
655
+ protected getBaseRequestOptions() {
656
+ const options = super.getBaseRequestOptions();
657
+ const config: Partial<Omit<RequestInit, 'method' | 'body'>> = {...options};
658
+
659
+ if (this.needsCors) {
660
+ config.mode = 'cors';
661
+ config.credentials = 'include';
662
+ }
663
+
664
+ return config;
665
+ }
666
+ }
667
+ ```
668
+
669
+ ## Troubleshooting
670
+
671
+ ### Headers Not Being Applied
672
+
673
+ **Problem**: Custom headers aren't appearing in requests.
674
+
675
+ **Solution**: Ensure you're spreading base options and handling undefined:
676
+
677
+ ```typescript
678
+ headers: {
679
+ ...(options.headers as Record<string, string> || {}), // ✅ Handle undefined
680
+ 'Your-Header': 'value',
681
+ }
682
+ ```
683
+
684
+ ### CORS Errors
685
+
686
+ **Problem**: CORS errors when making requests.
687
+
688
+ **Solution**: Set CORS options in `getBaseRequestOptions()`:
689
+
690
+ ```typescript
691
+ return {
692
+ ...options,
693
+ mode: 'cors',
694
+ credentials: 'include', // If needed
695
+ };
696
+ ```
697
+
698
+ ### Token Not Persisting
699
+
700
+ **Problem**: Token is lost between requests.
701
+
702
+ **Solution**: Store token as instance property:
703
+
704
+ ```typescript
705
+ import {YourAPI, ClientOptions} from './generated/type.js';
706
+
707
+ class MyAPI extends YourAPI {
708
+ private token: string | null = null; // ✅ Instance property
709
+
710
+ constructor(options: ClientOptions = {}) {
711
+ super(options);
712
+ }
713
+
714
+ setToken(token: string) {
715
+ this.token = token; // ✅ Persists across requests
716
+ }
717
+ }
718
+ ```
719
+
720
+ ### Type Errors
721
+
722
+ **Problem**: TypeScript errors when overriding.
723
+
724
+ **Solution**: Ensure return type matches exactly:
725
+
726
+ ```typescript
727
+ protected getBaseRequestOptions(): Partial<Omit<RequestInit, 'method' | 'body'>> {
728
+ // ✅ Correct return type
729
+ }
730
+ ```