zod-codegen 1.0.2 → 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.
@@ -53,15 +53,15 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
53
53
  private buildAST(openapi: OpenApiSpecType): ts.Statement[] {
54
54
  const imports = this.importBuilder.buildImports();
55
55
  const schemas = this.buildSchemas(openapi);
56
+ const serverConfig = this.buildServerConfiguration(openapi);
56
57
  const clientClass = this.buildClientClass(openapi, schemas);
57
- const baseUrlConstant = this.buildBaseUrlConstant(openapi);
58
58
 
59
59
  return [
60
60
  this.createComment('Imports'),
61
61
  ...imports,
62
62
  this.createComment('Components schemas'),
63
63
  ...Object.values(schemas),
64
- ...baseUrlConstant,
64
+ ...serverConfig,
65
65
  this.createComment('Client class'),
66
66
  clientClass,
67
67
  ];
@@ -111,33 +111,132 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
111
111
  undefined,
112
112
  [
113
113
  this.typeBuilder.createProperty('#baseUrl', 'string', true),
114
- this.buildConstructor(),
114
+ this.buildConstructor(openapi),
115
+ this.buildGetBaseRequestOptionsMethod(),
115
116
  this.buildHttpRequestMethod(),
116
117
  ...methods,
117
118
  ],
118
119
  );
119
120
  }
120
121
 
