zod-codegen 1.6.2 → 1.7.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.
Files changed (119) hide show
  1. package/.github/workflows/ci.yml +50 -48
  2. package/.github/workflows/release.yml +13 -3
  3. package/.husky/commit-msg +1 -1
  4. package/.husky/pre-commit +1 -1
  5. package/.lintstagedrc.json +5 -1
  6. package/.nvmrc +1 -1
  7. package/.prettierrc.json +12 -5
  8. package/CHANGELOG.md +15 -0
  9. package/CONTRIBUTING.md +12 -12
  10. package/EXAMPLES.md +135 -57
  11. package/PERFORMANCE.md +4 -4
  12. package/README.md +87 -64
  13. package/SECURITY.md +1 -1
  14. package/dist/src/cli.js +11 -18
  15. package/dist/src/generator.d.ts +2 -2
  16. package/dist/src/generator.d.ts.map +1 -1
  17. package/dist/src/generator.js +5 -3
  18. package/dist/src/interfaces/code-generator.d.ts.map +1 -1
  19. package/dist/src/services/code-generator.service.d.ts +24 -1
  20. package/dist/src/services/code-generator.service.d.ts.map +1 -1
  21. package/dist/src/services/code-generator.service.js +385 -216
  22. package/dist/src/services/file-reader.service.d.ts.map +1 -1
  23. package/dist/src/services/file-reader.service.js +1 -1
  24. package/dist/src/services/file-writer.service.d.ts.map +1 -1
  25. package/dist/src/services/file-writer.service.js +2 -2
  26. package/dist/src/services/import-builder.service.d.ts.map +1 -1
  27. package/dist/src/services/import-builder.service.js +3 -3
  28. package/dist/src/services/type-builder.service.d.ts.map +1 -1
  29. package/dist/src/types/generator-options.d.ts.map +1 -1
  30. package/dist/src/types/openapi.d.ts.map +1 -1
  31. package/dist/src/types/openapi.js +20 -20
  32. package/dist/src/utils/error-handler.d.ts.map +1 -1
  33. package/dist/src/utils/naming-convention.d.ts.map +1 -1
  34. package/dist/src/utils/naming-convention.js +6 -3
  35. package/dist/src/utils/signal-handler.d.ts.map +1 -1
  36. package/dist/tests/integration/cli-comprehensive.test.d.ts +2 -0
  37. package/dist/tests/integration/cli-comprehensive.test.d.ts.map +1 -0
  38. package/dist/tests/integration/cli-comprehensive.test.js +110 -0
  39. package/dist/tests/integration/cli.test.d.ts +2 -0
  40. package/dist/tests/integration/cli.test.d.ts.map +1 -0
  41. package/dist/tests/integration/cli.test.js +25 -0
  42. package/dist/tests/integration/error-scenarios.test.d.ts +2 -0
  43. package/dist/tests/integration/error-scenarios.test.d.ts.map +1 -0
  44. package/dist/tests/integration/error-scenarios.test.js +169 -0
  45. package/dist/tests/integration/snapshots.test.d.ts +2 -0
  46. package/dist/tests/integration/snapshots.test.d.ts.map +1 -0
  47. package/dist/tests/integration/snapshots.test.js +100 -0
  48. package/dist/tests/unit/code-generator-edge-cases.test.d.ts +2 -0
  49. package/dist/tests/unit/code-generator-edge-cases.test.d.ts.map +1 -0
  50. package/dist/tests/unit/code-generator-edge-cases.test.js +506 -0
  51. package/dist/tests/unit/code-generator.test.d.ts +2 -0
  52. package/dist/tests/unit/code-generator.test.d.ts.map +1 -0
  53. package/dist/tests/unit/code-generator.test.js +1364 -0
  54. package/dist/tests/unit/file-reader.test.d.ts +2 -0
  55. package/dist/tests/unit/file-reader.test.d.ts.map +1 -0
  56. package/dist/tests/unit/file-reader.test.js +125 -0
  57. package/dist/tests/unit/generator.test.d.ts +2 -0
  58. package/dist/tests/unit/generator.test.d.ts.map +1 -0
  59. package/dist/tests/unit/generator.test.js +119 -0
  60. package/dist/tests/unit/naming-convention.test.d.ts +2 -0
  61. package/dist/tests/unit/naming-convention.test.d.ts.map +1 -0
  62. package/dist/tests/unit/naming-convention.test.js +256 -0
  63. package/dist/tests/unit/reporter.test.d.ts +2 -0
  64. package/dist/tests/unit/reporter.test.d.ts.map +1 -0
  65. package/dist/tests/unit/reporter.test.js +44 -0
  66. package/dist/tests/unit/type-builder.test.d.ts +2 -0
  67. package/dist/tests/unit/type-builder.test.d.ts.map +1 -0
  68. package/dist/tests/unit/type-builder.test.js +108 -0
  69. package/dist/vitest.config.d.ts.map +1 -1
  70. package/dist/vitest.config.js +10 -20
  71. package/eslint.config.mjs +38 -28
  72. package/examples/.gitkeep +1 -1
  73. package/examples/README.md +4 -2
  74. package/examples/petstore/README.md +18 -17
  75. package/examples/petstore/{type.ts → api.ts} +158 -74
  76. package/examples/petstore/authenticated-usage.ts +6 -4
  77. package/examples/petstore/basic-usage.ts +4 -3
  78. package/examples/petstore/error-handling-usage.ts +84 -0
  79. package/examples/petstore/retry-handler-usage.ts +11 -18
  80. package/examples/petstore/server-variables-usage.ts +10 -10
  81. package/examples/pokeapi/README.md +8 -8
  82. package/examples/pokeapi/api.ts +218 -0
  83. package/examples/pokeapi/basic-usage.ts +3 -2
  84. package/examples/pokeapi/custom-client.ts +5 -4
  85. package/package.json +17 -21
  86. package/src/cli.ts +20 -25
  87. package/src/generator.ts +13 -11
  88. package/src/interfaces/code-generator.ts +1 -1
  89. package/src/services/code-generator.service.ts +989 -1099
  90. package/src/services/file-reader.service.ts +6 -5
  91. package/src/services/file-writer.service.ts +7 -7
  92. package/src/services/import-builder.service.ts +9 -13
  93. package/src/services/type-builder.service.ts +8 -19
  94. package/src/types/generator-options.ts +1 -1
  95. package/src/types/openapi.ts +22 -22
  96. package/src/utils/error-handler.ts +2 -2
  97. package/src/utils/naming-convention.ts +13 -10
  98. package/src/utils/reporter.ts +2 -2
  99. package/src/utils/signal-handler.ts +7 -8
  100. package/tests/integration/cli-comprehensive.test.ts +38 -32
  101. package/tests/integration/cli.test.ts +5 -5
  102. package/tests/integration/error-scenarios.test.ts +20 -26
  103. package/tests/integration/snapshots.test.ts +19 -23
  104. package/tests/unit/code-generator-edge-cases.test.ts +133 -133
  105. package/tests/unit/code-generator.test.ts +674 -268
  106. package/tests/unit/file-reader.test.ts +14 -14
  107. package/tests/unit/generator.test.ts +30 -18
  108. package/tests/unit/naming-convention.test.ts +27 -27
  109. package/tests/unit/type-builder.test.ts +2 -2
  110. package/tsconfig.json +5 -3
  111. package/vitest.config.ts +11 -21
  112. package/dist/scripts/update-manifest.d.ts +0 -14
  113. package/dist/scripts/update-manifest.d.ts.map +0 -1
  114. package/dist/scripts/update-manifest.js +0 -33
  115. package/dist/src/assets/manifest.json +0 -5
  116. package/examples/pokeapi/type.ts +0 -109
  117. package/generated/type.ts +0 -326
  118. package/scripts/update-manifest.ts +0 -49
  119. package/src/assets/manifest.json +0 -5
@@ -1,10 +1,9 @@
1
- import jp from 'jsonpath';
2
1
  import * as ts from 'typescript';
3
2
  import { z } from 'zod';
4
3
  import { MethodSchema, Reference, SchemaProperties } from '../types/openapi.js';
4
+ import { transformNamingConvention } from '../utils/naming-convention.js';
5
5
  import { TypeScriptImportBuilderService } from './import-builder.service.js';
6
6
  import { TypeScriptTypeBuilderService } from './type-builder.service.js';