121
- private buildConstructor(): ts.ConstructorDeclaration {
122
- return ts.factory.createConstructorDeclaration(
123
- undefined,
124
- [
125
- this.typeBuilder.createParameter('baseUrl', 'string', ts.factory.createIdentifier('defaultBaseUrl')),
126
- this.typeBuilder.createParameter('_', 'unknown', undefined, true),
127
- ],
128
- ts.factory.createBlock(
122
+ private buildConstructor(openapi: OpenApiSpecType): ts.ConstructorDeclaration {
123
+ const hasServers = openapi.servers && openapi.servers.length > 0;
124
+
125
+ if (hasServers) {
126
+ // Options-based constructor
127
+ return ts.factory.createConstructorDeclaration(
128
+ undefined,
129
129
  [
130
- ts.factory.createExpressionStatement(
131
- ts.factory.createBinaryExpression(
132
- ts.factory.createPropertyAccessExpression(
133
- ts.factory.createThis(),
134
- ts.factory.createPrivateIdentifier('#baseUrl'),
130
+ ts.factory.createParameterDeclaration(
131
+ undefined,
132
+ undefined,
133
+ ts.factory.createIdentifier('options'),
134
+ undefined,
135
+ ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('ClientOptions'), undefined),
136
+ undefined,
137
+ ),
138
+ ],
139
+ ts.factory.createBlock(
140
+ [
141
+ ts.factory.createVariableStatement(
142
+ undefined,
143
+ ts.factory.createVariableDeclarationList(
144
+ [
145
+ ts.factory.createVariableDeclaration(
146
+ ts.factory.createIdentifier('resolvedUrl'),
147
+ undefined,
148
+ undefined,
149
+ ts.factory.createConditionalExpression(
150
+ ts.factory.createBinaryExpression(
151
+ ts.factory.createPropertyAccessExpression(
152
+ ts.factory.createIdentifier('options'),
153
+ ts.factory.createIdentifier('baseUrl'),
154
+ ),
155
+ ts.factory.createToken(ts.SyntaxKind.ExclamationEqualsEqualsToken),
156
+ ts.factory.createNull(),
157
+ ),
158
+ ts.factory.createToken(ts.SyntaxKind.QuestionToken),
159
+ ts.factory.createPropertyAccessExpression(
160
+ ts.factory.createIdentifier('options'),
161
+ ts.factory.createIdentifier('baseUrl'),
162
+ ),
163
+ ts.factory.createToken(ts.SyntaxKind.ColonToken),
164
+ ts.factory.createCallExpression(ts.factory.createIdentifier('resolveServerUrl'), undefined, [
165
+ ts.factory.createPropertyAccessExpression(
166
+ ts.factory.createIdentifier('options'),
167
+ ts.factory.createIdentifier('serverIndex'),
168
+ ),
169
+ ts.factory.createPropertyAccessExpression(
170
+ ts.factory.createIdentifier('options'),
171
+ ts.factory.createIdentifier('serverVariables'),
172
+ ),
173
+ ]),
174
+ ),
175
+ ),
176
+ ],
177
+ ts.NodeFlags.Const,
135
178
  ),
136
- ts.factory.createToken(ts.SyntaxKind.EqualsToken),
137
- ts.factory.createIdentifier('baseUrl'),
138
179
  ),
139
- ),
180
+ ts.factory.createExpressionStatement(
181
+ ts.factory.createBinaryExpression(
182
+ ts.factory.createPropertyAccessExpression(
183
+ ts.factory.createThis(),
184
+ ts.factory.createPrivateIdentifier('#baseUrl'),
185
+ ),
186
+ ts.factory.createToken(ts.SyntaxKind.EqualsToken),
187
+ ts.factory.createIdentifier('resolvedUrl'),
188
+ ),
189
+ ),
190
+ ],
191
+ true,
192
+ ),
193
+ );
194
+ } else {
195
+ // Fallback: simple baseUrl parameter
196
+ return ts.factory.createConstructorDeclaration(
197
+ undefined,
198
+ [
199
+ this.typeBuilder.createParameter('baseUrl', 'string', ts.factory.createStringLiteral('/', true)),
200
+ this.typeBuilder.createParameter('_', 'unknown', undefined, true),
140
201
  ],
202
+ ts.factory.createBlock(
203
+ [
204
+ ts.factory.createExpressionStatement(
205
+ ts.factory.createBinaryExpression(
206
+ ts.factory.createPropertyAccessExpression(
207
+ ts.factory.createThis(),
208
+ ts.factory.createPrivateIdentifier('#baseUrl'),
209
+ ),
210
+ ts.factory.createToken(ts.SyntaxKind.EqualsToken),
211
+ ts.factory.createIdentifier('baseUrl'),
212
+ ),
213
+ ),
214
+ ],
215
+ true,
216
+ ),
217
+ );
218
+ }
219
+ }
220
+
221
+ private buildGetBaseRequestOptionsMethod(): ts.MethodDeclaration {
222
+ return ts.factory.createMethodDeclaration(
223
+ [ts.factory.createToken(ts.SyntaxKind.ProtectedKeyword)],
224
+ undefined,
225
+ ts.factory.createIdentifier('getBaseRequestOptions'),
226
+ undefined,
227
+ undefined,
228
+ [],
229
+ ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Partial'), [
230
+ ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Omit'), [
231
+ ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('RequestInit'), undefined),
232
+ ts.factory.createUnionTypeNode([
233
+ ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral('method', true)),
234
+ ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral('body', true)),
235
+ ]),
236
+ ]),
237
+ ]),
238
+ ts.factory.createBlock(
239
+ [ts.factory.createReturnStatement(ts.factory.createObjectLiteralExpression([], false))],
141
240
  true,
142
241
  ),
143
242
  );
@@ -155,7 +254,7 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
155
254
  this.typeBuilder.createParameter('path', 'string'),
156
255
  this.typeBuilder.createParameter(
157
256
  'options',
158
- '{params?: Record<string, string | number | boolean>; data?: unknown; contentType?: string}',
257
+ '{params?: Record<string, string | number | boolean>; data?: unknown; contentType?: string; headers?: Record<string, string>}',
159
258
  ts.factory.createObjectLiteralExpression([], false),
160
259
  false,
161
260
  ),
@@ -355,7 +454,87 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
355
454
  ts.NodeFlags.Const,
356
455
  ),
357
456
  ),