7
- import { transformNamingConvention, } from '../utils/naming-convention.js';
8
7
  export class TypeScriptCodeGeneratorService {
9
8
  typeBuilder = new TypeScriptTypeBuilderService();
10
9
  importBuilder = new TypeScriptImportBuilderService();
@@ -20,10 +19,33 @@ export class TypeScriptCodeGeneratorService {
20
19
  }
21
20
  ZodAST = z.object({
22
21
  type: z.enum(['string', 'number', 'boolean', 'object', 'array', 'unknown', 'record']),
23
- args: z.array(z.unknown()).optional(),
22
+ args: z.array(z.unknown()).optional()
24
23
  });
24
+ extractSchemaReferences(schema) {
25
+ const references = new Set();
26
+ const walk = (node) => {
27
+ if (Array.isArray(node)) {
28
+ for (const item of node) {
29
+ walk(item);
30
+ }
31
+ return;
32
+ }
33
+ if (node === null || typeof node !== 'object') {
34
+ return;
35
+ }
36
+ for (const [key, value] of Object.entries(node)) {
37
+ if (key === '$ref' && typeof value === 'string' && value.startsWith('#/components/schemas/')) {
38
+ references.add(value.replace('#/components/schemas/', ''));
39
+ continue;
40
+ }
41
+ walk(value);
42
+ }
43
+ };
44
+ walk(schema);
45
+ return [...references];
46
+ }
25
47
  generate(spec) {
26
- const file = ts.createSourceFile('generated.ts', '', ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
48
+ const file = ts.createSourceFile('api.ts', '', ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
27
49
  const nodes = this.buildAST(spec);
28
50
  return this.printer.printList(ts.ListFormat.MultiLine, ts.factory.createNodeArray(nodes), file);
29
51
  }
@@ -53,15 +75,19 @@ export class TypeScriptCodeGeneratorService {
53
75
  const schemaTypeAliases = this.buildSchemaTypeAliases(schemas);
54
76
  const serverConfig = this.buildServerConfiguration(openapi);
55
77
  const clientClass = this.buildClientClass(openapi, schemas);
78
+ const explicitTypeDeclarations = this.buildExplicitTypeDeclarations(openapi);
56
79
  return [
57
80
  this.createComment('Imports'),
58
81
  ...imports,
82
+ this.createComment('Explicit type declarations'),
83
+ ...explicitTypeDeclarations,
59
84
  this.createComment('Components schemas'),
60
85
  ...Object.values(schemas),
61
86
  ...schemaTypeAliases,
62
87
  ...serverConfig,
88
+ this.buildResponseValidationErrorClass(),
63
89
  this.createComment('Client class'),
64
- clientClass,
90
+ clientClass
65
91
  ];
66
92
  }
67
93
  buildSchemas(openapi) {
@@ -72,27 +98,195 @@ export class TypeScriptCodeGeneratorService {
72
98
  const sortedSchemaNames = this.topologicalSort(schemasMap);
73
99
  return sortedSchemaNames.reduce((schemaRegistered, name) => {
74
100
  const schema = openapi.components?.schemas?.[name];
75
- if (!schema)
101
+ if (!schema) {
76
102
  return schemaRegistered;
103
+ }
77
104
  // Set context for current schema being built
78
105
  this.currentSchemaName = name;
79
106
  const schemaExpression = this.buildSchema(schema);
80
107
  // Clear context
81
108
  this.currentSchemaName = null;
82
- const variableStatement = ts.factory.createVariableStatement([ts.factory.createToken(ts.SyntaxKind.ExportKeyword)], ts.factory.createVariableDeclarationList([
83
- ts.factory.createVariableDeclaration(ts.factory.createIdentifier(this.typeBuilder.sanitizeIdentifier(name)), undefined, undefined, schemaExpression),
84
- ], ts.NodeFlags.Const));
109
+ const sanitizedName = this.typeBuilder.sanitizeIdentifier(name);
110
+ // Add type annotation: z.ZodType<Name>
111
+ const typeAnnotation = ts.factory.createTypeReferenceNode(ts.factory.createQualifiedName(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('ZodType')), [
112
+ ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(sanitizedName), undefined)
113
+ ]);
114
+ const variableStatement = ts.factory.createVariableStatement([ts.factory.createToken(ts.SyntaxKind.ExportKeyword)], ts.factory.createVariableDeclarationList([ts.factory.createVariableDeclaration(ts.factory.createIdentifier(sanitizedName), undefined, typeAnnotation, schemaExpression)], ts.NodeFlags.Const));
85
115
  return {
86
116
  ...schemaRegistered,
87
- [name]: variableStatement,
117
+ [name]: variableStatement
88
118
  };
89
119
  }, {});
90
120
  }
91
- buildSchemaTypeAliases(schemas) {
92
- return Object.keys(schemas).map((name) => {
121
+ buildSchemaTypeAliases(_schemas) {
122
+ // Explicit type declarations are used instead of z.infer type exports
123
+ return [];
124
+ }
125
+ /**
126
+ * Builds explicit TypeScript type declarations for all schemas.
127
+ * Returns interface declarations for object types and type aliases for other types.
128
+ */
129
+ buildExplicitTypeDeclarations(openapi) {
130
+ const schemasEntries = Object.entries(openapi.components?.schemas ?? {});
131
+ const schemasMap = Object.fromEntries(schemasEntries);
132
+ const sortedSchemaNames = this.topologicalSort(schemasMap);
133
+ const statements = [];
134
+ for (const name of sortedSchemaNames) {
135
+ const schema = openapi.components?.schemas?.[name];
136
+ if (!schema) {
137
+ continue;
138
+ }
93
139
  const sanitizedName = this.typeBuilder.sanitizeIdentifier(name);
94
- return ts.factory.createTypeAliasDeclaration([ts.factory.createToken(ts.SyntaxKind.ExportKeyword)], ts.factory.createIdentifier(sanitizedName), undefined, ts.factory.createTypeReferenceNode(ts.factory.createQualifiedName(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('infer')), [ts.factory.createTypeQueryNode(ts.factory.createIdentifier(sanitizedName), undefined)]));
140
+ const safeSchema = SchemaProperties.safeParse(schema);
141
+ if (!safeSchema.success) {
142
+ // Unknown schema type, create a type alias to unknown
143
+ statements.push(ts.factory.createTypeAliasDeclaration([ts.factory.createToken(ts.SyntaxKind.ExportKeyword)], ts.factory.createIdentifier(sanitizedName), undefined, ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword)));
144
+ continue;
145
+ }
146
+ const schemaData = safeSchema.data;
147
+ const typeNode = this.buildTypeNode(schemaData);
148
+ // For object types with properties, create an interface
149
+ if (schemaData['type'] === 'object' && schemaData['properties']) {
150
+ statements.push(this.buildInterfaceDeclaration(sanitizedName, schemaData));
151
+ continue;
152
+ }
153
+ // For all other types (enums, arrays, unions, etc.), create a type alias
154
+ statements.push(ts.factory.createTypeAliasDeclaration([ts.factory.createToken(ts.SyntaxKind.ExportKeyword)], ts.factory.createIdentifier(sanitizedName), undefined, typeNode));
155
+ }
156
+ return statements;
157
+ }
158
+ /**
159
+ * Converts an OpenAPI schema to a TypeScript type node.
160
+ */
161
+ buildTypeNode(schema) {
162
+ const safeSchema = SchemaProperties.safeParse(schema);
163
+ if (!safeSchema.success) {
164
+ return ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword);
165
+ }
166
+ const prop = safeSchema.data;
167
+ // Handle $ref
168
+ if (this.isReference(prop)) {
169
+ const { $ref = '' } = Reference.parse(prop);
170
+ const refName = $ref.split('/').pop() ?? 'never';
171
+ const sanitizedRefName = this.typeBuilder.sanitizeIdentifier(refName);
172
+ return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(sanitizedRefName), undefined);
173
+ }
174
+ // Handle nullable
175
+ const isNullable = prop['nullable'] === true;
176
+ const baseTypeNode = this.buildBaseTypeNode(prop);
177
+ if (isNullable) {
178
+ return ts.factory.createUnionTypeNode([baseTypeNode, ts.factory.createLiteralTypeNode(ts.factory.createNull())]);
179
+ }
180
+ return baseTypeNode;
181
+ }
182
+ /**
183
+ * Builds the base type node without nullable handling.
184
+ */
185
+ buildBaseTypeNode(prop) {
186
+ // Handle anyOf/oneOf (union types)
187
+ if (prop['anyOf'] && Array.isArray(prop['anyOf']) && prop['anyOf'].length > 0) {
188
+ const types = prop['anyOf'].map((s) => this.buildTypeNode(s));
189
+ return ts.factory.createUnionTypeNode(types);
190
+ }
191
+ if (prop['oneOf'] && Array.isArray(prop['oneOf']) && prop['oneOf'].length > 0) {
192
+ const types = prop['oneOf'].map((s) => this.buildTypeNode(s));
193
+ return ts.factory.createUnionTypeNode(types);
194
+ }
195
+ // Handle allOf (intersection types)
196
+ if (prop['allOf'] && Array.isArray(prop['allOf']) && prop['allOf'].length > 0) {
197
+ const types = prop['allOf'].map((s) => this.buildTypeNode(s));
198
+ return ts.factory.createIntersectionTypeNode(types);
199
+ }
200
+ // Handle enum
201
+ if (prop['enum'] && Array.isArray(prop['enum']) && prop['enum'].length > 0) {
202
+ const literalTypes = prop['enum'].map((val) => {
203
+ if (typeof val === 'string') {
204
+ return ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(val, true));
205
+ }
206
+ else if (typeof val === 'number') {
207
+ if (val < 0) {
208
+ return ts.factory.createLiteralTypeNode(ts.factory.createPrefixUnaryExpression(ts.SyntaxKind.MinusToken, ts.factory.createNumericLiteral(String(Math.abs(val)))));
209
+ }
210
+ return ts.factory.createLiteralTypeNode(ts.factory.createNumericLiteral(String(val)));
211
+ }
212
+ else if (typeof val === 'boolean') {
213
+ return ts.factory.createLiteralTypeNode(val ? ts.factory.createTrue() : ts.factory.createFalse());
214
+ }
215
+ return ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword);
216
+ });
217
+ return ts.factory.createUnionTypeNode(literalTypes);
218
+ }
219
+ // Handle type-specific schemas
220
+ switch (prop['type']) {
221
+ case 'string':
222
+ return ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword);
223
+ case 'number':
224
+ case 'integer':
225
+ return ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword);
226
+ case 'boolean':
227
+ return ts.factory.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword);
228
+ case 'array': {
229
+ const itemsType = prop['items'] ? this.buildTypeNode(prop['items']) : ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword);
230
+ return ts.factory.createArrayTypeNode(itemsType);
231
+ }
232
+ case 'object': {
233
+ const properties = (prop['properties'] ?? {});
234
+ const requiredProps = (prop['required'] ?? []);
235
+ if (Object.keys(properties).length > 0) {
236
+ return this.buildObjectTypeLiteral(properties, requiredProps);
237
+ }
238
+ // Empty object or additionalProperties - use Record<string, unknown>
239
+ return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Record'), [
240
+ ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
241
+ ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword)
242
+ ]);
243
+ }
244
+ default:
245
+ return ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword);
246
+ }
247
+ }
248
+ /**
249
+ * Builds a TypeScript type literal for an object schema.
250
+ */
251
+ buildObjectTypeLiteral(properties, requiredProps) {
252
+ const members = Object.entries(properties).map(([name, propSchema]) => {
253
+ const isRequired = requiredProps.includes(name);
254
+ const typeNode = this.buildTypeNode(propSchema);
255
+ return ts.factory.createPropertySignature(undefined, ts.factory.createIdentifier(name), isRequired ? undefined : ts.factory.createToken(ts.SyntaxKind.QuestionToken), typeNode);
95
256
  });
257
+ return ts.factory.createTypeLiteralNode(members);
258
+ }
259
+ /**
260
+ * Builds a TypeScript interface declaration for an object schema.
261
+ */
262
+ buildInterfaceDeclaration(name, schema) {
263
+ const properties = (schema['properties'] ?? {});
264
+ const requiredProps = (schema['required'] ?? []);
265
+ const members = Object.entries(properties).map(([propName, propSchema]) => {
266
+ const isRequired = requiredProps.includes(propName);
267
+ const typeNode = this.buildTypeNode(propSchema);
268
+ return ts.factory.createPropertySignature(undefined, ts.factory.createIdentifier(propName), isRequired ? undefined : ts.factory.createToken(ts.SyntaxKind.QuestionToken), typeNode);
269
+ });
270
+ return ts.factory.createInterfaceDeclaration([ts.factory.createToken(ts.SyntaxKind.ExportKeyword)], ts.factory.createIdentifier(name), undefined, undefined, members);
271
+ }
272
+ buildResponseValidationErrorClass() {
273
+ const typeParamT = ts.factory.createTypeParameterDeclaration(undefined, 'T');
274
+ const responseProperty = ts.factory.createPropertyDeclaration([ts.factory.createToken(ts.SyntaxKind.ReadonlyKeyword)], 'response', undefined, ts.factory.createTypeReferenceNode('Response'), undefined);
275
+ const errorProperty = ts.factory.createPropertyDeclaration([ts.factory.createToken(ts.SyntaxKind.ReadonlyKeyword)], 'error', undefined, ts.factory.createTypeReferenceNode(ts.factory.createQualifiedName(ts.factory.createIdentifier('z'), 'ZodError'), [ts.factory.createTypeReferenceNode('T')]), undefined);
276
+ const constructorDecl = ts.factory.createConstructorDeclaration(undefined, [
277
+ ts.factory.createParameterDeclaration(undefined, undefined, 'message', undefined, ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword)),
278
+ ts.factory.createParameterDeclaration(undefined, undefined, 'response', undefined, ts.factory.createTypeReferenceNode('Response')),
279
+ ts.factory.createParameterDeclaration(undefined, undefined, 'error', undefined, ts.factory.createTypeReferenceNode(ts.factory.createQualifiedName(ts.factory.createIdentifier('z'), 'ZodError'), [ts.factory.createTypeReferenceNode('T')]))
280
+ ], ts.factory.createBlock([
281
+ ts.factory.createExpressionStatement(ts.factory.createCallExpression(ts.factory.createSuper(), undefined, [ts.factory.createIdentifier('message')])),
282
+ ts.factory.createExpressionStatement(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createThis(), 'name'), ts.SyntaxKind.EqualsToken, ts.factory.createAsExpression(ts.factory.createStringLiteral('ResponseValidationError', true), ts.factory.createTypeReferenceNode('const')))),
283
+ ts.factory.createExpressionStatement(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createThis(), 'response'), ts.SyntaxKind.EqualsToken, ts.factory.createIdentifier('response'))),
284
+ ts.factory.createExpressionStatement(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createThis(), 'error'), ts.SyntaxKind.EqualsToken, ts.factory.createIdentifier('error')))
285
+ ], true));
286
+ const dataGetter = ts.factory.createGetAccessorDeclaration(undefined, 'data', [], ts.factory.createTypeReferenceNode('T'), ts.factory.createBlock([
287
+ ts.factory.createReturnStatement(ts.factory.createAsExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createPropertyAccessExpression(ts.factory.createThis(), 'response'), 'json'), undefined, []), ts.factory.createTypeReferenceNode('T')))
288
+ ], true));
289
+ return ts.factory.createClassDeclaration([ts.factory.createToken(ts.SyntaxKind.ExportKeyword)], 'ResponseValidationError', [typeParamT], [ts.factory.createHeritageClause(ts.SyntaxKind.ExtendsKeyword, [ts.factory.createExpressionWithTypeArguments(ts.factory.createIdentifier('Error'), undefined)])], [responseProperty, errorProperty, constructorDecl, dataGetter]);
96
290
  }
97
291
  buildClientClass(openapi, schemas) {
98
292
  const clientName = this.generateClientName(openapi.info.title);
@@ -103,7 +297,7 @@ export class TypeScriptCodeGeneratorService {
103
297
  this.buildGetBaseRequestOptionsMethod(),
104
298
  this.buildHandleResponseMethod(),
105
299
  this.buildHttpRequestMethod(),
106
- ...methods,
300
+ ...methods
107
301
  ]);
108
302
  }
109
303
  buildConstructor(openapi) {
@@ -111,24 +305,21 @@ export class TypeScriptCodeGeneratorService {
111
305
  if (hasServers) {
112
306
  // Options-based constructor
113
307
  return ts.factory.createConstructorDeclaration(undefined, [
114
- ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createIdentifier('options'), undefined, ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('ClientOptions'), undefined), undefined),
308
+ ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createIdentifier('options'), undefined, ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('ClientOptions'), undefined), undefined)
115
309
  ], ts.factory.createBlock([
116
310
  ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([
117
311
  ts.factory.createVariableDeclaration(ts.factory.createIdentifier('resolvedUrl'), undefined, undefined, ts.factory.createConditionalExpression(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('baseUrl')), ts.factory.createToken(ts.SyntaxKind.ExclamationEqualsEqualsToken), ts.factory.createNull()), ts.factory.createToken(ts.SyntaxKind.QuestionToken), ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('baseUrl')), ts.factory.createToken(ts.SyntaxKind.ColonToken), ts.factory.createCallExpression(ts.factory.createIdentifier('resolveServerUrl'), undefined, [
118
312
  ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('serverIndex')),
119
- ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('serverVariables')),
120
- ]))),
313
+ ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('serverVariables'))
314
+ ])))
121
315
  ], ts.NodeFlags.Const)),
122
- ts.factory.createExpressionStatement(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createThis(), ts.factory.createPrivateIdentifier('#baseUrl')), ts.factory.createToken(ts.SyntaxKind.EqualsToken), ts.factory.createIdentifier('resolvedUrl'))),
316
+ ts.factory.createExpressionStatement(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createThis(), ts.factory.createPrivateIdentifier('#baseUrl')), ts.factory.createToken(ts.SyntaxKind.EqualsToken), ts.factory.createIdentifier('resolvedUrl')))
123
317
  ], true));
124
318
  }
125
319
  else {
126
320
  // Fallback: simple baseUrl parameter
127
- return ts.factory.createConstructorDeclaration(undefined, [
128
- this.typeBuilder.createParameter('baseUrl', 'string', ts.factory.createStringLiteral('/', true)),
129
- this.typeBuilder.createParameter('_', 'unknown', undefined, true),
130
- ], ts.factory.createBlock([
131
- ts.factory.createExpressionStatement(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createThis(), ts.factory.createPrivateIdentifier('#baseUrl')), ts.factory.createToken(ts.SyntaxKind.EqualsToken), ts.factory.createIdentifier('baseUrl'))),
321
+ return ts.factory.createConstructorDeclaration(undefined, [this.typeBuilder.createParameter('baseUrl', 'string', ts.factory.createStringLiteral('/', true)), this.typeBuilder.createParameter('_', 'unknown', undefined, true)], ts.factory.createBlock([
322
+ ts.factory.createExpressionStatement(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createThis(), ts.factory.createPrivateIdentifier('#baseUrl')), ts.factory.createToken(ts.SyntaxKind.EqualsToken), ts.factory.createIdentifier('baseUrl')))
132
323
  ], true));
133
324
  }
134
325
  }
@@ -138,9 +329,9 @@ export class TypeScriptCodeGeneratorService {
138
329
  ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('RequestInit'), undefined),
139
330
  ts.factory.createUnionTypeNode([
140
331
  ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral('method', true)),
141
- ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral('body', true)),
142
- ]),
143
- ]),
332
+ ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral('body', true))
333
+ ])
334
+ ])
144
335
  ]), ts.factory.createBlock([ts.factory.createReturnStatement(ts.factory.createObjectLiteralExpression([], false))], true));
145
336
  }
146
337
  buildHandleResponseMethod() {
@@ -148,76 +339,66 @@ export class TypeScriptCodeGeneratorService {
148
339
  this.typeBuilder.createParameter('response', 'Response'),
149
340
  this.typeBuilder.createParameter('method', 'string'),
150
341
  this.typeBuilder.createParameter('path', 'string'),
151
- this.typeBuilder.createParameter('options', '{params?: Record<string, string | number | boolean>; data?: unknown; contentType?: string; headers?: Record<string, string>}'),
152
- ], ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
153
- ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Response'), undefined),
154
- ]), ts.factory.createBlock([ts.factory.createReturnStatement(ts.factory.createIdentifier('response'))], true));
342
+ this.typeBuilder.createParameter('options', '{params?: Record<string, string | number | boolean>; data?: unknown; contentType?: string; headers?: Record<string, string>}')
343
+ ], ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Response'), undefined)]), ts.factory.createBlock([ts.factory.createReturnStatement(ts.factory.createIdentifier('response'))], true));
155
344
  }
156
345
  buildHttpRequestMethod() {
157
346
  return ts.factory.createMethodDeclaration([ts.factory.createToken(ts.SyntaxKind.ProtectedKeyword), ts.factory.createToken(ts.SyntaxKind.AsyncKeyword)], undefined, ts.factory.createIdentifier('makeRequest'), undefined, [this.typeBuilder.createGenericType('T')], [
158
347
  this.typeBuilder.createParameter('method', 'string'),
159
348
  this.typeBuilder.createParameter('path', 'string'),
160
- this.typeBuilder.createParameter('options', '{params?: Record<string, string | number | boolean>; data?: unknown; contentType?: string; headers?: Record<string, string>}', ts.factory.createObjectLiteralExpression([], false), false),
161
- ], ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
162
- ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('T'), undefined),
163
- ]), ts.factory.createBlock([
349
+ this.typeBuilder.createParameter('options', '{params?: Record<string, string | number | boolean>; data?: unknown; contentType?: string; headers?: Record<string, string>}', ts.factory.createObjectLiteralExpression([], false), false)
350
+ ], ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('T'), undefined)]), ts.factory.createBlock([
164
351
  // Create initial URL object that we will use to build the final URL
165
352
  ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([
166
353
  ts.factory.createVariableDeclaration(ts.factory.createIdentifier('baseUrl'), undefined, undefined, ts.factory.createNewExpression(ts.factory.createIdentifier('URL'), undefined, [
167
354
  ts.factory.createIdentifier('path'),
168
- ts.factory.createPropertyAccessExpression(ts.factory.createThis(), ts.factory.createPrivateIdentifier('#baseUrl')),
169
- ])),
355
+ ts.factory.createPropertyAccessExpression(ts.factory.createThis(), ts.factory.createPrivateIdentifier('#baseUrl'))
356
+ ]))
170
357
  ], ts.NodeFlags.Const)),