358
- // Build headers with dynamic Content-Type
457
+ // Get base request options (headers, signal, credentials, etc.)
458
+ ts.factory.createVariableStatement(
459
+ undefined,
460
+ ts.factory.createVariableDeclarationList(
461
+ [
462
+ ts.factory.createVariableDeclaration(
463
+ ts.factory.createIdentifier('baseOptions'),
464
+ undefined,
465
+ undefined,
466
+ ts.factory.createCallExpression(
467
+ ts.factory.createPropertyAccessExpression(
468
+ ts.factory.createThis(),
469
+ ts.factory.createIdentifier('getBaseRequestOptions'),
470
+ ),
471
+ undefined,
472
+ [],
473
+ ),
474
+ ),
475
+ ],
476
+ ts.NodeFlags.Const,
477
+ ),
478
+ ),
479
+ // Build Content-Type header
480
+ ts.factory.createVariableStatement(
481
+ undefined,
482
+ ts.factory.createVariableDeclarationList(
483
+ [
484
+ ts.factory.createVariableDeclaration(
485
+ ts.factory.createIdentifier('contentType'),
486
+ undefined,
487
+ undefined,
488
+ ts.factory.createConditionalExpression(
489
+ ts.factory.createBinaryExpression(
490
+ ts.factory.createPropertyAccessExpression(
491
+ ts.factory.createIdentifier('options'),
492
+ ts.factory.createIdentifier('contentType'),
493
+ ),
494
+ ts.factory.createToken(ts.SyntaxKind.EqualsEqualsEqualsToken),
495
+ ts.factory.createStringLiteral('application/x-www-form-urlencoded', true),
496
+ ),
497
+ undefined,
498
+ ts.factory.createStringLiteral('application/x-www-form-urlencoded', true),
499
+ undefined,
500
+ ts.factory.createStringLiteral('application/json', true),
501
+ ),
502
+ ),
503
+ ],
504
+ ts.NodeFlags.Const,
505
+ ),
506
+ ),
507
+ // Merge headers: base headers, Content-Type, and request-specific headers
508
+ ts.factory.createVariableStatement(
509
+ undefined,
510
+ ts.factory.createVariableDeclarationList(
511
+ [
512
+ ts.factory.createVariableDeclaration(
513
+ ts.factory.createIdentifier('baseHeaders'),
514
+ undefined,
515
+ undefined,
516
+ ts.factory.createConditionalExpression(
517
+ ts.factory.createBinaryExpression(
518
+ ts.factory.createPropertyAccessExpression(
519
+ ts.factory.createIdentifier('baseOptions'),
520
+ ts.factory.createIdentifier('headers'),
521
+ ),
522
+ ts.factory.createToken(ts.SyntaxKind.ExclamationEqualsEqualsToken),
523
+ ts.factory.createIdentifier('undefined'),
524
+ ),
525
+ undefined,
526
+ ts.factory.createPropertyAccessExpression(
527
+ ts.factory.createIdentifier('baseOptions'),
528
+ ts.factory.createIdentifier('headers'),
529
+ ),
530
+ undefined,
531
+ ts.factory.createObjectLiteralExpression([], false),
532
+ ),
533
+ ),
534
+ ],
535
+ ts.NodeFlags.Const,
536
+ ),
537
+ ),
359
538
  ts.factory.createVariableStatement(
360
539
  undefined,
361
540
  ts.factory.createVariableDeclarationList(
@@ -364,27 +543,42 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
364
543
  ts.factory.createIdentifier('headers'),
365
544
  undefined,
366
545
  undefined,
367
- ts.factory.createObjectLiteralExpression(
546
+ ts.factory.createCallExpression(
547
+ ts.factory.createPropertyAccessExpression(
548
+ ts.factory.createIdentifier('Object'),
549
+ ts.factory.createIdentifier('assign'),
550
+ ),
551
+ undefined,
368
552
  [
369
- ts.factory.createPropertyAssignment(
370
- ts.factory.createStringLiteral('Content-Type', true),
371
- ts.factory.createConditionalExpression(
372
- ts.factory.createBinaryExpression(
373
- ts.factory.createPropertyAccessExpression(
374
- ts.factory.createIdentifier('options'),
375
- ts.factory.createIdentifier('contentType'),
376
- ),
377
- ts.factory.createToken(ts.SyntaxKind.EqualsEqualsEqualsToken),
378
- ts.factory.createStringLiteral('application/x-www-form-urlencoded', true),
553
+ ts.factory.createObjectLiteralExpression([], false),
554
+ ts.factory.createIdentifier('baseHeaders'),
555
+ ts.factory.createObjectLiteralExpression(
556
+ [
557
+ ts.factory.createPropertyAssignment(
558
+ ts.factory.createStringLiteral('Content-Type', true),
559
+ ts.factory.createIdentifier('contentType'),
379
560
  ),
380
- undefined,
381
- ts.factory.createStringLiteral('application/x-www-form-urlencoded', true),
382
- undefined,
383
- ts.factory.createStringLiteral('application/json', true),
561
+ ],
562
+ false,
563
+ ),
564
+ ts.factory.createConditionalExpression(
565
+ ts.factory.createBinaryExpression(
566
+ ts.factory.createPropertyAccessExpression(
567
+ ts.factory.createIdentifier('options'),
568
+ ts.factory.createIdentifier('headers'),
569
+ ),
570
+ ts.factory.createToken(ts.SyntaxKind.ExclamationEqualsEqualsToken),
571
+ ts.factory.createIdentifier('undefined'),
384
572
  ),
573
+ undefined,
574
+ ts.factory.createPropertyAccessExpression(
575
+ ts.factory.createIdentifier('options'),
576
+ ts.factory.createIdentifier('headers'),
577
+ ),
578
+ undefined,
579
+ ts.factory.createObjectLiteralExpression([], false),
385
580
  ),
386
581
  ],
387
- true,
388
582
  ),
389
583
  ),
390
584
  ],
@@ -564,7 +758,7 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
564
758
  ts.NodeFlags.Const,
565
759
  ),
566
760
  ),
567
- // Make fetch request
761
+ // Make fetch request: merge base options with method, headers, and body
568
762
  ts.factory.createVariableStatement(
569
763
  undefined,
570
764
  ts.factory.createVariableDeclarationList(
@@ -576,22 +770,33 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
576
770
  ts.factory.createAwaitExpression(
577
771
  ts.factory.createCallExpression(ts.factory.createIdentifier('fetch'), undefined, [
578
772
  ts.factory.createIdentifier('url'),
579
- ts.factory.createObjectLiteralExpression(
773
+ ts.factory.createCallExpression(
774
+ ts.factory.createPropertyAccessExpression(
775
+ ts.factory.createIdentifier('Object'),
776
+ ts.factory.createIdentifier('assign'),
777
+ ),
778
+ undefined,
580
779
  [
581
- ts.factory.createShorthandPropertyAssignment(
582
- ts.factory.createIdentifier('method'),
583
- undefined,
584
- ),
585
- ts.factory.createPropertyAssignment(
586
- ts.factory.createIdentifier('headers'),
587
- ts.factory.createIdentifier('headers'),
588
- ),
589
- ts.factory.createPropertyAssignment(
590
- ts.factory.createIdentifier('body'),
591
- ts.factory.createIdentifier('body'),
780
+ ts.factory.createObjectLiteralExpression([], false),
781
+ ts.factory.createIdentifier('baseOptions'),
782
+ ts.factory.createObjectLiteralExpression(
783
+ [
784
+ ts.factory.createShorthandPropertyAssignment(
785
+ ts.factory.createIdentifier('method'),
786
+ undefined,
787
+ ),
788
+ ts.factory.createPropertyAssignment(
789
+ ts.factory.createIdentifier('headers'),
790
+ ts.factory.createIdentifier('headers'),
791
+ ),
792
+ ts.factory.createPropertyAssignment(
793
+ ts.factory.createIdentifier('body'),
794
+ ts.factory.createIdentifier('body'),
795
+ ),
796
+ ],
797
+ false,
592
798
  ),
593
799
  ],
594
- true,
595
800
  ),
596
801
  ]),
597
802
  ),
@@ -1049,28 +1254,407 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
1049
1254
  ]);
1050
1255
  }
1051
1256
 
1052
- private buildBaseUrlConstant(openapi: OpenApiSpecType): ts.Statement[] {
1053
- const baseUrl = openapi.servers?.[0]?.url;
1054
- if (!baseUrl) {
1257
+ private buildServerConfiguration(openapi: OpenApiSpecType): ts.Statement[] {
1258
+ const servers = openapi.servers;
1259
+
1260
+ if (!servers || servers.length === 0) {
1055
1261
  return [];
1056
1262
  }
1057
1263
 
1058
- return [
1264
+ const statements: ts.Statement[] = [];
1265
+
1266
+ // Build server configuration array
1267
+ const serverConfigElements = servers.map((server) => {
1268
+ const properties: ts.PropertyAssignment[] = [
1269
+ ts.factory.createPropertyAssignment('url', ts.factory.createStringLiteral(server.url, true)),
1270
+ ];
1271
+
1272
+ if (server.description) {
1273
+ properties.push(
1274
+ ts.factory.createPropertyAssignment('description', ts.factory.createStringLiteral(server.description, true)),
1275
+ );
1276
+ }
1277
+
1278
+ if (server.variables && Object.keys(server.variables).length > 0) {
1279
+ const variableProperties = Object.entries(server.variables).map(([varName, varDef]) => {
1280
+ const varProps: ts.PropertyAssignment[] = [
1281
+ ts.factory.createPropertyAssignment('default', ts.factory.createStringLiteral(varDef.default, true)),
1282
+ ];
1283
+
1284
+ if (varDef.enum && varDef.enum.length > 0) {
1285
+ varProps.push(
1286
+ ts.factory.createPropertyAssignment(
1287
+ 'enum',
1288
+ ts.factory.createArrayLiteralExpression(
1289
+ varDef.enum.map((val) => ts.factory.createStringLiteral(val, true)),
1290
+ false,
1291
+ ),
1292
+ ),
1293
+ );
1294
+ }
1295
+
1296
+ if (varDef.description) {
1297
+ varProps.push(
1298
+ ts.factory.createPropertyAssignment(
1299
+ 'description',
1300
+ ts.factory.createStringLiteral(varDef.description, true),
1301
+ ),
1302
+ );
1303
+ }
1304
+
1305
+ return ts.factory.createPropertyAssignment(varName, ts.factory.createObjectLiteralExpression(varProps, true));
1306
+ });
1307
+
1308
+ properties.push(
1309
+ ts.factory.createPropertyAssignment(
1310
+ 'variables',
1311
+ ts.factory.createObjectLiteralExpression(variableProperties, true),
1312
+ ),
1313
+ );
1314
+ }
1315
+
1316
+ return ts.factory.createObjectLiteralExpression(properties, true);
1317
+ });
1318
+
1319
+ // Export server configuration
1320
+ statements.push(
1059
1321
  ts.factory.createVariableStatement(
1060
- undefined,
1322
+ [ts.factory.createToken(ts.SyntaxKind.ExportKeyword)],
1323
+ ts.factory.createVariableDeclarationList(
1324
+ [
1325
+ ts.factory.createVariableDeclaration(
1326
+ ts.factory.createIdentifier('serverConfigurations'),
1327
+ undefined,
1328
+ undefined,
1329
+ ts.factory.createArrayLiteralExpression(serverConfigElements, false),
1330
+ ),
1331
+ ],
1332
+ ts.NodeFlags.Const,
1333
+ ),
1334
+ ),
1335
+ );
1336
+
1337
+ // Export default base URL (first server with default variables)
1338
+ const firstServer = servers[0];
1339
+ const defaultBaseUrl = firstServer ? this.resolveServerUrl(firstServer, {}) : '/';
1340
+ statements.push(
1341
+ ts.factory.createVariableStatement(
1342
+ [ts.factory.createToken(ts.SyntaxKind.ExportKeyword)],
1061
1343
  ts.factory.createVariableDeclarationList(
1062
1344
  [
1063
1345
  ts.factory.createVariableDeclaration(
1064
1346
  ts.factory.createIdentifier('defaultBaseUrl'),
1065
1347
  undefined,
1066
1348
  undefined,
1067
- ts.factory.createStringLiteral(baseUrl, true),
1349
+ ts.factory.createStringLiteral(defaultBaseUrl, true),
1350
+ ),
1351
+ ],
1352
+ ts.NodeFlags.Const,
1353
+ ),
1354
+ ),
1355
+ );
1356
+
1357
+ // Build ClientOptions type
1358
+ const optionProperties: ts.PropertySignature[] = [
1359
+ ts.factory.createPropertySignature(
1360
+ undefined,
1361
+ ts.factory.createIdentifier('baseUrl'),
1362
+ ts.factory.createToken(ts.SyntaxKind.QuestionToken),
1363
+ ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
1364
+ ),
1365
+ ts.factory.createPropertySignature(
1366
+ undefined,
1367
+ ts.factory.createIdentifier('serverIndex'),
1368
+ ts.factory.createToken(ts.SyntaxKind.QuestionToken),
1369
+ ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword),
1370
+ ),
1371
+ ts.factory.createPropertySignature(
1372
+ undefined,
1373
+ ts.factory.createIdentifier('serverVariables'),
1374
+ ts.factory.createToken(ts.SyntaxKind.QuestionToken),
1375
+ ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Record'), [
1376
+ ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
1377
+ ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
1378
+ ]),
1379
+ ),
1380
+ ];
1381
+
1382
+ statements.push(
1383
+ ts.factory.createTypeAliasDeclaration(
1384
+ [ts.factory.createToken(ts.SyntaxKind.ExportKeyword)],
1385
+ ts.factory.createIdentifier('ClientOptions'),
1386
+ undefined,
1387
+ ts.factory.createTypeLiteralNode(optionProperties),
1388
+ ),
1389
+ );
1390
+
1391
+ // Build resolveServerUrl helper function
1392
+ statements.push(this.buildResolveServerUrlFunction(servers));
1393
+
1394
+ return statements;
1395
+ }
1396
+
1397
+ private resolveServerUrl(
1398
+ server: {
1399
+ url: string;
1400
+ variables?:
1401
+ | Record<string, {default: string; enum?: string[] | undefined; description?: string | undefined}>
1402
+ | undefined;
1403
+ },
1404
+ variables: Record<string, string>,
1405
+ ): string {
1406
+ let url = server.url;
1407
+
1408
+ if (server.variables) {
1409
+ for (const [varName, varDef] of Object.entries(server.variables)) {
1410
+ const value = variables[varName] ?? varDef.default;
1411
+ url = url.replace(`{${varName}}`, value);
1412
+ }
1413
+ }
1414
+
1415
+ return url;
1416
+ }
1417
+
1418
+ private buildResolveServerUrlFunction(
1419
+ servers: {
1420
+ url: string;
1421
+ description?: string | undefined;
1422
+ variables?:
1423
+ | Record<string, {default: string; enum?: string[] | undefined; description?: string | undefined}>
1424
+ | undefined;
1425
+ }[],
1426
+ ): ts.FunctionDeclaration {
1427
+ // Build server configs array inline
1428
+ const serverConfigElements = servers.map((server) => {
1429
+ const properties: ts.PropertyAssignment[] = [
1430
+ ts.factory.createPropertyAssignment('url', ts.factory.createStringLiteral(server.url, true)),
1431
+ ];
1432
+
1433
+ if (server.variables && Object.keys(server.variables).length > 0) {
1434
+ const variableProperties = Object.entries(server.variables).map(([varName, varDef]) => {
1435
+ const varProps: ts.PropertyAssignment[] = [
1436
+ ts.factory.createPropertyAssignment('default', ts.factory.createStringLiteral(varDef.default, true)),
1437
+ ];
1438
+
1439
+ if (varDef.enum && varDef.enum.length > 0) {
1440
+ varProps.push(
1441
+ ts.factory.createPropertyAssignment(
1442
+ 'enum',
1443
+ ts.factory.createArrayLiteralExpression(
1444
+ varDef.enum.map((val) => ts.factory.createStringLiteral(val, true)),
1445
+ false,
1446
+ ),
1447
+ ),
1448
+ );
1449
+ }
1450
+
1451
+ return ts.factory.createPropertyAssignment(varName, ts.factory.createObjectLiteralExpression(varProps, true));
1452
+ });
1453
+
1454
+ properties.push(
1455
+ ts.factory.createPropertyAssignment(
1456
+ 'variables',
1457
+ ts.factory.createObjectLiteralExpression(variableProperties, true),
1458
+ ),
1459
+ );
1460
+ }
1461
+
1462
+ return ts.factory.createObjectLiteralExpression(properties, true);
1463
+ });
1464
+
1465
+ // Build function body - simplified version
1466
+ const idx = ts.factory.createIdentifier('idx');
1467
+ const configs = ts.factory.createIdentifier('configs');
1468
+ const config = ts.factory.createIdentifier('config');
1469
+ const url = ts.factory.createIdentifier('url');
1470
+ const key = ts.factory.createIdentifier('key');
1471
+ const value = ts.factory.createIdentifier('value');
1472
+
1473
+ const bodyStatements: ts.Statement[] = [
1474
+ // const configs = [...]
1475
+ ts.factory.createVariableStatement(
1476
+ undefined,
1477
+ ts.factory.createVariableDeclarationList(
1478
+ [
1479
+ ts.factory.createVariableDeclaration(
1480
+ configs,
1481
+ undefined,
1482
+ undefined,
1483
+ ts.factory.createArrayLiteralExpression(serverConfigElements, false),
1484
+ ),
1485
+ ],
1486
+ ts.NodeFlags.Const,
1487
+ ),
1488
+ ),
1489
+ // const idx = serverIndex ?? 0
1490
+ ts.factory.createVariableStatement(
1491
+ undefined,
1492
+ ts.factory.createVariableDeclarationList(
1493
+ [
1494
+ ts.factory.createVariableDeclaration(
1495
+ idx,
1496
+ undefined,
1497
+ undefined,
1498
+ ts.factory.createBinaryExpression(
1499
+ ts.factory.createIdentifier('serverIndex'),
1500
+ ts.factory.createToken(ts.SyntaxKind.QuestionQuestionToken),
1501
+ ts.factory.createNumericLiteral('0'),
1502
+ ),
1068
1503
  ),
1069
1504
  ],
1070
1505
  ts.NodeFlags.Const,
1071
1506
  ),
1072
1507
  ),
1508
+ // if (idx < configs.length) { ... }
1509
+ ts.factory.createIfStatement(
1510
+ ts.factory.createBinaryExpression(
1511
+ idx,
1512
+ ts.factory.createToken(ts.SyntaxKind.LessThanToken),
1513
+ ts.factory.createPropertyAccessExpression(configs, ts.factory.createIdentifier('length')),
1514
+ ),
1515
+ ts.factory.createBlock(
1516
+ [
1517
+ // const config = configs[idx]
1518
+ ts.factory.createVariableStatement(
1519
+ undefined,
1520
+ ts.factory.createVariableDeclarationList(
1521
+ [
1522
+ ts.factory.createVariableDeclaration(
1523
+ config,
1524
+ undefined,
1525
+ undefined,
1526
+ ts.factory.createElementAccessExpression(configs, idx),
1527
+ ),
1528
+ ],
1529
+ ts.NodeFlags.Const,
1530
+ ),
1531
+ ),
1532
+ // let url = config.url
1533
+ ts.factory.createVariableStatement(
1534
+ undefined,
1535
+ ts.factory.createVariableDeclarationList(
1536
+ [
1537
+ ts.factory.createVariableDeclaration(
1538
+ url,
1539
+ undefined,
1540
+ undefined,
1541
+ ts.factory.createPropertyAccessExpression(config, ts.factory.createIdentifier('url')),
1542
+ ),
1543
+ ],
1544
+ ts.NodeFlags.Let,
1545
+ ),
1546
+ ),
1547
+ // if (config.variables && serverVariables) { ... }
1548
+ ts.factory.createIfStatement(
1549
+ ts.factory.createLogicalAnd(
1550
+ ts.factory.createPropertyAccessExpression(config, ts.factory.createIdentifier('variables')),
1551
+ ts.factory.createIdentifier('serverVariables'),
1552
+ ),
1553
+ ts.factory.createBlock(
1554
+ [
1555
+ // for (const [key, value] of Object.entries(serverVariables)) { url = url.replace(...) }
1556
+ ts.factory.createForOfStatement(
1557
+ undefined,
1558
+ ts.factory.createVariableDeclarationList(
1559
+ [
1560
+ ts.factory.createVariableDeclaration(
1561
+ ts.factory.createArrayBindingPattern([
1562
+ ts.factory.createBindingElement(undefined, undefined, key),
1563
+ ts.factory.createBindingElement(undefined, undefined, value),
1564
+ ]),
1565
+ undefined,
1566
+ undefined,
1567
+ ),
1568
+ ],
1569
+ ts.NodeFlags.Const,
1570
+ ),
1571
+ ts.factory.createCallExpression(
1572
+ ts.factory.createPropertyAccessExpression(
1573
+ ts.factory.createIdentifier('Object'),
1574
+ ts.factory.createIdentifier('entries'),
1575
+ ),
1576
+ undefined,
1577
+ [ts.factory.createIdentifier('serverVariables')],
1578
+ ),
1579
+ ts.factory.createBlock(
1580
+ [
1581
+ ts.factory.createExpressionStatement(
1582
+ ts.factory.createBinaryExpression(
1583
+ url,
1584
+ ts.factory.createToken(ts.SyntaxKind.EqualsToken),
1585
+ ts.factory.createCallExpression(
1586
+ ts.factory.createPropertyAccessExpression(url, ts.factory.createIdentifier('replace')),
1587
+ undefined,
1588
+ [
1589
+ ts.factory.createNewExpression(ts.factory.createIdentifier('RegExp'), undefined, [
1590
+ ts.factory.createBinaryExpression(
1591
+ ts.factory.createBinaryExpression(
1592
+ ts.factory.createStringLiteral('\\{'),
1593
+ ts.factory.createToken(ts.SyntaxKind.PlusToken),
1594
+ key,
1595
+ ),
1596
+ ts.factory.createToken(ts.SyntaxKind.PlusToken),
1597
+ ts.factory.createStringLiteral('\\}'),
1598
+ ),
1599
+ ts.factory.createStringLiteral('g'),
1600
+ ]),
1601
+ value,
1602
+ ],
1603
+ ),
1604
+ ),
1605
+ ),
1606
+ ],
1607
+ true,
1608
+ ),
1609
+ ),
1610
+ ],
1611
+ true,
1612
+ ),
1613
+ ),
1614
+ // return url
1615
+ ts.factory.createReturnStatement(url),
1616
+ ],
1617
+ true,
1618
+ ),
1619
+ ),
1620
+ // return default (first server with defaults)
1621
+ ts.factory.createReturnStatement(
1622
+ ts.factory.createStringLiteral(servers[0] ? this.resolveServerUrl(servers[0], {}) : '/', true),
1623
+ ),
1073
1624
  ];
1625
+
1626
+ return ts.factory.createFunctionDeclaration(
1627
+ undefined,
1628
+ undefined,
1629
+ ts.factory.createIdentifier('resolveServerUrl'),
1630
+ undefined,
1631
+ [
1632
+ ts.factory.createParameterDeclaration(
1633
+ undefined,
1634
+ undefined,
1635
+ ts.factory.createIdentifier('serverIndex'),
1636
+ ts.factory.createToken(ts.SyntaxKind.QuestionToken),
1637
+ ts.factory.createUnionTypeNode([
1638
+ ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword),
1639
+ ts.factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword),
1640
+ ]),
1641
+ undefined,
1642
+ ),
1643
+ ts.factory.createParameterDeclaration(
1644
+ undefined,
1645
+ undefined,
1646
+ ts.factory.createIdentifier('serverVariables'),
1647
+ ts.factory.createToken(ts.SyntaxKind.QuestionToken),
1648
+ ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Record'), [
1649
+ ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
1650
+ ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
1651
+ ]),
1652
+ ts.factory.createObjectLiteralExpression([], false),
1653
+ ),
1654
+ ],
1655
+ ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
1656
+ ts.factory.createBlock(bodyStatements, true),
1657
+ );
1074
1658
  }
1075
1659
 
1076
1660
  private generateClientName(title: string): string {