171
358
  ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([
172
- ts.factory.createVariableDeclaration(ts.factory.createIdentifier('url'), undefined, undefined, ts.factory.createConditionalExpression(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('params')), ts.factory.createToken(ts.SyntaxKind.AmpersandAmpersandToken), ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('Object'), ts.factory.createIdentifier('keys')), undefined, [
173
- ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('params')),
174
- ]), ts.factory.createIdentifier('length')), ts.factory.createToken(ts.SyntaxKind.GreaterThanToken), ts.factory.createNumericLiteral('0'))), undefined, ts.factory.createCallExpression(ts.factory.createParenthesizedExpression(ts.factory.createArrowFunction(undefined, undefined, [], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createBlock([
175
- ts.factory.createExpressionStatement(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('Object'), ts.factory.createIdentifier('entries')), undefined, [
176
- ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('params')),
177
- ]), ts.factory.createIdentifier('filter')), undefined, [
359
+ ts.factory.createVariableDeclaration(ts.factory.createIdentifier('url'), undefined, undefined, ts.factory.createConditionalExpression(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('params')), ts.factory.createToken(ts.SyntaxKind.AmpersandAmpersandToken), ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('Object'), ts.factory.createIdentifier('keys')), undefined, [ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('params'))]), ts.factory.createIdentifier('length')), ts.factory.createToken(ts.SyntaxKind.GreaterThanToken), ts.factory.createNumericLiteral('0'))), undefined, ts.factory.createCallExpression(ts.factory.createParenthesizedExpression(ts.factory.createArrowFunction(undefined, undefined, [], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createBlock([
360
+ ts.factory.createExpressionStatement(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('Object'), ts.factory.createIdentifier('entries')), undefined, [ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('params'))]), ts.factory.createIdentifier('filter')), undefined, [
178
361
  ts.factory.createArrowFunction(undefined, undefined, [
179
362
  ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createArrayBindingPattern([
180
363
  ts.factory.createBindingElement(undefined, undefined, ts.factory.createIdentifier(''), undefined),
181
- ts.factory.createBindingElement(undefined, undefined, ts.factory.createIdentifier('value'), undefined),
182
- ]), undefined, undefined),
183
- ], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createBinaryExpression(ts.factory.createIdentifier('value'), ts.SyntaxKind.ExclamationEqualsEqualsToken, ts.factory.createIdentifier('undefined'))),
364
+ ts.factory.createBindingElement(undefined, undefined, ts.factory.createIdentifier('value'), undefined)
365
+ ]), undefined, undefined)
366
+ ], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createBinaryExpression(ts.factory.createIdentifier('value'), ts.SyntaxKind.ExclamationEqualsEqualsToken, ts.factory.createIdentifier('undefined')))
184
367
  ]), ts.factory.createIdentifier('forEach')), undefined, [
185
368
  ts.factory.createArrowFunction(undefined, undefined, [
186
369
  ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createArrayBindingPattern([
187
370
  ts.factory.createBindingElement(undefined, undefined, ts.factory.createIdentifier('key'), undefined),
188
- ts.factory.createBindingElement(undefined, undefined, ts.factory.createIdentifier('value'), undefined),
189
- ]), undefined, undefined),
371
+ ts.factory.createBindingElement(undefined, undefined, ts.factory.createIdentifier('value'), undefined)
372
+ ]), undefined, undefined)
190
373
  ], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createBlock([
191
374
  ts.factory.createExpressionStatement(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('baseUrl'), ts.factory.createIdentifier('searchParams')), ts.factory.createIdentifier('set')), undefined, [
192
375
  ts.factory.createIdentifier('key'),
193
- ts.factory.createCallExpression(ts.factory.createIdentifier('String'), undefined, [ts.factory.createIdentifier('value')]),
194
- ])),
195
- ], false)),
376
+ ts.factory.createCallExpression(ts.factory.createIdentifier('String'), undefined, [ts.factory.createIdentifier('value')])
377
+ ]))
378
+ ], false))
196
379
  ])),
197
- ts.factory.createReturnStatement(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('baseUrl'), ts.factory.createIdentifier('toString')), undefined, [])),
198
- ], true))), undefined, []), undefined, ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('baseUrl'), ts.factory.createIdentifier('toString')), undefined, []))),
380
+ ts.factory.createReturnStatement(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('baseUrl'), ts.factory.createIdentifier('toString')), undefined, []))
381
+ ], true))), undefined, []), undefined, ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('baseUrl'), ts.factory.createIdentifier('toString')), undefined, [])))
199
382
  ], ts.NodeFlags.Const)),
200
383
  // Get base request options (headers, signal, credentials, etc.)
201
384
  ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([
202
- ts.factory.createVariableDeclaration(ts.factory.createIdentifier('baseOptions'), undefined, undefined, ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createThis(), ts.factory.createIdentifier('getBaseRequestOptions')), undefined, [])),
385
+ ts.factory.createVariableDeclaration(ts.factory.createIdentifier('baseOptions'), undefined, undefined, ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createThis(), ts.factory.createIdentifier('getBaseRequestOptions')), undefined, []))
203
386
  ], ts.NodeFlags.Const)),
204
387
  // Build Content-Type header
205
388
  ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([
206
- ts.factory.createVariableDeclaration(ts.factory.createIdentifier('contentType'), undefined, undefined, ts.factory.createConditionalExpression(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('contentType')), ts.factory.createToken(ts.SyntaxKind.EqualsEqualsEqualsToken), ts.factory.createStringLiteral('application/x-www-form-urlencoded', true)), undefined, ts.factory.createStringLiteral('application/x-www-form-urlencoded', true), undefined, ts.factory.createStringLiteral('application/json', true))),
389
+ ts.factory.createVariableDeclaration(ts.factory.createIdentifier('contentType'), undefined, undefined, ts.factory.createConditionalExpression(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('contentType')), ts.factory.createToken(ts.SyntaxKind.EqualsEqualsEqualsToken), ts.factory.createStringLiteral('application/x-www-form-urlencoded', true)), undefined, ts.factory.createStringLiteral('application/x-www-form-urlencoded', true), undefined, ts.factory.createStringLiteral('application/json', true)))
207
390
  ], ts.NodeFlags.Const)),
208
391
  // Merge headers: base headers, Content-Type, and request-specific headers
209
392
  ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([
210
- ts.factory.createVariableDeclaration(ts.factory.createIdentifier('baseHeaders'), undefined, undefined, ts.factory.createConditionalExpression(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('baseOptions'), ts.factory.createIdentifier('headers')), ts.factory.createToken(ts.SyntaxKind.ExclamationEqualsEqualsToken), ts.factory.createIdentifier('undefined')), undefined, ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('baseOptions'), ts.factory.createIdentifier('headers')), undefined, ts.factory.createObjectLiteralExpression([], false))),
393
+ ts.factory.createVariableDeclaration(ts.factory.createIdentifier('baseHeaders'), undefined, undefined, ts.factory.createConditionalExpression(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('baseOptions'), ts.factory.createIdentifier('headers')), ts.factory.createToken(ts.SyntaxKind.ExclamationEqualsEqualsToken), ts.factory.createIdentifier('undefined')), undefined, ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('baseOptions'), ts.factory.createIdentifier('headers')), undefined, ts.factory.createObjectLiteralExpression([], false)))
211
394
  ], ts.NodeFlags.Const)),
212
395
  ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([
213
396
  ts.factory.createVariableDeclaration(ts.factory.createIdentifier('headers'), undefined, undefined, ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('Object'), ts.factory.createIdentifier('assign')), undefined, [
214
397
  ts.factory.createObjectLiteralExpression([], false),
215
398
  ts.factory.createIdentifier('baseHeaders'),
216
- ts.factory.createObjectLiteralExpression([
217
- ts.factory.createPropertyAssignment(ts.factory.createStringLiteral('Content-Type', true), ts.factory.createIdentifier('contentType')),
218
- ], false),
219
- ts.factory.createConditionalExpression(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('headers')), ts.factory.createToken(ts.SyntaxKind.ExclamationEqualsEqualsToken), ts.factory.createIdentifier('undefined')), undefined, ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('headers')), undefined, ts.factory.createObjectLiteralExpression([], false)),
220
- ])),
399
+ ts.factory.createObjectLiteralExpression([ts.factory.createPropertyAssignment(ts.factory.createStringLiteral('Content-Type', true), ts.factory.createIdentifier('contentType'))], false),
400
+ ts.factory.createConditionalExpression(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('headers')), ts.factory.createToken(ts.SyntaxKind.ExclamationEqualsEqualsToken), ts.factory.createIdentifier('undefined')), undefined, ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('headers')), undefined, ts.factory.createObjectLiteralExpression([], false))
401
+ ]))
221
402
  ], ts.NodeFlags.Const)),
222
403
  // Build body with form-urlencoded support
223
404
  ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([
@@ -225,29 +406,25 @@ export class TypeScriptCodeGeneratorService {
225
406
  // Form-urlencoded: convert object to URLSearchParams
226
407
  ts.factory.createCallExpression(ts.factory.createParenthesizedExpression(ts.factory.createArrowFunction(undefined, undefined, [], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createBlock([
227
408
  ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([
228
- ts.factory.createVariableDeclaration(ts.factory.createIdentifier('params'), undefined, undefined, ts.factory.createNewExpression(ts.factory.createIdentifier('URLSearchParams'), undefined, [])),
409
+ ts.factory.createVariableDeclaration(ts.factory.createIdentifier('params'), undefined, undefined, ts.factory.createNewExpression(ts.factory.createIdentifier('URLSearchParams'), undefined, []))
229
410
  ], ts.NodeFlags.Const)),
230
- ts.factory.createExpressionStatement(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('Object'), ts.factory.createIdentifier('entries')), undefined, [
231
- ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('data')),
232
- ]), ts.factory.createIdentifier('forEach')), undefined, [
411
+ ts.factory.createExpressionStatement(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('Object'), ts.factory.createIdentifier('entries')), undefined, [ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('data'))]), ts.factory.createIdentifier('forEach')), undefined, [
233
412
  ts.factory.createArrowFunction(undefined, undefined, [
234
413
  ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createArrayBindingPattern([
235
414
  ts.factory.createBindingElement(undefined, undefined, ts.factory.createIdentifier('key'), undefined),
236
- ts.factory.createBindingElement(undefined, undefined, ts.factory.createIdentifier('value'), undefined),
237
- ]), undefined, undefined),
415
+ ts.factory.createBindingElement(undefined, undefined, ts.factory.createIdentifier('value'), undefined)
416
+ ]), undefined, undefined)
238
417
  ], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createBlock([
239
418
  ts.factory.createExpressionStatement(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('params'), ts.factory.createIdentifier('set')), undefined, [
240
419
  ts.factory.createIdentifier('key'),
241
- ts.factory.createCallExpression(ts.factory.createIdentifier('String'), undefined, [ts.factory.createIdentifier('value')]),
242
- ])),
243
- ], false)),
420
+ ts.factory.createCallExpression(ts.factory.createIdentifier('String'), undefined, [ts.factory.createIdentifier('value')])
421
+ ]))
422
+ ], false))
244
423
  ])),
245
- ts.factory.createReturnStatement(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('params'), ts.factory.createIdentifier('toString')), undefined, [])),
424
+ ts.factory.createReturnStatement(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('params'), ts.factory.createIdentifier('toString')), undefined, []))
246
425
  ], false))), undefined, []), undefined,
247
426
  // JSON: stringify the data
248
- ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('JSON'), ts.factory.createIdentifier('stringify')), undefined, [
249
- ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('data')),
250
- ])), undefined, ts.factory.createNull())),
427
+ ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('JSON'), ts.factory.createIdentifier('stringify')), undefined, [ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('data'))])), undefined, ts.factory.createNull()))
251
428
  ], ts.NodeFlags.Const)),
252
429
  // Make fetch request: merge base options with method, headers, and body
253
430
  ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([
@@ -259,10 +436,10 @@ export class TypeScriptCodeGeneratorService {
259
436
  ts.factory.createObjectLiteralExpression([
260
437
  ts.factory.createShorthandPropertyAssignment(ts.factory.createIdentifier('method'), undefined),
261
438
  ts.factory.createPropertyAssignment(ts.factory.createIdentifier('headers'), ts.factory.createIdentifier('headers')),
262
- ts.factory.createPropertyAssignment(ts.factory.createIdentifier('body'), ts.factory.createIdentifier('body')),
263
- ], false),
264
- ]),
265
- ]))),
439
+ ts.factory.createPropertyAssignment(ts.factory.createIdentifier('body'), ts.factory.createIdentifier('body'))
440
+ ], false)
441
+ ])
442
+ ])))
266
443
  ], ts.NodeFlags.Const)),
267
444
  // Handle response through hook (allows subclasses to intercept and modify response)
268
445
  ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([
@@ -270,18 +447,18 @@ export class TypeScriptCodeGeneratorService {
270
447
  ts.factory.createIdentifier('rawResponse'),
271
448
  ts.factory.createIdentifier('method'),
272
449
  ts.factory.createIdentifier('path'),
273
- ts.factory.createIdentifier('options'),
274
- ]))),
450
+ ts.factory.createIdentifier('options')
451
+ ])))
275
452
  ], ts.NodeFlags.Const)),
276
453
  // Check response status
277
454
  ts.factory.createIfStatement(ts.factory.createPrefixUnaryExpression(ts.SyntaxKind.ExclamationToken, ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('response'), ts.factory.createIdentifier('ok'))), ts.factory.createThrowStatement(ts.factory.createNewExpression(ts.factory.createIdentifier('Error'), undefined, [
278
455
  ts.factory.createTemplateExpression(ts.factory.createTemplateHead('HTTP ', 'HTTP '), [
279
456
  ts.factory.createTemplateSpan(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('response'), ts.factory.createIdentifier('status')), ts.factory.createTemplateMiddle(': ', ': ')),
280
- ts.factory.createTemplateSpan(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('response'), ts.factory.createIdentifier('statusText')), ts.factory.createTemplateTail('', '')),
281
- ]),
457
+ ts.factory.createTemplateSpan(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('response'), ts.factory.createIdentifier('statusText')), ts.factory.createTemplateTail('', ''))
458
+ ])
282
459
  ])), undefined),
283
460
  // Return parsed JSON
284
- ts.factory.createReturnStatement(ts.factory.createAwaitExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('response'), ts.factory.createIdentifier('json')), undefined, []))),
461
+ ts.factory.createReturnStatement(ts.factory.createAwaitExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('response'), ts.factory.createIdentifier('json')), undefined, [])))
285
462
  ], true));
286
463
  }
287
464
  buildClientMethods(openapi, schemas) {
@@ -327,7 +504,7 @@ export class TypeScriptCodeGeneratorService {
327
504
  // This will be handled in transformOperationName
328
505
  const modifiedSchema = {
329
506
  ...safeMethodSchema,
330
- operationId: `${operationId}_${methodLower}`,
507
+ operationId: `${operationId}_${methodLower}`
331
508
  };
332
509
  return this.buildEndpointMethod(method, path, modifiedSchema, schemas);
333
510
  }
@@ -352,7 +529,7 @@ export class TypeScriptCodeGeneratorService {
352
529
  path,
353
530
  ...(schema.tags !== undefined && { tags: schema.tags }),
354
531
  ...(schema.summary !== undefined && { summary: schema.summary }),
355
- ...(schema.description !== undefined && { description: schema.description }),
532
+ ...(schema.description !== undefined && { description: schema.description })
356
533
  };
357
534
  transformed = this.operationNameTransformer(details);
358
535
  }
@@ -391,9 +568,7 @@ export class TypeScriptCodeGeneratorService {
391
568
  }), false)
392
569
  : undefined;
393
570
  // Build request body
394
- const requestBodyExpression = hasRequestBody
395
- ? ts.factory.createIdentifier('body')
396
- : undefined;
571
+ const requestBodyExpression = hasRequestBody ? ts.factory.createIdentifier('body') : undefined;
397
572
  // Build options object for makeRequest
398
573
  const optionsProps = [];
399
574
  if (queryParamsExpression) {
@@ -409,10 +584,32 @@ export class TypeScriptCodeGeneratorService {
409
584
  const optionsExpression = ts.factory.createObjectLiteralExpression(optionsProps, false);
410
585
  // Call makeRequest
411
586
  const makeRequestCall = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createThis(), ts.factory.createIdentifier('makeRequest')), undefined, [ts.factory.createStringLiteral(method.toUpperCase(), true), pathExpression, optionsExpression]);
412
- // Add Zod validation if we have a response schema
413
587
  if (responseSchema) {
414
- const validateCall = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(responseSchema, ts.factory.createIdentifier('parse')), undefined, [ts.factory.createAwaitExpression(makeRequestCall)]);
415
- statements.push(ts.factory.createReturnStatement(validateCall));
588
+ const schemaName = responseSchema.text;
589
+ const schemaNameLower = schemaName.charAt(0).toLowerCase() + schemaName.slice(1);
590
+ const parsedVarName = `parsed${schemaName}`;
591
+ // const response = await this.makeRequest(...)
592
+ statements.push(ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([ts.factory.createVariableDeclaration('response', undefined, undefined, ts.factory.createAwaitExpression(makeRequestCall))], ts.NodeFlags.Const)));
593
+ // const parsed{Name} = {Schema}.safeParse(response)
594
+ statements.push(ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([
595
+ ts.factory.createVariableDeclaration(parsedVarName, undefined, undefined, ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(responseSchema, ts.factory.createIdentifier('safeParse')), undefined, [
596
+ ts.factory.createIdentifier('response')
597
+ ]))
598
+ ], ts.NodeFlags.Const)));
599
+ // if (!parsed{Name}.success) { throw new ResponseValidationError<{Type}>(...) }
600
+ statements.push(ts.factory.createIfStatement(ts.factory.createPrefixUnaryExpression(ts.SyntaxKind.ExclamationToken, ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(parsedVarName), 'success')), ts.factory.createBlock([
601
+ ts.factory.createThrowStatement(ts.factory.createNewExpression(ts.factory.createIdentifier('ResponseValidationError'), [ts.factory.createTypeReferenceNode(schemaName)], [
602
+ ts.factory.createTemplateExpression(ts.factory.createTemplateHead(`Invalid ${schemaNameLower}: `), [
603
+ ts.factory.createTemplateSpan(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createPropertyAccessExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(parsedVarName), 'error'), 'errors'), 'map'), undefined, [
604
+ ts.factory.createArrowFunction(undefined, undefined, [ts.factory.createParameterDeclaration(undefined, undefined, 'error')], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('error'), 'message'))
605
+ ]), 'join'), undefined, [ts.factory.createStringLiteral(', ', true)]), ts.factory.createTemplateTail(''))
606
+ ]),
607
+ ts.factory.createIdentifier('response'),
608
+ ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(parsedVarName), 'error')
609
+ ]))
610
+ ], true)));
611
+ // return parsed{Name}.data
612
+ statements.push(ts.factory.createReturnStatement(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(parsedVarName), 'data')));
416
613
  }
417
614
  else {
418
615
  statements.push(ts.factory.createReturnStatement(ts.factory.createAwaitExpression(makeRequestCall)));
@@ -441,7 +638,7 @@ export class TypeScriptCodeGeneratorService {
441
638
  matches.push({
442
639
  index: match.index,
443
640
  length: match[0].length,
444
- name: paramName,
641
+ name: paramName
445
642
  });
446
643
  }
447
644
  }
@@ -536,9 +733,7 @@ export class TypeScriptCodeGeneratorService {
536
733
  parameters.push(this.typeBuilder.createParameter('body', bodyType, undefined, !schema.requestBody?.required));
537
734
  }
538
735
  // Determine content type for request body
539
- const contentType = hasRequestBody && schema.requestBody?.content?.['application/x-www-form-urlencoded']
540
- ? 'application/x-www-form-urlencoded'
541
- : 'application/json';
736
+ const contentType = hasRequestBody && schema.requestBody?.content?.['application/x-www-form-urlencoded'] ? 'application/x-www-form-urlencoded' : 'application/json';
542
737
  return { parameters, pathParams, queryParams, hasRequestBody, contentType };
543
738
  }
544
739
  getParameterType(schema) {
@@ -632,9 +827,7 @@ export class TypeScriptCodeGeneratorService {
632
827
  const responseDefault = schema.responses?.['default'];
633
828
  const response = response200 ?? response201 ?? responseDefault;
634
829
  if (!response?.content?.['application/json']?.schema) {
635
- return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
636
- ts.factory.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword),
637
- ]);
830
+ return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [ts.factory.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword)]);
638
831
  }
639
832
  const responseSchema = response.content['application/json'].schema;
640
833
  const typeName = this.getSchemaTypeName(responseSchema, schemas);
@@ -646,26 +839,22 @@ export class TypeScriptCodeGeneratorService {
646
839
  if (schemas[sanitizedItemTypeName]) {
647
840
  // Use the type alias directly (it already uses z.infer)
648
841
  return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
649
- ts.factory.createArrayTypeNode(ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(sanitizedItemTypeName), undefined)),
842
+ ts.factory.createArrayTypeNode(ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(sanitizedItemTypeName), undefined))
650
843
  ]);
651
844
  }
652
845
  // If it's a primitive array, use the type name as-is
653
- return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
654
- ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(typeName), undefined),
655
- ]);
846
+ return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(typeName), undefined)]);
656
847
  }
657
848
  const sanitizedTypeName = this.typeBuilder.sanitizeIdentifier(typeName);
658
849
  // Check if it's a custom schema type (we have a type alias for it)
659
850
  if (schemas[sanitizedTypeName]) {
660
851
  // Use the type name directly (we have a type alias that already uses z.infer)
661
852
  return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
662
- ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(sanitizedTypeName), undefined),
853
+ ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(sanitizedTypeName), undefined)
663
854
  ]);
664
855
  }
665
856
  // For primitive types and Record types, use the type name directly
666
- return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
667
- ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(typeName), undefined),
668
- ]);
857
+ return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(typeName), undefined)]);
669
858
  }
670
859
  buildServerConfiguration(openapi) {
671
860
  const servers = openapi.servers;
@@ -675,17 +864,13 @@ export class TypeScriptCodeGeneratorService {
675
864
  const statements = [];
676
865
  // Build server configuration array
677
866
  const serverConfigElements = servers.map((server) => {
678
- const properties = [
679
- ts.factory.createPropertyAssignment('url', ts.factory.createStringLiteral(server.url, true)),
680
- ];
867
+ const properties = [ts.factory.createPropertyAssignment('url', ts.factory.createStringLiteral(server.url, true))];
681
868
  if (server.description) {
682
869
  properties.push(ts.factory.createPropertyAssignment('description', ts.factory.createStringLiteral(server.description, true)));
683
870
  }
684
871
  if (server.variables && Object.keys(server.variables).length > 0) {
685
872
  const variableProperties = Object.entries(server.variables).map(([varName, varDef]) => {
686
- const varProps = [
687
- ts.factory.createPropertyAssignment('default', ts.factory.createStringLiteral(varDef.default, true)),
688
- ];
873
+ const varProps = [ts.factory.createPropertyAssignment('default', ts.factory.createStringLiteral(varDef.default, true))];
689
874
  if (varDef.enum && varDef.enum.length > 0) {
690
875
  varProps.push(ts.factory.createPropertyAssignment('enum', ts.factory.createArrayLiteralExpression(varDef.enum.map((val) => ts.factory.createStringLiteral(val, true)), false)));
691
876
  }
@@ -700,22 +885,20 @@ export class TypeScriptCodeGeneratorService {
700
885
  });
701
886
  // Export server configuration
702
887
  statements.push(ts.factory.createVariableStatement([ts.factory.createToken(ts.SyntaxKind.ExportKeyword)], ts.factory.createVariableDeclarationList([
703
- ts.factory.createVariableDeclaration(ts.factory.createIdentifier('serverConfigurations'), undefined, undefined, ts.factory.createArrayLiteralExpression(serverConfigElements, false)),
888
+ ts.factory.createVariableDeclaration(ts.factory.createIdentifier('serverConfigurations'), undefined, undefined, ts.factory.createArrayLiteralExpression(serverConfigElements, false))
704
889
  ], ts.NodeFlags.Const)));
705
890
  // Export default base URL (first server with default variables)
706
891
  const firstServer = servers[0];
707
892
  const defaultBaseUrl = firstServer ? this.resolveServerUrl(firstServer, {}) : '/';
708
- statements.push(ts.factory.createVariableStatement([ts.factory.createToken(ts.SyntaxKind.ExportKeyword)], ts.factory.createVariableDeclarationList([
709
- ts.factory.createVariableDeclaration(ts.factory.createIdentifier('defaultBaseUrl'), undefined, undefined, ts.factory.createStringLiteral(defaultBaseUrl, true)),
710
- ], ts.NodeFlags.Const)));
893
+ statements.push(ts.factory.createVariableStatement([ts.factory.createToken(ts.SyntaxKind.ExportKeyword)], ts.factory.createVariableDeclarationList([ts.factory.createVariableDeclaration(ts.factory.createIdentifier('defaultBaseUrl'), undefined, undefined, ts.factory.createStringLiteral(defaultBaseUrl, true))], ts.NodeFlags.Const)));
711
894
  // Build ClientOptions type
712
895
  const optionProperties = [
713
896
  ts.factory.createPropertySignature(undefined, ts.factory.createIdentifier('baseUrl'), ts.factory.createToken(ts.SyntaxKind.QuestionToken), ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword)),
714
897
  ts.factory.createPropertySignature(undefined, ts.factory.createIdentifier('serverIndex'), ts.factory.createToken(ts.SyntaxKind.QuestionToken), ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword)),
715
898
  ts.factory.createPropertySignature(undefined, ts.factory.createIdentifier('serverVariables'), ts.factory.createToken(ts.SyntaxKind.QuestionToken), ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Record'), [
716
899
  ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
717
- ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
718
- ])),
900
+ ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword)
901
+ ]))
719
902
  ];
720
903
  statements.push(ts.factory.createTypeAliasDeclaration([ts.factory.createToken(ts.SyntaxKind.ExportKeyword)], ts.factory.createIdentifier('ClientOptions'), undefined, ts.factory.createTypeLiteralNode(optionProperties)));
721
904
  // Build resolveServerUrl helper function
@@ -735,14 +918,10 @@ export class TypeScriptCodeGeneratorService {
735
918
  buildResolveServerUrlFunction(servers) {
736
919
  // Build server configs array inline
737
920
  const serverConfigElements = servers.map((server) => {
738
- const properties = [
739
- ts.factory.createPropertyAssignment('url', ts.factory.createStringLiteral(server.url, true)),
740
- ];
921
+ const properties = [ts.factory.createPropertyAssignment('url', ts.factory.createStringLiteral(server.url, true))];
741
922
  if (server.variables && Object.keys(server.variables).length > 0) {
742
923
  const variableProperties = Object.entries(server.variables).map(([varName, varDef]) => {
743
- const varProps = [
744
- ts.factory.createPropertyAssignment('default', ts.factory.createStringLiteral(varDef.default, true)),
745
- ];
924
+ const varProps = [ts.factory.createPropertyAssignment('default', ts.factory.createStringLiteral(varDef.default, true))];
746
925
  if (varDef.enum && varDef.enum.length > 0) {
747
926
  varProps.push(ts.factory.createPropertyAssignment('enum', ts.factory.createArrayLiteralExpression(varDef.enum.map((val) => ts.factory.createStringLiteral(val, true)), false)));
748
927
  }
@@ -761,56 +940,47 @@ export class TypeScriptCodeGeneratorService {
761
940
  const value = ts.factory.createIdentifier('value');
762
941
  const bodyStatements = [
763
942
  // const configs = [...]
764
- ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([
765
- ts.factory.createVariableDeclaration(configs, undefined, undefined, ts.factory.createArrayLiteralExpression(serverConfigElements, false)),
766
- ], ts.NodeFlags.Const)),
943
+ ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([ts.factory.createVariableDeclaration(configs, undefined, undefined, ts.factory.createArrayLiteralExpression(serverConfigElements, false))], ts.NodeFlags.Const)),
767
944
  // const idx = serverIndex ?? 0
768
945
  ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([
769
- ts.factory.createVariableDeclaration(idx, undefined, undefined, ts.factory.createBinaryExpression(ts.factory.createIdentifier('serverIndex'), ts.factory.createToken(ts.SyntaxKind.QuestionQuestionToken), ts.factory.createNumericLiteral('0'))),
946
+ ts.factory.createVariableDeclaration(idx, undefined, undefined, ts.factory.createBinaryExpression(ts.factory.createIdentifier('serverIndex'), ts.factory.createToken(ts.SyntaxKind.QuestionQuestionToken), ts.factory.createNumericLiteral('0')))
770
947
  ], ts.NodeFlags.Const)),
771
948
  // if (idx < configs.length) { ... }
772
949
  ts.factory.createIfStatement(ts.factory.createBinaryExpression(idx, ts.factory.createToken(ts.SyntaxKind.LessThanToken), ts.factory.createPropertyAccessExpression(configs, ts.factory.createIdentifier('length'))), ts.factory.createBlock([
773
950
  // const config = configs[idx]
774
- ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([
775
- ts.factory.createVariableDeclaration(config, undefined, undefined, ts.factory.createElementAccessExpression(configs, idx)),
776
- ], ts.NodeFlags.Const)),
951
+ ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([ts.factory.createVariableDeclaration(config, undefined, undefined, ts.factory.createElementAccessExpression(configs, idx))], ts.NodeFlags.Const)),
777
952
  // let url = config.url
778
- ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([
779
- ts.factory.createVariableDeclaration(url, undefined, undefined, ts.factory.createPropertyAccessExpression(config, ts.factory.createIdentifier('url'))),
780
- ], ts.NodeFlags.Let)),
953
+ ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([ts.factory.createVariableDeclaration(url, undefined, undefined, ts.factory.createPropertyAccessExpression(config, ts.factory.createIdentifier('url')))], ts.NodeFlags.Let)),
781
954
  // if (config.variables && serverVariables) { ... }
782
955
  ts.factory.createIfStatement(ts.factory.createLogicalAnd(ts.factory.createPropertyAccessExpression(config, ts.factory.createIdentifier('variables')), ts.factory.createIdentifier('serverVariables')), ts.factory.createBlock([
783
956
  // for (const [key, value] of Object.entries(serverVariables)) { url = url.replace(...) }
784
957
  ts.factory.createForOfStatement(undefined, ts.factory.createVariableDeclarationList([
785
958
  ts.factory.createVariableDeclaration(ts.factory.createArrayBindingPattern([
786
959
  ts.factory.createBindingElement(undefined, undefined, key),
787
- ts.factory.createBindingElement(undefined, undefined, value),
788
- ]), undefined, undefined),
960
+ ts.factory.createBindingElement(undefined, undefined, value)
961
+ ]), undefined, undefined)
789
962
  ], ts.NodeFlags.Const), ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('Object'), ts.factory.createIdentifier('entries')), undefined, [ts.factory.createIdentifier('serverVariables')]), ts.factory.createBlock([
790
963
  ts.factory.createExpressionStatement(ts.factory.createBinaryExpression(url, ts.factory.createToken(ts.SyntaxKind.EqualsToken), ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(url, ts.factory.createIdentifier('replace')), undefined, [
791
964
  ts.factory.createNewExpression(ts.factory.createIdentifier('RegExp'), undefined, [
792
965
  ts.factory.createBinaryExpression(ts.factory.createBinaryExpression(ts.factory.createStringLiteral('\\{'), ts.factory.createToken(ts.SyntaxKind.PlusToken), key), ts.factory.createToken(ts.SyntaxKind.PlusToken), ts.factory.createStringLiteral('\\}')),
793
- ts.factory.createStringLiteral('g'),
966
+ ts.factory.createStringLiteral('g')
794
967
  ]),
795
- value,
796
- ]))),
797
- ], true)),
968
+ value
969
+ ])))
970
+ ], true))
798
971
  ], true)),
799
972
  // return url
800
- ts.factory.createReturnStatement(url),
973
+ ts.factory.createReturnStatement(url)
801
974
  ], true)),
802
975
  // return default (first server with defaults)
803
- ts.factory.createReturnStatement(ts.factory.createStringLiteral(servers[0] ? this.resolveServerUrl(servers[0], {}) : '/', true)),
976
+ ts.factory.createReturnStatement(ts.factory.createStringLiteral(servers[0] ? this.resolveServerUrl(servers[0], {}) : '/', true))
804
977
  ];
805
978
  return ts.factory.createFunctionDeclaration(undefined, undefined, ts.factory.createIdentifier('resolveServerUrl'), undefined, [
806
- ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createIdentifier('serverIndex'), ts.factory.createToken(ts.SyntaxKind.QuestionToken), ts.factory.createUnionTypeNode([
807
- ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword),
808
- ts.factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword),
809
- ]), undefined),
979
+ ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createIdentifier('serverIndex'), ts.factory.createToken(ts.SyntaxKind.QuestionToken), ts.factory.createUnionTypeNode([ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword), ts.factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword)]), undefined),
810
980
  ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createIdentifier('serverVariables'), ts.factory.createToken(ts.SyntaxKind.QuestionToken), ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Record'), [
811
981
  ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
812
- ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
813
- ]), ts.factory.createObjectLiteralExpression([], false)),
982
+ ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword)
983
+ ]), ts.factory.createObjectLiteralExpression([], false))
814
984
  ], ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword), ts.factory.createBlock(bodyStatements, true));
815
985
  }
816
986
  generateClientName(title) {
@@ -914,9 +1084,7 @@ export class TypeScriptCodeGeneratorService {
914
1084
  const prop = safeProperty.data;
915
1085
  if (this.isReference(prop)) {
916
1086
  const refSchema = this.buildFromReference(prop);
917
- return required
918
- ? refSchema
919
- : ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(refSchema, ts.factory.createIdentifier('optional')), undefined, []);
1087
+ return required ? refSchema : ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(refSchema, ts.factory.createIdentifier('optional')), undefined, []);
920
1088
  }
921
1089
  if (prop['anyOf'] && Array.isArray(prop['anyOf']) && prop['anyOf'].length > 0) {
922
1090
  return this.handleLogicalOperator('anyOf', prop['anyOf'], required);
@@ -964,7 +1132,9 @@ export class TypeScriptCodeGeneratorService {
964
1132
  else {
965
1133
  literalValue = ts.factory.createStringLiteral(String(val), true);
966
1134
  }
967
- return ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('literal')), undefined, [literalValue]);
1135
+ return ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('literal')), undefined, [
1136
+ literalValue
1137
+ ]);
968
1138
  });
969
1139
  const unionExpression = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('union')), undefined, [ts.factory.createArrayLiteralExpression(literalSchemas, false)]);
970
1140
  return required
@@ -978,15 +1148,19 @@ export class TypeScriptCodeGeneratorService {
978
1148
  let arraySchema = this.buildZodAST([
979
1149
  {
980
1150
  type: 'array',
981
- args: [itemsSchema],
982
- },
1151
+ args: [itemsSchema]
1152
+ }
983
1153
  ]);
984
1154
  // Apply array constraints
985
1155
  if (typeof prop['minItems'] === 'number') {
986
- arraySchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(arraySchema, ts.factory.createIdentifier('min')), undefined, [ts.factory.createNumericLiteral(String(prop['minItems']))]);
1156
+ arraySchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(arraySchema, ts.factory.createIdentifier('min')), undefined, [
1157
+ ts.factory.createNumericLiteral(String(prop['minItems']))
1158
+ ]);
987
1159
  }
988
1160
  if (typeof prop['maxItems'] === 'number') {
989
- arraySchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(arraySchema, ts.factory.createIdentifier('max')), undefined, [ts.factory.createNumericLiteral(String(prop['maxItems']))]);
1161
+ arraySchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(arraySchema, ts.factory.createIdentifier('max')), undefined, [
1162
+ ts.factory.createNumericLiteral(String(prop['maxItems']))
1163
+ ]);
990
1164
  }
991
1165
  return required
992
1166
  ? arraySchema
@@ -1004,9 +1178,9 @@ export class TypeScriptCodeGeneratorService {
1004
1178
  args: [
1005
1179
  ts.factory.createObjectLiteralExpression(propertiesEntries.map(([name, propValue]) => {
1006
1180
  return ts.factory.createPropertyAssignment(ts.factory.createIdentifier(name), this.buildProperty(propValue, propRequired.includes(name)));
1007
- }), true),
1008
- ],
1009
- },
1181
+ }), true)
1182
+ ]
1183
+ }
1010
1184
  ]);
1011
1185
  // Apply object constraints
1012
1186
  let constrainedSchema = objectSchema;
@@ -1014,16 +1188,16 @@ export class TypeScriptCodeGeneratorService {
1014
1188
  constrainedSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(constrainedSchema, ts.factory.createIdentifier('refine')), undefined, [
1015
1189
  ts.factory.createArrowFunction(undefined, undefined, [ts.factory.createParameterDeclaration(undefined, undefined, 'obj', undefined, undefined, undefined)], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('Object'), ts.factory.createIdentifier('keys')), undefined, [ts.factory.createIdentifier('obj')]), ts.factory.createIdentifier('length')), ts.factory.createToken(ts.SyntaxKind.GreaterThanEqualsToken), ts.factory.createNumericLiteral(String(prop['minProperties'])))),
1016
1190
  ts.factory.createObjectLiteralExpression([
1017
- ts.factory.createPropertyAssignment(ts.factory.createIdentifier('message'), ts.factory.createStringLiteral(`Object must have at least ${String(prop['minProperties'])} properties`)),
1018
- ]),
1191
+ ts.factory.createPropertyAssignment(ts.factory.createIdentifier('message'), ts.factory.createStringLiteral(`Object must have at least ${String(prop['minProperties'])} properties`))
1192
+ ])
1019
1193
  ]);
1020
1194
  }
1021
1195
  if (typeof prop['maxProperties'] === 'number') {
1022
1196
  constrainedSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(constrainedSchema, ts.factory.createIdentifier('refine')), undefined, [
1023
1197
  ts.factory.createArrowFunction(undefined, undefined, [ts.factory.createParameterDeclaration(undefined, undefined, 'obj', undefined, undefined, undefined)], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('Object'), ts.factory.createIdentifier('keys')), undefined, [ts.factory.createIdentifier('obj')]), ts.factory.createIdentifier('length')), ts.factory.createToken(ts.SyntaxKind.LessThanEqualsToken), ts.factory.createNumericLiteral(String(prop['maxProperties'])))),
1024
1198
  ts.factory.createObjectLiteralExpression([
1025
- ts.factory.createPropertyAssignment(ts.factory.createIdentifier('message'), ts.factory.createStringLiteral(`Object must have at most ${String(prop['maxProperties'])} properties`)),
1026
- ]),
1199
+ ts.factory.createPropertyAssignment(ts.factory.createIdentifier('message'), ts.factory.createStringLiteral(`Object must have at most ${String(prop['maxProperties'])} properties`))
1200
+ ])
1027
1201
  ]);
1028
1202
  }
1029
1203
  return required
@@ -1033,31 +1207,30 @@ export class TypeScriptCodeGeneratorService {
1033
1207
  return this.buildZodAST([
1034
1208
  {
1035
1209
  type: 'record',
1036
- args: [this.buildZodAST(['string']), this.buildZodAST(['unknown'])],
1037
- },
1210
+ args: [this.buildZodAST(['string']), this.buildZodAST(['unknown'])]
1211
+ }
1038
1212
  ]);
1039
1213
  }
1040
1214
  case 'integer': {
1041
1215
  let numberSchema = this.buildZodAST(['number', 'int']);
1042
1216
  // Apply number constraints
1043
1217
  if (prop['minimum'] !== undefined && typeof prop['minimum'] === 'number') {
1044
- const minValue = prop['exclusiveMinimum'] && typeof prop['exclusiveMinimum'] === 'boolean'
1045
- ? prop['minimum'] + 1
1046
- : prop['minimum'];
1218
+ const minValue = prop['exclusiveMinimum'] && typeof prop['exclusiveMinimum'] === 'boolean' ? prop['minimum'] + 1 : prop['minimum'];
1047
1219
  numberSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(numberSchema, ts.factory.createIdentifier(prop['exclusiveMinimum'] && typeof prop['exclusiveMinimum'] === 'boolean' ? 'gt' : 'gte')), undefined, [ts.factory.createNumericLiteral(String(minValue))]);
1048
1220
  }
1049
1221
  if (prop['maximum'] !== undefined && typeof prop['maximum'] === 'number') {
1050
- const maxValue = prop['exclusiveMaximum'] && typeof prop['exclusiveMaximum'] === 'boolean'
1051
- ? prop['maximum'] - 1
1052
- : prop['maximum'];
1222
+ const maxValue = prop['exclusiveMaximum'] && typeof prop['exclusiveMaximum'] === 'boolean' ? prop['maximum'] - 1 : prop['maximum'];
1053
1223
  numberSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(numberSchema, ts.factory.createIdentifier(prop['exclusiveMaximum'] ? 'lt' : 'lte')), undefined, [ts.factory.createNumericLiteral(String(maxValue))]);
1054
1224
  }
1055
1225
  if (typeof prop['multipleOf'] === 'number') {
1056
1226
  const refineFunction = ts.factory.createArrowFunction(undefined, undefined, [ts.factory.createParameterDeclaration(undefined, undefined, 'val', undefined, undefined, undefined)], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createBinaryExpression(ts.factory.createBinaryExpression(ts.factory.createIdentifier('val'), ts.factory.createToken(ts.SyntaxKind.PercentToken), ts.factory.createNumericLiteral(String(prop['multipleOf']))), ts.factory.createToken(ts.SyntaxKind.EqualsEqualsEqualsToken), ts.factory.createNumericLiteral('0')));
1057
1227
  const refineOptions = ts.factory.createObjectLiteralExpression([
1058
- ts.factory.createPropertyAssignment(ts.factory.createIdentifier('message'), ts.factory.createStringLiteral(`Number must be a multiple of ${String(prop['multipleOf'])}`)),
1228
+ ts.factory.createPropertyAssignment(ts.factory.createIdentifier('message'), ts.factory.createStringLiteral(`Number must be a multiple of ${String(prop['multipleOf'])}`))
1229
+ ]);
1230
+ numberSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(numberSchema, ts.factory.createIdentifier('refine')), undefined, [
1231
+ refineFunction,
1232
+ refineOptions
1059
1233
  ]);
1060
- numberSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(numberSchema, ts.factory.createIdentifier('refine')), undefined, [refineFunction, refineOptions]);
1061
1234
  }
1062
1235
  return required
1063
1236
  ? numberSchema
@@ -1067,23 +1240,22 @@ export class TypeScriptCodeGeneratorService {
1067
1240
  let numberSchema = this.buildZodAST(['number']);
1068
1241
  // Apply number constraints
1069
1242
  if (prop['minimum'] !== undefined && typeof prop['minimum'] === 'number') {
1070
- const minValue = prop['exclusiveMinimum'] && typeof prop['exclusiveMinimum'] === 'boolean'
1071
- ? prop['minimum'] + 1
1072
- : prop['minimum'];
1243
+ const minValue = prop['exclusiveMinimum'] && typeof prop['exclusiveMinimum'] === 'boolean' ? prop['minimum'] + 1 : prop['minimum'];
1073
1244
  numberSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(numberSchema, ts.factory.createIdentifier(prop['exclusiveMinimum'] && typeof prop['exclusiveMinimum'] === 'boolean' ? 'gt' : 'gte')), undefined, [ts.factory.createNumericLiteral(String(minValue))]);
1074
1245
  }
1075
1246
  if (prop['maximum'] !== undefined && typeof prop['maximum'] === 'number') {
1076
- const maxValue = prop['exclusiveMaximum'] && typeof prop['exclusiveMaximum'] === 'boolean'
1077
- ? prop['maximum'] - 1
1078
- : prop['maximum'];
1247
+ const maxValue = prop['exclusiveMaximum'] && typeof prop['exclusiveMaximum'] === 'boolean' ? prop['maximum'] - 1 : prop['maximum'];
1079
1248
  numberSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(numberSchema, ts.factory.createIdentifier(prop['exclusiveMaximum'] ? 'lt' : 'lte')), undefined, [ts.factory.createNumericLiteral(String(maxValue))]);
1080
1249
  }
1081
1250
  if (typeof prop['multipleOf'] === 'number') {
1082
1251
  const refineFunction = ts.factory.createArrowFunction(undefined, undefined, [ts.factory.createParameterDeclaration(undefined, undefined, 'val', undefined, undefined, undefined)], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createBinaryExpression(ts.factory.createBinaryExpression(ts.factory.createIdentifier('val'), ts.factory.createToken(ts.SyntaxKind.PercentToken), ts.factory.createNumericLiteral(String(prop['multipleOf']))), ts.factory.createToken(ts.SyntaxKind.EqualsEqualsEqualsToken), ts.factory.createNumericLiteral('0')));
1083
1252
  const refineOptions = ts.factory.createObjectLiteralExpression([
1084
- ts.factory.createPropertyAssignment(ts.factory.createIdentifier('message'), ts.factory.createStringLiteral(`Number must be a multiple of ${String(prop['multipleOf'])}`)),
1253
+ ts.factory.createPropertyAssignment(ts.factory.createIdentifier('message'), ts.factory.createStringLiteral(`Number must be a multiple of ${String(prop['multipleOf'])}`))
1254
+ ]);
1255
+ numberSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(numberSchema, ts.factory.createIdentifier('refine')), undefined, [
1256
+ refineFunction,
1257
+ refineOptions
1085
1258
  ]);
1086
- numberSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(numberSchema, ts.factory.createIdentifier('refine')), undefined, [refineFunction, refineOptions]);
1087
1259
  }
1088
1260
  return required
1089
1261
  ? numberSchema
@@ -1118,22 +1290,26 @@ export class TypeScriptCodeGeneratorService {
1118
1290
  }
1119
1291
  // Apply string constraints
1120
1292
  if (typeof prop['minLength'] === 'number') {
1121
- stringSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(stringSchema, ts.factory.createIdentifier('min')), undefined, [ts.factory.createNumericLiteral(String(prop['minLength']))]);
1293
+ stringSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(stringSchema, ts.factory.createIdentifier('min')), undefined, [
1294
+ ts.factory.createNumericLiteral(String(prop['minLength']))
1295
+ ]);
1122
1296
  }
1123
1297
  if (typeof prop['maxLength'] === 'number') {
1124
- stringSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(stringSchema, ts.factory.createIdentifier('max')), undefined, [ts.factory.createNumericLiteral(String(prop['maxLength']))]);
1298
+ stringSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(stringSchema, ts.factory.createIdentifier('max')), undefined, [
1299
+ ts.factory.createNumericLiteral(String(prop['maxLength']))
1300
+ ]);
1125
1301
  }
1126
1302
  if (prop['pattern'] && typeof prop['pattern'] === 'string') {
1127
1303
  stringSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(stringSchema, ts.factory.createIdentifier('regex')), undefined, [
1128
- ts.factory.createNewExpression(ts.factory.createIdentifier('RegExp'), undefined, [
1129
- ts.factory.createStringLiteral(prop['pattern'], true),
1130
- ]),
1304
+ ts.factory.createNewExpression(ts.factory.createIdentifier('RegExp'), undefined, [ts.factory.createStringLiteral(prop['pattern'], true)])
1131
1305
  ]);
1132
1306
  }
1133
1307
  // Apply default value if not required
1134
1308
  if (!required && prop['default'] !== undefined) {
1135
1309
  const defaultValue = this.buildDefaultValue(prop['default']);
1136
- stringSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(stringSchema, ts.factory.createIdentifier('default')), undefined, [defaultValue]);
1310
+ stringSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(stringSchema, ts.factory.createIdentifier('default')), undefined, [
1311
+ defaultValue
1312
+ ]);
1137
1313
  }
1138
1314
  return required
1139
1315
  ? stringSchema
@@ -1143,12 +1319,10 @@ export class TypeScriptCodeGeneratorService {
1143
1319
  let booleanSchema = this.buildZodAST(['boolean']);
1144
1320
  // Apply default value if not required
1145
1321
  if (!required && prop['default'] !== undefined) {
1146
- const defaultValue = typeof prop['default'] === 'boolean'
1147
- ? prop['default']
1148
- ? ts.factory.createTrue()
1149
- : ts.factory.createFalse()
1150
- : ts.factory.createFalse();
1151
- booleanSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(booleanSchema, ts.factory.createIdentifier('default')), undefined, [defaultValue]);
1322
+ const defaultValue = typeof prop['default'] === 'boolean' ? (prop['default'] ? ts.factory.createTrue() : ts.factory.createFalse()) : ts.factory.createFalse();
1323
+ booleanSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(booleanSchema, ts.factory.createIdentifier('default')), undefined, [
1324
+ defaultValue
1325
+ ]);
1152
1326
  }
1153
1327
  return required
1154
1328
  ? booleanSchema
@@ -1200,7 +1374,9 @@ export class TypeScriptCodeGeneratorService {
1200
1374
  case 'anyOf':
1201
1375
  case 'oneOf': {
1202
1376
  const unionSchemas = schemas.map((schema) => this.buildSchemaFromLogicalOperator(schema));
1203
- return ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('union')), undefined, [ts.factory.createArrayLiteralExpression(unionSchemas, false)]);
1377
+ return ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('union')), undefined, [
1378
+ ts.factory.createArrayLiteralExpression(unionSchemas, false)
1379
+ ]);
1204
1380
  }
1205
1381
  case 'allOf': {
1206
1382
  if (schemas.length === 0) {
@@ -1215,10 +1391,12 @@ export class TypeScriptCodeGeneratorService {
1215
1391
  case 'not': {
1216
1392
  const notSchema = this.buildSchemaFromLogicalOperator(schemas[0]);
1217
1393
  return ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('any')), ts.factory.createIdentifier('refine')), undefined, [
1218
- ts.factory.createArrowFunction(undefined, undefined, [ts.factory.createParameterDeclaration(undefined, undefined, 'val', undefined, undefined, undefined)], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createPrefixUnaryExpression(ts.SyntaxKind.ExclamationToken, ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(notSchema, ts.factory.createIdentifier('safeParse')), undefined, [ts.factory.createIdentifier('val')]))),
1394
+ ts.factory.createArrowFunction(undefined, undefined, [ts.factory.createParameterDeclaration(undefined, undefined, 'val', undefined, undefined, undefined)], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createPrefixUnaryExpression(ts.SyntaxKind.ExclamationToken, ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(notSchema, ts.factory.createIdentifier('safeParse')), undefined, [
1395
+ ts.factory.createIdentifier('val')
1396
+ ]))),
1219
1397
  ts.factory.createObjectLiteralExpression([
1220
- ts.factory.createPropertyAssignment(ts.factory.createIdentifier('message'), ts.factory.createStringLiteral('Value must not match the excluded schema')),
1221
- ]),
1398
+ ts.factory.createPropertyAssignment(ts.factory.createIdentifier('message'), ts.factory.createStringLiteral('Value must not match the excluded schema'))
1399
+ ])
1222
1400
  ]);
1223
1401
  }
1224
1402
  default:
@@ -1267,16 +1445,16 @@ export class TypeScriptCodeGeneratorService {
1267
1445
  args: [
1268
1446
  ts.factory.createObjectLiteralExpression(properties.map(([name, property]) => {
1269
1447
  return ts.factory.createPropertyAssignment(ts.factory.createIdentifier(name), this.buildSchemaFromLogicalOperator(property));
1270
- }), true),
1271
- ],
1272
- },
1448
+ }), true)
1449
+ ]
1450
+ }
1273
1451
  ]);
1274
1452
  }
1275
1453
  return this.buildZodAST([
1276
1454
  {
1277
1455
  type: 'record',
1278
- args: [this.buildZodAST(['string']), this.buildZodAST(['unknown'])],
1279
- },
1456
+ args: [this.buildZodAST(['string']), this.buildZodAST(['unknown'])]
1457
+ }
1280
1458
  ]);
1281
1459
  }
1282
1460
  buildArrayTypeFromSchema(schemaObj) {
@@ -1284,8 +1462,8 @@ export class TypeScriptCodeGeneratorService {
1284
1462
  return this.buildZodAST([
1285
1463
  {
1286
1464
  type: 'array',
1287
- args: [this.buildSchemaFromLogicalOperator(schemaObj.items)],
1288
- },
1465
+ args: [this.buildSchemaFromLogicalOperator(schemaObj.items)]
1466
+ }
1289
1467
  ]);
1290
1468
  }
1291
1469
  return this.buildZodAST(['array']);
@@ -1305,7 +1483,7 @@ export class TypeScriptCodeGeneratorService {
1305
1483
  if (this.isCircularReference(refName)) {
1306
1484
  // Generate: z.lazy(() => RefSchema)
1307
1485
  return ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('lazy')), undefined, [
1308
- ts.factory.createArrowFunction(undefined, undefined, [], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createIdentifier(sanitizedRefName)),
1486
+ ts.factory.createArrowFunction(undefined, undefined, [], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createIdentifier(sanitizedRefName))
1309
1487
  ]);
1310
1488
  }
1311
1489
  return ts.factory.createIdentifier(sanitizedRefName);
@@ -1323,9 +1501,7 @@ export class TypeScriptCodeGeneratorService {
1323
1501
  }
1324
1502
  // Case 2: Reference to a schema that's part of a circular dependency chain
1325
1503
  // and we're currently building a schema that's also in that chain
1326
- if (this.circularSchemas.has(refName) &&
1327
- this.currentSchemaName !== null &&
1328
- this.circularSchemas.has(this.currentSchemaName)) {
1504
+ if (this.circularSchemas.has(refName) && this.currentSchemaName !== null && this.circularSchemas.has(this.currentSchemaName)) {
1329
1505
  return true;
1330
1506
  }
1331
1507
  return false;
@@ -1340,11 +1516,7 @@ export class TypeScriptCodeGeneratorService {
1340
1516
  // Build dependency graph
1341
1517
  const graph = new Map();
1342
1518
  for (const [name, schema] of Object.entries(schemas)) {
1343
- const dependencies = jp
1344
- .query(schema, '$..["$ref"]')
1345
- .filter((ref) => ref.startsWith('#/components/schemas/'))
1346
- .map((ref) => ref.replace('#/components/schemas/', ''))
1347
- .filter((dep) => dep in schemas);
1519
+ const dependencies = this.extractSchemaReferences(schema).filter((dep) => dep in schemas);
1348
1520
  graph.set(name, dependencies);
1349
1521
  }
1350
1522
  // Tarjan's algorithm for finding SCCs
@@ -1422,10 +1594,7 @@ export class TypeScriptCodeGeneratorService {
1422
1594
  }
1423
1595
  visiting.add(name);
1424
1596
  const schema = schemas[name];
1425
- const dependencies = jp
1426
- .query(schema, '$..["$ref"]')
1427
- .filter((ref) => ref.startsWith('#/components/schemas/'))
1428
- .map((ref) => ref.replace('#/components/schemas/', ''));
1597
+ const dependencies = this.extractSchemaReferences(schema);
1429
1598
  for (const dep of dependencies) {
1430
1599
  if (schemas[dep]) {
1431
1600
  visit(dep);