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.
- package/.github/workflows/ci.yml +50 -48
- package/.github/workflows/release.yml +13 -3
- package/.husky/commit-msg +1 -1
- package/.husky/pre-commit +1 -1
- package/.lintstagedrc.json +5 -1
- package/.nvmrc +1 -1
- package/.prettierrc.json +12 -5
- package/CHANGELOG.md +15 -0
- package/CONTRIBUTING.md +12 -12
- package/EXAMPLES.md +135 -57
- package/PERFORMANCE.md +4 -4
- package/README.md +87 -64
- package/SECURITY.md +1 -1
- package/dist/src/cli.js +11 -18
- package/dist/src/generator.d.ts +2 -2
- package/dist/src/generator.d.ts.map +1 -1
- package/dist/src/generator.js +5 -3
- package/dist/src/interfaces/code-generator.d.ts.map +1 -1
- package/dist/src/services/code-generator.service.d.ts +24 -1
- package/dist/src/services/code-generator.service.d.ts.map +1 -1
- package/dist/src/services/code-generator.service.js +385 -216
- package/dist/src/services/file-reader.service.d.ts.map +1 -1
- package/dist/src/services/file-reader.service.js +1 -1
- package/dist/src/services/file-writer.service.d.ts.map +1 -1
- package/dist/src/services/file-writer.service.js +2 -2
- package/dist/src/services/import-builder.service.d.ts.map +1 -1
- package/dist/src/services/import-builder.service.js +3 -3
- package/dist/src/services/type-builder.service.d.ts.map +1 -1
- package/dist/src/types/generator-options.d.ts.map +1 -1
- package/dist/src/types/openapi.d.ts.map +1 -1
- package/dist/src/types/openapi.js +20 -20
- package/dist/src/utils/error-handler.d.ts.map +1 -1
- package/dist/src/utils/naming-convention.d.ts.map +1 -1
- package/dist/src/utils/naming-convention.js +6 -3
- package/dist/src/utils/signal-handler.d.ts.map +1 -1
- package/dist/tests/integration/cli-comprehensive.test.d.ts +2 -0
- package/dist/tests/integration/cli-comprehensive.test.d.ts.map +1 -0
- package/dist/tests/integration/cli-comprehensive.test.js +110 -0
- package/dist/tests/integration/cli.test.d.ts +2 -0
- package/dist/tests/integration/cli.test.d.ts.map +1 -0
- package/dist/tests/integration/cli.test.js +25 -0
- package/dist/tests/integration/error-scenarios.test.d.ts +2 -0
- package/dist/tests/integration/error-scenarios.test.d.ts.map +1 -0
- package/dist/tests/integration/error-scenarios.test.js +169 -0
- package/dist/tests/integration/snapshots.test.d.ts +2 -0
- package/dist/tests/integration/snapshots.test.d.ts.map +1 -0
- package/dist/tests/integration/snapshots.test.js +100 -0
- package/dist/tests/unit/code-generator-edge-cases.test.d.ts +2 -0
- package/dist/tests/unit/code-generator-edge-cases.test.d.ts.map +1 -0
- package/dist/tests/unit/code-generator-edge-cases.test.js +506 -0
- package/dist/tests/unit/code-generator.test.d.ts +2 -0
- package/dist/tests/unit/code-generator.test.d.ts.map +1 -0
- package/dist/tests/unit/code-generator.test.js +1364 -0
- package/dist/tests/unit/file-reader.test.d.ts +2 -0
- package/dist/tests/unit/file-reader.test.d.ts.map +1 -0
- package/dist/tests/unit/file-reader.test.js +125 -0
- package/dist/tests/unit/generator.test.d.ts +2 -0
- package/dist/tests/unit/generator.test.d.ts.map +1 -0
- package/dist/tests/unit/generator.test.js +119 -0
- package/dist/tests/unit/naming-convention.test.d.ts +2 -0
- package/dist/tests/unit/naming-convention.test.d.ts.map +1 -0
- package/dist/tests/unit/naming-convention.test.js +256 -0
- package/dist/tests/unit/reporter.test.d.ts +2 -0
- package/dist/tests/unit/reporter.test.d.ts.map +1 -0
- package/dist/tests/unit/reporter.test.js +44 -0
- package/dist/tests/unit/type-builder.test.d.ts +2 -0
- package/dist/tests/unit/type-builder.test.d.ts.map +1 -0
- package/dist/tests/unit/type-builder.test.js +108 -0
- package/dist/vitest.config.d.ts.map +1 -1
- package/dist/vitest.config.js +10 -20
- package/eslint.config.mjs +38 -28
- package/examples/.gitkeep +1 -1
- package/examples/README.md +4 -2
- package/examples/petstore/README.md +18 -17
- package/examples/petstore/{type.ts → api.ts} +158 -74
- package/examples/petstore/authenticated-usage.ts +6 -4
- package/examples/petstore/basic-usage.ts +4 -3
- package/examples/petstore/error-handling-usage.ts +84 -0
- package/examples/petstore/retry-handler-usage.ts +11 -18
- package/examples/petstore/server-variables-usage.ts +10 -10
- package/examples/pokeapi/README.md +8 -8
- package/examples/pokeapi/api.ts +218 -0
- package/examples/pokeapi/basic-usage.ts +3 -2
- package/examples/pokeapi/custom-client.ts +5 -4
- package/package.json +17 -21
- package/src/cli.ts +20 -25
- package/src/generator.ts +13 -11
- package/src/interfaces/code-generator.ts +1 -1
- package/src/services/code-generator.service.ts +989 -1099
- package/src/services/file-reader.service.ts +6 -5
- package/src/services/file-writer.service.ts +7 -7
- package/src/services/import-builder.service.ts +9 -13
- package/src/services/type-builder.service.ts +8 -19
- package/src/types/generator-options.ts +1 -1
- package/src/types/openapi.ts +22 -22
- package/src/utils/error-handler.ts +2 -2
- package/src/utils/naming-convention.ts +13 -10
- package/src/utils/reporter.ts +2 -2
- package/src/utils/signal-handler.ts +7 -8
- package/tests/integration/cli-comprehensive.test.ts +38 -32
- package/tests/integration/cli.test.ts +5 -5
- package/tests/integration/error-scenarios.test.ts +20 -26
- package/tests/integration/snapshots.test.ts +19 -23
- package/tests/unit/code-generator-edge-cases.test.ts +133 -133
- package/tests/unit/code-generator.test.ts +674 -268
- package/tests/unit/file-reader.test.ts +14 -14
- package/tests/unit/generator.test.ts +30 -18
- package/tests/unit/naming-convention.test.ts +27 -27
- package/tests/unit/type-builder.test.ts +2 -2
- package/tsconfig.json +5 -3
- package/vitest.config.ts +11 -21
- package/dist/scripts/update-manifest.d.ts +0 -14
- package/dist/scripts/update-manifest.d.ts.map +0 -1
- package/dist/scripts/update-manifest.js +0 -33
- package/dist/src/assets/manifest.json +0 -5
- package/examples/pokeapi/type.ts +0 -109
- package/generated/type.ts +0 -326
- package/scripts/update-manifest.ts +0 -49
- package/src/assets/manifest.json +0 -5
|
@@ -1,23 +1,17 @@
|
|
|
1
|
-
import jp from 'jsonpath';
|
|
2
1
|
import * as ts from 'typescript';
|
|
3
|
-
import {z} from 'zod';
|
|
4
|
-
import type {CodeGenerator, SchemaBuilder} from '../interfaces/code-generator';
|
|
5
|
-
import type {
|
|
6
|
-
import type {
|
|
7
|
-
import {MethodSchema, Reference, SchemaProperties} from '../types/openapi';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
type NamingConvention,
|
|
12
|
-
type OperationDetails,
|
|
13
|
-
type OperationNameTransformer,
|
|
14
|
-
transformNamingConvention,
|
|
15
|
-
} from '../utils/naming-convention';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import type { CodeGenerator, SchemaBuilder } from '../interfaces/code-generator';
|
|
4
|
+
import type { GeneratorOptions } from '../types/generator-options';
|
|
5
|
+
import type { MethodSchemaType, OpenApiSpecType, ReferenceType } from '../types/openapi';
|
|
6
|
+
import { MethodSchema, Reference, SchemaProperties } from '../types/openapi';
|
|
7
|
+
import { type NamingConvention, type OperationDetails, type OperationNameTransformer, transformNamingConvention } from '../utils/naming-convention';
|
|
8
|
+
import { TypeScriptImportBuilderService } from './import-builder.service';
|
|
9
|
+
import { TypeScriptTypeBuilderService } from './type-builder.service';
|
|
16
10
|
|
|
17
11
|
export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuilder {
|
|
18
12
|
private readonly typeBuilder = new TypeScriptTypeBuilderService();
|
|
19
13
|
private readonly importBuilder = new TypeScriptImportBuilderService();
|
|
20
|
-
private readonly printer = ts.createPrinter({newLine: ts.NewLineKind.LineFeed});
|
|
14
|
+
private readonly printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
|
|
21
15
|
private readonly namingConvention: NamingConvention | undefined;
|
|
22
16
|
private readonly operationNameTransformer: OperationNameTransformer | undefined;
|
|
23
17
|
|
|
@@ -32,11 +26,40 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
32
26
|
|
|
33
27
|
private readonly ZodAST = z.object({
|
|
34
28
|
type: z.enum(['string', 'number', 'boolean', 'object', 'array', 'unknown', 'record']),
|
|
35
|
-
args: z.array(z.unknown()).optional()
|
|
29
|
+
args: z.array(z.unknown()).optional()
|
|
36
30
|
});
|
|
37
31
|
|
|
32
|
+
private extractSchemaReferences(schema: unknown): string[] {
|
|
33
|
+
const references = new Set<string>();
|
|
34
|
+
|
|
35
|
+
const walk = (node: unknown): void => {
|
|
36
|
+
if (Array.isArray(node)) {
|
|
37
|
+
for (const item of node) {
|
|
38
|
+
walk(item);
|
|
39
|
+
}
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (node === null || typeof node !== 'object') {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
for (const [key, value] of Object.entries(node as Record<string, unknown>)) {
|
|
48
|
+
if (key === '$ref' && typeof value === 'string' && value.startsWith('#/components/schemas/')) {
|
|
49
|
+
references.add(value.replace('#/components/schemas/', ''));
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
walk(value);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
walk(schema);
|
|
58
|
+
return [...references];
|
|
59
|
+
}
|
|
60
|
+
|
|
38
61
|
generate(spec: OpenApiSpecType): string {
|
|
39
|
-
const file = ts.createSourceFile('
|
|
62
|
+
const file = ts.createSourceFile('api.ts', '', ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
|
|
40
63
|
const nodes = this.buildAST(spec);
|
|
41
64
|
return this.printer.printList(ts.ListFormat.MultiLine, ts.factory.createNodeArray(nodes), file);
|
|
42
65
|
}
|
|
@@ -75,15 +98,20 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
75
98
|
const serverConfig = this.buildServerConfiguration(openapi);
|
|
76
99
|
const clientClass = this.buildClientClass(openapi, schemas);
|
|
77
100
|
|
|
101
|
+
const explicitTypeDeclarations = this.buildExplicitTypeDeclarations(openapi);
|
|
102
|
+
|
|
78
103
|
return [
|
|
79
104
|
this.createComment('Imports'),
|
|
80
105
|
...imports,
|
|
106
|
+
this.createComment('Explicit type declarations'),
|
|
107
|
+
...explicitTypeDeclarations,
|
|
81
108
|
this.createComment('Components schemas'),
|
|
82
109
|
...Object.values(schemas),
|
|
83
110
|
...schemaTypeAliases,
|
|
84
111
|
...serverConfig,
|
|
112
|
+
this.buildResponseValidationErrorClass(),
|
|
85
113
|
this.createComment('Client class'),
|
|
86
|
-
clientClass
|
|
114
|
+
clientClass
|
|
87
115
|
];
|
|
88
116
|
}
|
|
89
117
|
|
|
@@ -98,7 +126,9 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
98
126
|
|
|
99
127
|
return sortedSchemaNames.reduce<Record<string, ts.VariableStatement>>((schemaRegistered, name) => {
|
|
100
128
|
const schema = openapi.components?.schemas?.[name];
|
|
101
|
-
if (!schema)
|
|
129
|
+
if (!schema) {
|
|
130
|
+
return schemaRegistered;
|
|
131
|
+
}
|
|
102
132
|
|
|
103
133
|
// Set context for current schema being built
|
|
104
134
|
this.currentSchemaName = name;
|
|
@@ -108,47 +138,321 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
108
138
|
// Clear context
|
|
109
139
|
this.currentSchemaName = null;
|
|
110
140
|
|
|
141
|
+
const sanitizedName = this.typeBuilder.sanitizeIdentifier(name);
|
|
142
|
+
|
|
143
|
+
// Add type annotation: z.ZodType<Name>
|
|
144
|
+
const typeAnnotation = ts.factory.createTypeReferenceNode(ts.factory.createQualifiedName(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('ZodType')), [
|
|
145
|
+
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(sanitizedName), undefined)
|
|
146
|
+
]);
|
|
147
|
+
|
|
111
148
|
const variableStatement = ts.factory.createVariableStatement(
|
|
112
149
|
[ts.factory.createToken(ts.SyntaxKind.ExportKeyword)],
|
|
113
150
|
ts.factory.createVariableDeclarationList(
|
|
114
|
-
[
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
undefined,
|
|
118
|
-
undefined,
|
|
119
|
-
schemaExpression,
|
|
120
|
-
),
|
|
121
|
-
],
|
|
122
|
-
ts.NodeFlags.Const,
|
|
123
|
-
),
|
|
151
|
+
[ts.factory.createVariableDeclaration(ts.factory.createIdentifier(sanitizedName), undefined, typeAnnotation, schemaExpression)],
|
|
152
|
+
ts.NodeFlags.Const
|
|
153
|
+
)
|
|
124
154
|
);
|
|
125
155
|
|
|
126
156
|
return {
|
|
127
157
|
...schemaRegistered,
|
|
128
|
-
[name]: variableStatement
|
|
158
|
+
[name]: variableStatement
|
|
129
159
|
};
|
|
130
160
|
}, {});
|
|
131
161
|
}
|
|
132
162
|
|
|
133
|
-
private buildSchemaTypeAliases(
|
|
134
|
-
|
|
163
|
+
private buildSchemaTypeAliases(_schemas: Record<string, ts.VariableStatement>): ts.TypeAliasDeclaration[] {
|
|
164
|
+
// Explicit type declarations are used instead of z.infer type exports
|
|
165
|
+
return [];
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Builds explicit TypeScript type declarations for all schemas.
|
|
170
|
+
* Returns interface declarations for object types and type aliases for other types.
|
|
171
|
+
*/
|
|
172
|
+
private buildExplicitTypeDeclarations(openapi: OpenApiSpecType): ts.Statement[] {
|
|
173
|
+
const schemasEntries = Object.entries(openapi.components?.schemas ?? {});
|
|
174
|
+
const schemasMap = Object.fromEntries(schemasEntries);
|
|
175
|
+
const sortedSchemaNames = this.topologicalSort(schemasMap);
|
|
176
|
+
|
|
177
|
+
const statements: ts.Statement[] = [];
|
|
178
|
+
|
|
179
|
+
for (const name of sortedSchemaNames) {
|
|
180
|
+
const schema = openapi.components?.schemas?.[name];
|
|
181
|
+
if (!schema) {
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
|
|
135
185
|
const sanitizedName = this.typeBuilder.sanitizeIdentifier(name);
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
186
|
+
const safeSchema = SchemaProperties.safeParse(schema);
|
|
187
|
+
|
|
188
|
+
if (!safeSchema.success) {
|
|
189
|
+
// Unknown schema type, create a type alias to unknown
|
|
190
|
+
statements.push(
|
|
191
|
+
ts.factory.createTypeAliasDeclaration(
|
|
192
|
+
[ts.factory.createToken(ts.SyntaxKind.ExportKeyword)],
|
|
193
|
+
ts.factory.createIdentifier(sanitizedName),
|
|
194
|
+
undefined,
|
|
195
|
+
ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword)
|
|
196
|
+
)
|
|
197
|
+
);
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const schemaData = safeSchema.data;
|
|
202
|
+
const typeNode = this.buildTypeNode(schemaData);
|
|
203
|
+
|
|
204
|
+
// For object types with properties, create an interface
|
|
205
|
+
if (schemaData['type'] === 'object' && schemaData['properties']) {
|
|
206
|
+
statements.push(this.buildInterfaceDeclaration(sanitizedName, schemaData));
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// For all other types (enums, arrays, unions, etc.), create a type alias
|
|
211
|
+
statements.push(
|
|
212
|
+
ts.factory.createTypeAliasDeclaration([ts.factory.createToken(ts.SyntaxKind.ExportKeyword)], ts.factory.createIdentifier(sanitizedName), undefined, typeNode)
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return statements;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Converts an OpenAPI schema to a TypeScript type node.
|
|
221
|
+
*/
|
|
222
|
+
private buildTypeNode(schema: unknown): ts.TypeNode {
|
|
223
|
+
const safeSchema = SchemaProperties.safeParse(schema);
|
|
224
|
+
if (!safeSchema.success) {
|
|
225
|
+
return ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const prop = safeSchema.data;
|
|
229
|
+
|
|
230
|
+
// Handle $ref
|
|
231
|
+
if (this.isReference(prop)) {
|
|
232
|
+
const { $ref = '' } = Reference.parse(prop);
|
|
233
|
+
const refName = $ref.split('/').pop() ?? 'never';
|
|
234
|
+
const sanitizedRefName = this.typeBuilder.sanitizeIdentifier(refName);
|
|
235
|
+
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(sanitizedRefName), undefined);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Handle nullable
|
|
239
|
+
const isNullable = prop['nullable'] === true;
|
|
240
|
+
const baseTypeNode = this.buildBaseTypeNode(prop);
|
|
241
|
+
|
|
242
|
+
if (isNullable) {
|
|
243
|
+
return ts.factory.createUnionTypeNode([baseTypeNode, ts.factory.createLiteralTypeNode(ts.factory.createNull())]);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return baseTypeNode;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Builds the base type node without nullable handling.
|
|
251
|
+
*/
|
|
252
|
+
private buildBaseTypeNode(prop: Record<string, unknown>): ts.TypeNode {
|
|
253
|
+
// Handle anyOf/oneOf (union types)
|
|
254
|
+
if (prop['anyOf'] && Array.isArray(prop['anyOf']) && prop['anyOf'].length > 0) {
|
|
255
|
+
const types = prop['anyOf'].map((s: unknown) => this.buildTypeNode(s));
|
|
256
|
+
return ts.factory.createUnionTypeNode(types);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (prop['oneOf'] && Array.isArray(prop['oneOf']) && prop['oneOf'].length > 0) {
|
|
260
|
+
const types = prop['oneOf'].map((s: unknown) => this.buildTypeNode(s));
|
|
261
|
+
return ts.factory.createUnionTypeNode(types);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Handle allOf (intersection types)
|
|
265
|
+
if (prop['allOf'] && Array.isArray(prop['allOf']) && prop['allOf'].length > 0) {
|
|
266
|
+
const types = prop['allOf'].map((s: unknown) => this.buildTypeNode(s));
|
|
267
|
+
return ts.factory.createIntersectionTypeNode(types);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Handle enum
|
|
271
|
+
if (prop['enum'] && Array.isArray(prop['enum']) && prop['enum'].length > 0) {
|
|
272
|
+
const literalTypes = prop['enum'].map((val: unknown) => {
|
|
273
|
+
if (typeof val === 'string') {
|
|
274
|
+
return ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(val, true));
|
|
275
|
+
} else if (typeof val === 'number') {
|
|
276
|
+
if (val < 0) {
|
|
277
|
+
return ts.factory.createLiteralTypeNode(ts.factory.createPrefixUnaryExpression(ts.SyntaxKind.MinusToken, ts.factory.createNumericLiteral(String(Math.abs(val)))));
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
return ts.factory.createLiteralTypeNode(ts.factory.createNumericLiteral(String(val)));
|
|
281
|
+
} else if (typeof val === 'boolean') {
|
|
282
|
+
return ts.factory.createLiteralTypeNode(val ? ts.factory.createTrue() : ts.factory.createFalse());
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword);
|
|
286
|
+
});
|
|
287
|
+
return ts.factory.createUnionTypeNode(literalTypes);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Handle type-specific schemas
|
|
291
|
+
switch (prop['type']) {
|
|
292
|
+
case 'string':
|
|
293
|
+
return ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword);
|
|
294
|
+
case 'number':
|
|
295
|
+
case 'integer':
|
|
296
|
+
return ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword);
|
|
297
|
+
case 'boolean':
|
|
298
|
+
return ts.factory.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword);
|
|
299
|
+
case 'array': {
|
|
300
|
+
const itemsType = prop['items'] ? this.buildTypeNode(prop['items']) : ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword);
|
|
301
|
+
return ts.factory.createArrayTypeNode(itemsType);
|
|
302
|
+
}
|
|
303
|
+
case 'object': {
|
|
304
|
+
const properties = (prop['properties'] ?? {}) as Record<string, unknown>;
|
|
305
|
+
const requiredProps = (prop['required'] ?? []) as string[];
|
|
306
|
+
|
|
307
|
+
if (Object.keys(properties).length > 0) {
|
|
308
|
+
return this.buildObjectTypeLiteral(properties, requiredProps);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// Empty object or additionalProperties - use Record<string, unknown>
|
|
312
|
+
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Record'), [
|
|
313
|
+
ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
|
|
314
|
+
ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword)
|
|
315
|
+
]);
|
|
316
|
+
}
|
|
317
|
+
default:
|
|
318
|
+
return ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Builds a TypeScript type literal for an object schema.
|
|
324
|
+
*/
|
|
325
|
+
private buildObjectTypeLiteral(properties: Record<string, unknown>, requiredProps: string[]): ts.TypeLiteralNode {
|
|
326
|
+
const members = Object.entries(properties).map(([name, propSchema]) => {
|
|
327
|
+
const isRequired = requiredProps.includes(name);
|
|
328
|
+
const typeNode = this.buildTypeNode(propSchema);
|
|
329
|
+
|
|
330
|
+
return ts.factory.createPropertySignature(
|
|
139
331
|
undefined,
|
|
140
|
-
ts.factory.
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
332
|
+
ts.factory.createIdentifier(name),
|
|
333
|
+
isRequired ? undefined : ts.factory.createToken(ts.SyntaxKind.QuestionToken),
|
|
334
|
+
typeNode
|
|
335
|
+
);
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
return ts.factory.createTypeLiteralNode(members);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Builds a TypeScript interface declaration for an object schema.
|
|
343
|
+
*/
|
|
344
|
+
private buildInterfaceDeclaration(name: string, schema: Record<string, unknown>): ts.InterfaceDeclaration {
|
|
345
|
+
const properties = (schema['properties'] ?? {}) as Record<string, unknown>;
|
|
346
|
+
const requiredProps = (schema['required'] ?? []) as string[];
|
|
347
|
+
|
|
348
|
+
const members = Object.entries(properties).map(([propName, propSchema]) => {
|
|
349
|
+
const isRequired = requiredProps.includes(propName);
|
|
350
|
+
const typeNode = this.buildTypeNode(propSchema);
|
|
351
|
+
|
|
352
|
+
return ts.factory.createPropertySignature(
|
|
353
|
+
undefined,
|
|
354
|
+
ts.factory.createIdentifier(propName),
|
|
355
|
+
isRequired ? undefined : ts.factory.createToken(ts.SyntaxKind.QuestionToken),
|
|
356
|
+
typeNode
|
|
144
357
|
);
|
|
145
358
|
});
|
|
359
|
+
|
|
360
|
+
return ts.factory.createInterfaceDeclaration([ts.factory.createToken(ts.SyntaxKind.ExportKeyword)], ts.factory.createIdentifier(name), undefined, undefined, members);
|
|
146
361
|
}
|
|
147
362
|
|
|
148
|
-
private
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
363
|
+
private buildResponseValidationErrorClass(): ts.ClassDeclaration {
|
|
364
|
+
const typeParamT = ts.factory.createTypeParameterDeclaration(undefined, 'T');
|
|
365
|
+
|
|
366
|
+
const responseProperty = ts.factory.createPropertyDeclaration(
|
|
367
|
+
[ts.factory.createToken(ts.SyntaxKind.ReadonlyKeyword)],
|
|
368
|
+
'response',
|
|
369
|
+
undefined,
|
|
370
|
+
ts.factory.createTypeReferenceNode('Response'),
|
|
371
|
+
undefined
|
|
372
|
+
);
|
|
373
|
+
|
|
374
|
+
const errorProperty = ts.factory.createPropertyDeclaration(
|
|
375
|
+
[ts.factory.createToken(ts.SyntaxKind.ReadonlyKeyword)],
|
|
376
|
+
'error',
|
|
377
|
+
undefined,
|
|
378
|
+
ts.factory.createTypeReferenceNode(ts.factory.createQualifiedName(ts.factory.createIdentifier('z'), 'ZodError'), [ts.factory.createTypeReferenceNode('T')]),
|
|
379
|
+
undefined
|
|
380
|
+
);
|
|
381
|
+
|
|
382
|
+
const constructorDecl = ts.factory.createConstructorDeclaration(
|
|
383
|
+
undefined,
|
|
384
|
+
[
|
|
385
|
+
ts.factory.createParameterDeclaration(undefined, undefined, 'message', undefined, ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword)),
|
|
386
|
+
ts.factory.createParameterDeclaration(undefined, undefined, 'response', undefined, ts.factory.createTypeReferenceNode('Response')),
|
|
387
|
+
ts.factory.createParameterDeclaration(
|
|
388
|
+
undefined,
|
|
389
|
+
undefined,
|
|
390
|
+
'error',
|
|
391
|
+
undefined,
|
|
392
|
+
ts.factory.createTypeReferenceNode(ts.factory.createQualifiedName(ts.factory.createIdentifier('z'), 'ZodError'), [ts.factory.createTypeReferenceNode('T')])
|
|
393
|
+
)
|
|
394
|
+
],
|
|
395
|
+
ts.factory.createBlock(
|
|
396
|
+
[
|
|
397
|
+
ts.factory.createExpressionStatement(ts.factory.createCallExpression(ts.factory.createSuper(), undefined, [ts.factory.createIdentifier('message')])),
|
|
398
|
+
ts.factory.createExpressionStatement(
|
|
399
|
+
ts.factory.createBinaryExpression(
|
|
400
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createThis(), 'name'),
|
|
401
|
+
ts.SyntaxKind.EqualsToken,
|
|
402
|
+
ts.factory.createAsExpression(ts.factory.createStringLiteral('ResponseValidationError', true), ts.factory.createTypeReferenceNode('const'))
|
|
403
|
+
)
|
|
404
|
+
),
|
|
405
|
+
ts.factory.createExpressionStatement(
|
|
406
|
+
ts.factory.createBinaryExpression(
|
|
407
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createThis(), 'response'),
|
|
408
|
+
ts.SyntaxKind.EqualsToken,
|
|
409
|
+
ts.factory.createIdentifier('response')
|
|
410
|
+
)
|
|
411
|
+
),
|
|
412
|
+
ts.factory.createExpressionStatement(
|
|
413
|
+
ts.factory.createBinaryExpression(
|
|
414
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createThis(), 'error'),
|
|
415
|
+
ts.SyntaxKind.EqualsToken,
|
|
416
|
+
ts.factory.createIdentifier('error')
|
|
417
|
+
)
|
|
418
|
+
)
|
|
419
|
+
],
|
|
420
|
+
true
|
|
421
|
+
)
|
|
422
|
+
);
|
|
423
|
+
|
|
424
|
+
const dataGetter = ts.factory.createGetAccessorDeclaration(
|
|
425
|
+
undefined,
|
|
426
|
+
'data',
|
|
427
|
+
[],
|
|
428
|
+
ts.factory.createTypeReferenceNode('T'),
|
|
429
|
+
ts.factory.createBlock(
|
|
430
|
+
[
|
|
431
|
+
ts.factory.createReturnStatement(
|
|
432
|
+
ts.factory.createAsExpression(
|
|
433
|
+
ts.factory.createCallExpression(
|
|
434
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createPropertyAccessExpression(ts.factory.createThis(), 'response'), 'json'),
|
|
435
|
+
undefined,
|
|
436
|
+
[]
|
|
437
|
+
),
|
|
438
|
+
ts.factory.createTypeReferenceNode('T')
|
|
439
|
+
)
|
|
440
|
+
)
|
|
441
|
+
],
|
|
442
|
+
true
|
|
443
|
+
)
|
|
444
|
+
);
|
|
445
|
+
|
|
446
|
+
return ts.factory.createClassDeclaration(
|
|
447
|
+
[ts.factory.createToken(ts.SyntaxKind.ExportKeyword)],
|
|
448
|
+
'ResponseValidationError',
|
|
449
|
+
[typeParamT],
|
|
450
|
+
[ts.factory.createHeritageClause(ts.SyntaxKind.ExtendsKeyword, [ts.factory.createExpressionWithTypeArguments(ts.factory.createIdentifier('Error'), undefined)])],
|
|
451
|
+
[responseProperty, errorProperty, constructorDecl, dataGetter]
|
|
452
|
+
);
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
private buildClientClass(openapi: OpenApiSpecType, schemas: Record<string, ts.VariableStatement>): ts.ClassDeclaration {
|
|
152
456
|
const clientName = this.generateClientName(openapi.info.title);
|
|
153
457
|
const methods = this.buildClientMethods(openapi, schemas);
|
|
154
458
|
|
|
@@ -163,8 +467,8 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
163
467
|
this.buildGetBaseRequestOptionsMethod(),
|
|
164
468
|
this.buildHandleResponseMethod(),
|
|
165
469
|
this.buildHttpRequestMethod(),
|
|
166
|
-
...methods
|
|
167
|
-
]
|
|
470
|
+
...methods
|
|
471
|
+
]
|
|
168
472
|
);
|
|
169
473
|
}
|
|
170
474
|
|
|
@@ -182,8 +486,8 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
182
486
|
ts.factory.createIdentifier('options'),
|
|
183
487
|
undefined,
|
|
184
488
|
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('ClientOptions'), undefined),
|
|
185
|
-
undefined
|
|
186
|
-
)
|
|
489
|
+
undefined
|
|
490
|
+
)
|
|
187
491
|
],
|
|
188
492
|
ts.factory.createBlock(
|
|
189
493
|
[
|
|
@@ -197,72 +501,51 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
197
501
|
undefined,
|
|
198
502
|
ts.factory.createConditionalExpression(
|
|
199
503
|
ts.factory.createBinaryExpression(
|
|
200
|
-
ts.factory.createPropertyAccessExpression(
|
|
201
|
-
ts.factory.createIdentifier('options'),
|
|
202
|
-
ts.factory.createIdentifier('baseUrl'),
|
|
203
|
-
),
|
|
504
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('baseUrl')),
|
|
204
505
|
ts.factory.createToken(ts.SyntaxKind.ExclamationEqualsEqualsToken),
|
|
205
|
-
ts.factory.createNull()
|
|
506
|
+
ts.factory.createNull()
|
|
206
507
|
),
|
|
207
508
|
ts.factory.createToken(ts.SyntaxKind.QuestionToken),
|
|
208
|
-
ts.factory.createPropertyAccessExpression(
|
|
209
|
-
ts.factory.createIdentifier('options'),
|
|
210
|
-
ts.factory.createIdentifier('baseUrl'),
|
|
211
|
-
),
|
|
509
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('baseUrl')),
|
|
212
510
|
ts.factory.createToken(ts.SyntaxKind.ColonToken),
|
|
213
511
|
ts.factory.createCallExpression(ts.factory.createIdentifier('resolveServerUrl'), undefined, [
|
|
214
|
-
ts.factory.createPropertyAccessExpression(
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
ts.factory.createIdentifier('options'),
|
|
220
|
-
ts.factory.createIdentifier('serverVariables'),
|
|
221
|
-
),
|
|
222
|
-
]),
|
|
223
|
-
),
|
|
224
|
-
),
|
|
512
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('serverIndex')),
|
|
513
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('serverVariables'))
|
|
514
|
+
])
|
|
515
|
+
)
|
|
516
|
+
)
|
|
225
517
|
],
|
|
226
|
-
ts.NodeFlags.Const
|
|
227
|
-
)
|
|
518
|
+
ts.NodeFlags.Const
|
|
519
|
+
)
|
|
228
520
|
),
|
|
229
521
|
ts.factory.createExpressionStatement(
|
|
230
522
|
ts.factory.createBinaryExpression(
|
|
231
|
-
ts.factory.createPropertyAccessExpression(
|
|
232
|
-
ts.factory.createThis(),
|
|
233
|
-
ts.factory.createPrivateIdentifier('#baseUrl'),
|
|
234
|
-
),
|
|
523
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createThis(), ts.factory.createPrivateIdentifier('#baseUrl')),
|
|
235
524
|
ts.factory.createToken(ts.SyntaxKind.EqualsToken),
|
|
236
|
-
ts.factory.createIdentifier('resolvedUrl')
|
|
237
|
-
)
|
|
238
|
-
)
|
|
525
|
+
ts.factory.createIdentifier('resolvedUrl')
|
|
526
|
+
)
|
|
527
|
+
)
|
|
239
528
|
],
|
|
240
|
-
true
|
|
241
|
-
)
|
|
529
|
+
true
|
|
530
|
+
)
|
|
242
531
|
);
|
|
243
532
|
} else {
|
|
244
533
|
// Fallback: simple baseUrl parameter
|
|
245
534
|
return ts.factory.createConstructorDeclaration(
|
|
246
535
|
undefined,
|
|
247
|
-
[
|
|
248
|
-
this.typeBuilder.createParameter('baseUrl', 'string', ts.factory.createStringLiteral('/', true)),
|
|
249
|
-
this.typeBuilder.createParameter('_', 'unknown', undefined, true),
|
|
250
|
-
],
|
|
536
|
+
[this.typeBuilder.createParameter('baseUrl', 'string', ts.factory.createStringLiteral('/', true)), this.typeBuilder.createParameter('_', 'unknown', undefined, true)],
|
|
251
537
|
ts.factory.createBlock(
|
|
252
538
|
[
|
|
253
539
|
ts.factory.createExpressionStatement(
|
|
254
540
|
ts.factory.createBinaryExpression(
|
|
255
|
-
ts.factory.createPropertyAccessExpression(
|
|
256
|
-
ts.factory.createThis(),
|
|
257
|
-
ts.factory.createPrivateIdentifier('#baseUrl'),
|
|
258
|
-
),
|
|
541
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createThis(), ts.factory.createPrivateIdentifier('#baseUrl')),
|
|
259
542
|
ts.factory.createToken(ts.SyntaxKind.EqualsToken),
|
|
260
|
-
ts.factory.createIdentifier('baseUrl')
|
|
261
|
-
)
|
|
262
|
-
)
|
|
543
|
+
ts.factory.createIdentifier('baseUrl')
|
|
544
|
+
)
|
|
545
|
+
)
|
|
263
546
|
],
|
|
264
|
-
true
|
|
265
|
-
)
|
|
547
|
+
true
|
|
548
|
+
)
|
|
266
549
|
);
|
|
267
550
|
}
|
|
268
551
|
}
|
|
@@ -280,14 +563,11 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
280
563
|
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('RequestInit'), undefined),
|
|
281
564
|
ts.factory.createUnionTypeNode([
|
|
282
565
|
ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral('method', true)),
|
|
283
|
-
ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral('body', true))
|
|
284
|
-
])
|
|
285
|
-
])
|
|
566
|
+
ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral('body', true))
|
|
567
|
+
])
|
|
568
|
+
])
|
|
286
569
|
]),
|
|
287
|
-
ts.factory.createBlock(
|
|
288
|
-
[ts.factory.createReturnStatement(ts.factory.createObjectLiteralExpression([], false))],
|
|
289
|
-
true,
|
|
290
|
-
),
|
|
570
|
+
ts.factory.createBlock([ts.factory.createReturnStatement(ts.factory.createObjectLiteralExpression([], false))], true)
|
|
291
571
|
);
|
|
292
572
|
}
|
|
293
573
|
|
|
@@ -302,15 +582,10 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
302
582
|
this.typeBuilder.createParameter('response', 'Response'),
|
|
303
583
|
this.typeBuilder.createParameter('method', 'string'),
|
|
304
584
|
this.typeBuilder.createParameter('path', 'string'),
|
|
305
|
-
this.typeBuilder.createParameter(
|
|
306
|
-
'options',
|
|
307
|
-
'{params?: Record<string, string | number | boolean>; data?: unknown; contentType?: string; headers?: Record<string, string>}',
|
|
308
|
-
),
|
|
585
|
+
this.typeBuilder.createParameter('options', '{params?: Record<string, string | number | boolean>; data?: unknown; contentType?: string; headers?: Record<string, string>}')
|
|
309
586
|
],
|
|
310
|
-
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
|
|
311
|
-
|
|
312
|
-
]),
|
|
313
|
-
ts.factory.createBlock([ts.factory.createReturnStatement(ts.factory.createIdentifier('response'))], true),
|
|
587
|
+
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Response'), undefined)]),
|
|
588
|
+
ts.factory.createBlock([ts.factory.createReturnStatement(ts.factory.createIdentifier('response'))], true)
|
|
314
589
|
);
|
|
315
590
|
}
|
|
316
591
|
|
|
@@ -328,12 +603,10 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
328
603
|
'options',
|
|
329
604
|
'{params?: Record<string, string | number | boolean>; data?: unknown; contentType?: string; headers?: Record<string, string>}',
|
|
330
605
|
ts.factory.createObjectLiteralExpression([], false),
|
|
331
|
-
false
|
|
332
|
-
)
|
|
606
|
+
false
|
|
607
|
+
)
|
|
333
608
|
],
|
|
334
|
-
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
|
|
335
|
-
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('T'), undefined),
|
|
336
|
-
]),
|
|
609
|
+
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('T'), undefined)]),
|
|
337
610
|
ts.factory.createBlock(
|
|
338
611
|
[
|
|
339
612
|
// Create initial URL object that we will use to build the final URL
|
|
@@ -347,15 +620,12 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
347
620
|
undefined,
|
|
348
621
|
ts.factory.createNewExpression(ts.factory.createIdentifier('URL'), undefined, [
|
|
349
622
|
ts.factory.createIdentifier('path'),
|
|
350
|
-
ts.factory.createPropertyAccessExpression(
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
),
|
|
354
|
-
]),
|
|
355
|
-
),
|
|
623
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createThis(), ts.factory.createPrivateIdentifier('#baseUrl'))
|
|
624
|
+
])
|
|
625
|
+
)
|
|
356
626
|
],
|
|
357
|
-
ts.NodeFlags.Const
|
|
358
|
-
)
|
|
627
|
+
ts.NodeFlags.Const
|
|
628
|
+
)
|
|
359
629
|
),
|
|
360
630
|
ts.factory.createVariableStatement(
|
|
361
631
|
undefined,
|
|
@@ -367,31 +637,20 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
367
637
|
undefined,
|
|
368
638
|
ts.factory.createConditionalExpression(
|
|
369
639
|
ts.factory.createBinaryExpression(
|
|
370
|
-
ts.factory.createPropertyAccessExpression(
|
|
371
|
-
ts.factory.createIdentifier('options'),
|
|
372
|
-
ts.factory.createIdentifier('params'),
|
|
373
|
-
),
|
|
640
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('params')),
|
|
374
641
|
ts.factory.createToken(ts.SyntaxKind.AmpersandAmpersandToken),
|
|
375
642
|
ts.factory.createBinaryExpression(
|
|
376
643
|
ts.factory.createPropertyAccessExpression(
|
|
377
644
|
ts.factory.createCallExpression(
|
|
378
|
-
ts.factory.createPropertyAccessExpression(
|
|
379
|
-
ts.factory.createIdentifier('Object'),
|
|
380
|
-
ts.factory.createIdentifier('keys'),
|
|
381
|
-
),
|
|
645
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('Object'), ts.factory.createIdentifier('keys')),
|
|
382
646
|
undefined,
|
|
383
|
-
[
|
|
384
|
-
ts.factory.createPropertyAccessExpression(
|
|
385
|
-
ts.factory.createIdentifier('options'),
|
|
386
|
-
ts.factory.createIdentifier('params'),
|
|
387
|
-
),
|
|
388
|
-
],
|
|
647
|
+
[ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('params'))]
|
|
389
648
|
),
|
|
390
|
-
ts.factory.createIdentifier('length')
|
|
649
|
+
ts.factory.createIdentifier('length')
|
|
391
650
|
),
|
|
392
651
|
ts.factory.createToken(ts.SyntaxKind.GreaterThanToken),
|
|
393
|
-
ts.factory.createNumericLiteral('0')
|
|
394
|
-
)
|
|
652
|
+
ts.factory.createNumericLiteral('0')
|
|
653
|
+
)
|
|
395
654
|
),
|
|
396
655
|
undefined,
|
|
397
656
|
ts.factory.createCallExpression(
|
|
@@ -410,19 +669,11 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
410
669
|
ts.factory.createCallExpression(
|
|
411
670
|
ts.factory.createPropertyAccessExpression(
|
|
412
671
|
ts.factory.createCallExpression(
|
|
413
|
-
ts.factory.createPropertyAccessExpression(
|
|
414
|
-
ts.factory.createIdentifier('Object'),
|
|
415
|
-
ts.factory.createIdentifier('entries'),
|
|
416
|
-
),
|
|
672
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('Object'), ts.factory.createIdentifier('entries')),
|
|
417
673
|
undefined,
|
|
418
|
-
[
|
|
419
|
-
ts.factory.createPropertyAccessExpression(
|
|
420
|
-
ts.factory.createIdentifier('options'),
|
|
421
|
-
ts.factory.createIdentifier('params'),
|
|
422
|
-
),
|
|
423
|
-
],
|
|
674
|
+
[ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('params'))]
|
|
424
675
|
),
|
|
425
|
-
ts.factory.createIdentifier('filter')
|
|
676
|
+
ts.factory.createIdentifier('filter')
|
|
426
677
|
),
|
|
427
678
|
undefined,
|
|
428
679
|
[
|
|
@@ -434,34 +685,24 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
434
685
|
undefined,
|
|
435
686
|
undefined,
|
|
436
687
|
ts.factory.createArrayBindingPattern([
|
|
437
|
-
ts.factory.createBindingElement(
|
|
438
|
-
|
|
439
|
-
undefined,
|
|
440
|
-
ts.factory.createIdentifier(''),
|
|
441
|
-
undefined,
|
|
442
|
-
),
|
|
443
|
-
ts.factory.createBindingElement(
|
|
444
|
-
undefined,
|
|
445
|
-
undefined,
|
|
446
|
-
ts.factory.createIdentifier('value'),
|
|
447
|
-
undefined,
|
|
448
|
-
),
|
|
688
|
+
ts.factory.createBindingElement(undefined, undefined, ts.factory.createIdentifier(''), undefined),
|
|
689
|
+
ts.factory.createBindingElement(undefined, undefined, ts.factory.createIdentifier('value'), undefined)
|
|
449
690
|
]),
|
|
450
691
|
undefined,
|
|
451
|
-
undefined
|
|
452
|
-
)
|
|
692
|
+
undefined
|
|
693
|
+
)
|
|
453
694
|
],
|
|
454
695
|
undefined,
|
|
455
696
|
ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
|
|
456
697
|
ts.factory.createBinaryExpression(
|
|
457
698
|
ts.factory.createIdentifier('value'),
|
|
458
699
|
ts.SyntaxKind.ExclamationEqualsEqualsToken,
|
|
459
|
-
ts.factory.createIdentifier('undefined')
|
|
460
|
-
)
|
|
461
|
-
)
|
|
462
|
-
]
|
|
700
|
+
ts.factory.createIdentifier('undefined')
|
|
701
|
+
)
|
|
702
|
+
)
|
|
703
|
+
]
|
|
463
704
|
),
|
|
464
|
-
ts.factory.createIdentifier('forEach')
|
|
705
|
+
ts.factory.createIdentifier('forEach')
|
|
465
706
|
),
|
|
466
707
|
undefined,
|
|
467
708
|
[
|
|
@@ -473,22 +714,12 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
473
714
|
undefined,
|
|
474
715
|
undefined,
|
|
475
716
|
ts.factory.createArrayBindingPattern([
|
|
476
|
-
ts.factory.createBindingElement(
|
|
477
|
-
|
|
478
|
-
undefined,
|
|
479
|
-
ts.factory.createIdentifier('key'),
|
|
480
|
-
undefined,
|
|
481
|
-
),
|
|
482
|
-
ts.factory.createBindingElement(
|
|
483
|
-
undefined,
|
|
484
|
-
undefined,
|
|
485
|
-
ts.factory.createIdentifier('value'),
|
|
486
|
-
undefined,
|
|
487
|
-
),
|
|
717
|
+
ts.factory.createBindingElement(undefined, undefined, ts.factory.createIdentifier('key'), undefined),
|
|
718
|
+
ts.factory.createBindingElement(undefined, undefined, ts.factory.createIdentifier('value'), undefined)
|
|
488
719
|
]),
|
|
489
720
|
undefined,
|
|
490
|
-
undefined
|
|
491
|
-
)
|
|
721
|
+
undefined
|
|
722
|
+
)
|
|
492
723
|
],
|
|
493
724
|
undefined,
|
|
494
725
|
ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
|
|
@@ -497,62 +728,49 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
497
728
|
ts.factory.createExpressionStatement(
|
|
498
729
|
ts.factory.createCallExpression(
|
|
499
730
|
ts.factory.createPropertyAccessExpression(
|
|
500
|
-
ts.factory.createPropertyAccessExpression(
|
|
501
|
-
|
|
502
|
-
ts.factory.createIdentifier('searchParams'),
|
|
503
|
-
),
|
|
504
|
-
ts.factory.createIdentifier('set'),
|
|
731
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('baseUrl'), ts.factory.createIdentifier('searchParams')),
|
|
732
|
+
ts.factory.createIdentifier('set')
|
|
505
733
|
),
|
|
506
734
|
undefined,
|
|
507
735
|
[
|
|
508
736
|
ts.factory.createIdentifier('key'),
|
|
509
|
-
ts.factory.createCallExpression(
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
),
|
|
514
|
-
],
|
|
515
|
-
),
|
|
516
|
-
),
|
|
737
|
+
ts.factory.createCallExpression(ts.factory.createIdentifier('String'), undefined, [ts.factory.createIdentifier('value')])
|
|
738
|
+
]
|
|
739
|
+
)
|
|
740
|
+
)
|
|
517
741
|
],
|
|
518
|
-
false
|
|
519
|
-
)
|
|
520
|
-
)
|
|
521
|
-
]
|
|
522
|
-
)
|
|
742
|
+
false
|
|
743
|
+
)
|
|
744
|
+
)
|
|
745
|
+
]
|
|
746
|
+
)
|
|
523
747
|
),
|
|
524
748
|
ts.factory.createReturnStatement(
|
|
525
749
|
ts.factory.createCallExpression(
|
|
526
|
-
ts.factory.createPropertyAccessExpression(
|
|
527
|
-
ts.factory.createIdentifier('baseUrl'),
|
|
528
|
-
ts.factory.createIdentifier('toString'),
|
|
529
|
-
),
|
|
750
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('baseUrl'), ts.factory.createIdentifier('toString')),
|
|
530
751
|
undefined,
|
|
531
|
-
[]
|
|
532
|
-
)
|
|
533
|
-
)
|
|
752
|
+
[]
|
|
753
|
+
)
|
|
754
|
+
)
|
|
534
755
|
],
|
|
535
|
-
true
|
|
536
|
-
)
|
|
537
|
-
)
|
|
756
|
+
true
|
|
757
|
+
)
|
|
758
|
+
)
|
|
538
759
|
),
|
|
539
760
|
undefined,
|
|
540
|
-
[]
|
|
761
|
+
[]
|
|
541
762
|
),
|
|
542
763
|
undefined,
|
|
543
764
|
ts.factory.createCallExpression(
|
|
544
|
-
ts.factory.createPropertyAccessExpression(
|
|
545
|
-
ts.factory.createIdentifier('baseUrl'),
|
|
546
|
-
ts.factory.createIdentifier('toString'),
|
|
547
|
-
),
|
|
765
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('baseUrl'), ts.factory.createIdentifier('toString')),
|
|
548
766
|
undefined,
|
|
549
|
-
[]
|
|
550
|
-
)
|
|
551
|
-
)
|
|
552
|
-
)
|
|
767
|
+
[]
|
|
768
|
+
)
|
|
769
|
+
)
|
|
770
|
+
)
|
|
553
771
|
],
|
|
554
|
-
ts.NodeFlags.Const
|
|
555
|
-
)
|
|
772
|
+
ts.NodeFlags.Const
|
|
773
|
+
)
|
|
556
774
|
),
|
|
557
775
|
// Get base request options (headers, signal, credentials, etc.)
|
|
558
776
|
ts.factory.createVariableStatement(
|
|
@@ -564,17 +782,14 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
564
782
|
undefined,
|
|
565
783
|
undefined,
|
|
566
784
|
ts.factory.createCallExpression(
|
|
567
|
-
ts.factory.createPropertyAccessExpression(
|
|
568
|
-
ts.factory.createThis(),
|
|
569
|
-
ts.factory.createIdentifier('getBaseRequestOptions'),
|
|
570
|
-
),
|
|
785
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createThis(), ts.factory.createIdentifier('getBaseRequestOptions')),
|
|
571
786
|
undefined,
|
|
572
|
-
[]
|
|
573
|
-
)
|
|
574
|
-
)
|
|
787
|
+
[]
|
|
788
|
+
)
|
|
789
|
+
)
|
|
575
790
|
],
|
|
576
|
-
ts.NodeFlags.Const
|
|
577
|
-
)
|
|
791
|
+
ts.NodeFlags.Const
|
|
792
|
+
)
|
|
578
793
|
),
|
|
579
794
|
// Build Content-Type header
|
|
580
795
|
ts.factory.createVariableStatement(
|
|
@@ -587,22 +802,19 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
587
802
|
undefined,
|
|
588
803
|
ts.factory.createConditionalExpression(
|
|
589
804
|
ts.factory.createBinaryExpression(
|
|
590
|
-
ts.factory.createPropertyAccessExpression(
|
|
591
|
-
ts.factory.createIdentifier('options'),
|
|
592
|
-
ts.factory.createIdentifier('contentType'),
|
|
593
|
-
),
|
|
805
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('contentType')),
|
|
594
806
|
ts.factory.createToken(ts.SyntaxKind.EqualsEqualsEqualsToken),
|
|
595
|
-
ts.factory.createStringLiteral('application/x-www-form-urlencoded', true)
|
|
807
|
+
ts.factory.createStringLiteral('application/x-www-form-urlencoded', true)
|
|
596
808
|
),
|
|
597
809
|
undefined,
|
|
598
810
|
ts.factory.createStringLiteral('application/x-www-form-urlencoded', true),
|
|
599
811
|
undefined,
|
|
600
|
-
ts.factory.createStringLiteral('application/json', true)
|
|
601
|
-
)
|
|
602
|
-
)
|
|
812
|
+
ts.factory.createStringLiteral('application/json', true)
|
|
813
|
+
)
|
|
814
|
+
)
|
|
603
815
|
],
|
|
604
|
-
ts.NodeFlags.Const
|
|
605
|
-
)
|
|
816
|
+
ts.NodeFlags.Const
|
|
817
|
+
)
|
|
606
818
|
),
|
|
607
819
|
// Merge headers: base headers, Content-Type, and request-specific headers
|
|
608
820
|
ts.factory.createVariableStatement(
|
|
@@ -615,25 +827,19 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
615
827
|
undefined,
|
|
616
828
|
ts.factory.createConditionalExpression(
|
|
617
829
|
ts.factory.createBinaryExpression(
|
|
618
|
-
ts.factory.createPropertyAccessExpression(
|
|
619
|
-
ts.factory.createIdentifier('baseOptions'),
|
|
620
|
-
ts.factory.createIdentifier('headers'),
|
|
621
|
-
),
|
|
830
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('baseOptions'), ts.factory.createIdentifier('headers')),
|
|
622
831
|
ts.factory.createToken(ts.SyntaxKind.ExclamationEqualsEqualsToken),
|
|
623
|
-
ts.factory.createIdentifier('undefined')
|
|
832
|
+
ts.factory.createIdentifier('undefined')
|
|
624
833
|
),
|
|
625
834
|
undefined,
|
|
626
|
-
ts.factory.createPropertyAccessExpression(
|
|
627
|
-
ts.factory.createIdentifier('baseOptions'),
|
|
628
|
-
ts.factory.createIdentifier('headers'),
|
|
629
|
-
),
|
|
835
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('baseOptions'), ts.factory.createIdentifier('headers')),
|
|
630
836
|
undefined,
|
|
631
|
-
ts.factory.createObjectLiteralExpression([], false)
|
|
632
|
-
)
|
|
633
|
-
)
|
|
837
|
+
ts.factory.createObjectLiteralExpression([], false)
|
|
838
|
+
)
|
|
839
|
+
)
|
|
634
840
|
],
|
|
635
|
-
ts.NodeFlags.Const
|
|
636
|
-
)
|
|
841
|
+
ts.NodeFlags.Const
|
|
842
|
+
)
|
|
637
843
|
),
|
|
638
844
|
ts.factory.createVariableStatement(
|
|
639
845
|
undefined,
|
|
@@ -644,46 +850,32 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
644
850
|
undefined,
|
|
645
851
|
undefined,
|
|
646
852
|
ts.factory.createCallExpression(
|
|
647
|
-
ts.factory.createPropertyAccessExpression(
|
|
648
|
-
ts.factory.createIdentifier('Object'),
|
|
649
|
-
ts.factory.createIdentifier('assign'),
|
|
650
|
-
),
|
|
853
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('Object'), ts.factory.createIdentifier('assign')),
|
|
651
854
|
undefined,
|
|
652
855
|
[
|
|
653
856
|
ts.factory.createObjectLiteralExpression([], false),
|
|
654
857
|
ts.factory.createIdentifier('baseHeaders'),
|
|
655
858
|
ts.factory.createObjectLiteralExpression(
|
|
656
|
-
[
|
|
657
|
-
|
|
658
|
-
ts.factory.createStringLiteral('Content-Type', true),
|
|
659
|
-
ts.factory.createIdentifier('contentType'),
|
|
660
|
-
),
|
|
661
|
-
],
|
|
662
|
-
false,
|
|
859
|
+
[ts.factory.createPropertyAssignment(ts.factory.createStringLiteral('Content-Type', true), ts.factory.createIdentifier('contentType'))],
|
|
860
|
+
false
|
|
663
861
|
),
|
|
664
862
|
ts.factory.createConditionalExpression(
|
|
665
863
|
ts.factory.createBinaryExpression(
|
|
666
|
-
ts.factory.createPropertyAccessExpression(
|
|
667
|
-
ts.factory.createIdentifier('options'),
|
|
668
|
-
ts.factory.createIdentifier('headers'),
|
|
669
|
-
),
|
|
864
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('headers')),
|
|
670
865
|
ts.factory.createToken(ts.SyntaxKind.ExclamationEqualsEqualsToken),
|
|
671
|
-
ts.factory.createIdentifier('undefined')
|
|
866
|
+
ts.factory.createIdentifier('undefined')
|
|
672
867
|
),
|
|
673
868
|
undefined,
|
|
674
|
-
ts.factory.createPropertyAccessExpression(
|
|
675
|
-
ts.factory.createIdentifier('options'),
|
|
676
|
-
ts.factory.createIdentifier('headers'),
|
|
677
|
-
),
|
|
869
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('headers')),
|
|
678
870
|
undefined,
|
|
679
|
-
ts.factory.createObjectLiteralExpression([], false)
|
|
680
|
-
)
|
|
681
|
-
]
|
|
682
|
-
)
|
|
683
|
-
)
|
|
871
|
+
ts.factory.createObjectLiteralExpression([], false)
|
|
872
|
+
)
|
|
873
|
+
]
|
|
874
|
+
)
|
|
875
|
+
)
|
|
684
876
|
],
|
|
685
|
-
ts.NodeFlags.Const
|
|
686
|
-
)
|
|
877
|
+
ts.NodeFlags.Const
|
|
878
|
+
)
|
|
687
879
|
),
|
|
688
880
|
// Build body with form-urlencoded support
|
|
689
881
|
ts.factory.createVariableStatement(
|
|
@@ -696,22 +888,16 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
696
888
|
undefined,
|
|
697
889
|
ts.factory.createConditionalExpression(
|
|
698
890
|
ts.factory.createBinaryExpression(
|
|
699
|
-
ts.factory.createPropertyAccessExpression(
|
|
700
|
-
ts.factory.createIdentifier('options'),
|
|
701
|
-
ts.factory.createIdentifier('data'),
|
|
702
|
-
),
|
|
891
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('data')),
|
|
703
892
|
ts.factory.createToken(ts.SyntaxKind.ExclamationEqualsEqualsToken),
|
|
704
|
-
ts.factory.createIdentifier('undefined')
|
|
893
|
+
ts.factory.createIdentifier('undefined')
|
|
705
894
|
),
|
|
706
895
|
undefined,
|
|
707
896
|
ts.factory.createConditionalExpression(
|
|
708
897
|
ts.factory.createBinaryExpression(
|
|
709
|
-
ts.factory.createPropertyAccessExpression(
|
|
710
|
-
ts.factory.createIdentifier('options'),
|
|
711
|
-
ts.factory.createIdentifier('contentType'),
|
|
712
|
-
),
|
|
898
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('contentType')),
|
|
713
899
|
ts.factory.createToken(ts.SyntaxKind.EqualsEqualsEqualsToken),
|
|
714
|
-
ts.factory.createStringLiteral('application/x-www-form-urlencoded', true)
|
|
900
|
+
ts.factory.createStringLiteral('application/x-www-form-urlencoded', true)
|
|
715
901
|
),
|
|
716
902
|
undefined,
|
|
717
903
|
// Form-urlencoded: convert object to URLSearchParams
|
|
@@ -733,33 +919,21 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
733
919
|
ts.factory.createIdentifier('params'),
|
|
734
920
|
undefined,
|
|
735
921
|
undefined,
|
|
736
|
-
ts.factory.createNewExpression(
|
|
737
|
-
|
|
738
|
-
undefined,
|
|
739
|
-
[],
|
|
740
|
-
),
|
|
741
|
-
),
|
|
922
|
+
ts.factory.createNewExpression(ts.factory.createIdentifier('URLSearchParams'), undefined, [])
|
|
923
|
+
)
|
|
742
924
|
],
|
|
743
|
-
ts.NodeFlags.Const
|
|
744
|
-
)
|
|
925
|
+
ts.NodeFlags.Const
|
|
926
|
+
)
|
|
745
927
|
),
|
|
746
928
|
ts.factory.createExpressionStatement(
|
|
747
929
|
ts.factory.createCallExpression(
|
|
748
930
|
ts.factory.createPropertyAccessExpression(
|
|
749
931
|
ts.factory.createCallExpression(
|
|
750
|
-
ts.factory.createPropertyAccessExpression(
|
|
751
|
-
ts.factory.createIdentifier('Object'),
|
|
752
|
-
ts.factory.createIdentifier('entries'),
|
|
753
|
-
),
|
|
932
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('Object'), ts.factory.createIdentifier('entries')),
|
|
754
933
|
undefined,
|
|
755
|
-
[
|
|
756
|
-
ts.factory.createPropertyAccessExpression(
|
|
757
|
-
ts.factory.createIdentifier('options'),
|
|
758
|
-
ts.factory.createIdentifier('data'),
|
|
759
|
-
),
|
|
760
|
-
],
|
|
934
|
+
[ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('data'))]
|
|
761
935
|
),
|
|
762
|
-
ts.factory.createIdentifier('forEach')
|
|
936
|
+
ts.factory.createIdentifier('forEach')
|
|
763
937
|
),
|
|
764
938
|
undefined,
|
|
765
939
|
[
|
|
@@ -771,22 +945,12 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
771
945
|
undefined,
|
|
772
946
|
undefined,
|
|
773
947
|
ts.factory.createArrayBindingPattern([
|
|
774
|
-
ts.factory.createBindingElement(
|
|
775
|
-
|
|
776
|
-
undefined,
|
|
777
|
-
ts.factory.createIdentifier('key'),
|
|
778
|
-
undefined,
|
|
779
|
-
),
|
|
780
|
-
ts.factory.createBindingElement(
|
|
781
|
-
undefined,
|
|
782
|
-
undefined,
|
|
783
|
-
ts.factory.createIdentifier('value'),
|
|
784
|
-
undefined,
|
|
785
|
-
),
|
|
948
|
+
ts.factory.createBindingElement(undefined, undefined, ts.factory.createIdentifier('key'), undefined),
|
|
949
|
+
ts.factory.createBindingElement(undefined, undefined, ts.factory.createIdentifier('value'), undefined)
|
|
786
950
|
]),
|
|
787
951
|
undefined,
|
|
788
|
-
undefined
|
|
789
|
-
)
|
|
952
|
+
undefined
|
|
953
|
+
)
|
|
790
954
|
],
|
|
791
955
|
undefined,
|
|
792
956
|
ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
|
|
@@ -794,69 +958,51 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
794
958
|
[
|
|
795
959
|
ts.factory.createExpressionStatement(
|
|
796
960
|
ts.factory.createCallExpression(
|
|
797
|
-
ts.factory.createPropertyAccessExpression(
|
|
798
|
-
ts.factory.createIdentifier('params'),
|
|
799
|
-
ts.factory.createIdentifier('set'),
|
|
800
|
-
),
|
|
961
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('params'), ts.factory.createIdentifier('set')),
|
|
801
962
|
undefined,
|
|
802
963
|
[
|
|
803
964
|
ts.factory.createIdentifier('key'),
|
|
804
|
-
ts.factory.createCallExpression(
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
),
|
|
809
|
-
],
|
|
810
|
-
),
|
|
811
|
-
),
|
|
965
|
+
ts.factory.createCallExpression(ts.factory.createIdentifier('String'), undefined, [ts.factory.createIdentifier('value')])
|
|
966
|
+
]
|
|
967
|
+
)
|
|
968
|
+
)
|
|
812
969
|
],
|
|
813
|
-
false
|
|
814
|
-
)
|
|
815
|
-
)
|
|
816
|
-
]
|
|
817
|
-
)
|
|
970
|
+
false
|
|
971
|
+
)
|
|
972
|
+
)
|
|
973
|
+
]
|
|
974
|
+
)
|
|
818
975
|
),
|
|
819
976
|
ts.factory.createReturnStatement(
|
|
820
977
|
ts.factory.createCallExpression(
|
|
821
|
-
ts.factory.createPropertyAccessExpression(
|
|
822
|
-
ts.factory.createIdentifier('params'),
|
|
823
|
-
ts.factory.createIdentifier('toString'),
|
|
824
|
-
),
|
|
978
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('params'), ts.factory.createIdentifier('toString')),
|
|
825
979
|
undefined,
|
|
826
|
-
[]
|
|
827
|
-
)
|
|
828
|
-
)
|
|
980
|
+
[]
|
|
981
|
+
)
|
|
982
|
+
)
|
|
829
983
|
],
|
|
830
|
-
false
|
|
831
|
-
)
|
|
832
|
-
)
|
|
984
|
+
false
|
|
985
|
+
)
|
|
986
|
+
)
|
|
833
987
|
),
|
|
834
988
|
undefined,
|
|
835
|
-
[]
|
|
989
|
+
[]
|
|
836
990
|
),
|
|
837
991
|
undefined,
|
|
838
992
|
// JSON: stringify the data
|
|
839
993
|
ts.factory.createCallExpression(
|
|
840
|
-
ts.factory.createPropertyAccessExpression(
|
|
841
|
-
ts.factory.createIdentifier('JSON'),
|
|
842
|
-
ts.factory.createIdentifier('stringify'),
|
|
843
|
-
),
|
|
994
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('JSON'), ts.factory.createIdentifier('stringify')),
|
|
844
995
|
undefined,
|
|
845
|
-
[
|
|
846
|
-
|
|
847
|
-
ts.factory.createIdentifier('options'),
|
|
848
|
-
ts.factory.createIdentifier('data'),
|
|
849
|
-
),
|
|
850
|
-
],
|
|
851
|
-
),
|
|
996
|
+
[ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('data'))]
|
|
997
|
+
)
|
|
852
998
|
),
|
|
853
999
|
undefined,
|
|
854
|
-
ts.factory.createNull()
|
|
855
|
-
)
|
|
856
|
-
)
|
|
1000
|
+
ts.factory.createNull()
|
|
1001
|
+
)
|
|
1002
|
+
)
|
|
857
1003
|
],
|
|
858
|
-
ts.NodeFlags.Const
|
|
859
|
-
)
|
|
1004
|
+
ts.NodeFlags.Const
|
|
1005
|
+
)
|
|
860
1006
|
),
|
|
861
1007
|
// Make fetch request: merge base options with method, headers, and body
|
|
862
1008
|
ts.factory.createVariableStatement(
|
|
@@ -871,39 +1017,27 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
871
1017
|
ts.factory.createCallExpression(ts.factory.createIdentifier('fetch'), undefined, [
|
|
872
1018
|
ts.factory.createIdentifier('url'),
|
|
873
1019
|
ts.factory.createCallExpression(
|
|
874
|
-
ts.factory.createPropertyAccessExpression(
|
|
875
|
-
ts.factory.createIdentifier('Object'),
|
|
876
|
-
ts.factory.createIdentifier('assign'),
|
|
877
|
-
),
|
|
1020
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('Object'), ts.factory.createIdentifier('assign')),
|
|
878
1021
|
undefined,
|
|
879
1022
|
[
|
|
880
1023
|
ts.factory.createObjectLiteralExpression([], false),
|
|
881
1024
|
ts.factory.createIdentifier('baseOptions'),
|
|
882
1025
|
ts.factory.createObjectLiteralExpression(
|
|
883
1026
|
[
|
|
884
|
-
ts.factory.createShorthandPropertyAssignment(
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
),
|
|
888
|
-
ts.factory.createPropertyAssignment(
|
|
889
|
-
ts.factory.createIdentifier('headers'),
|
|
890
|
-
ts.factory.createIdentifier('headers'),
|
|
891
|
-
),
|
|
892
|
-
ts.factory.createPropertyAssignment(
|
|
893
|
-
ts.factory.createIdentifier('body'),
|
|
894
|
-
ts.factory.createIdentifier('body'),
|
|
895
|
-
),
|
|
1027
|
+
ts.factory.createShorthandPropertyAssignment(ts.factory.createIdentifier('method'), undefined),
|
|
1028
|
+
ts.factory.createPropertyAssignment(ts.factory.createIdentifier('headers'), ts.factory.createIdentifier('headers')),
|
|
1029
|
+
ts.factory.createPropertyAssignment(ts.factory.createIdentifier('body'), ts.factory.createIdentifier('body'))
|
|
896
1030
|
],
|
|
897
|
-
false
|
|
898
|
-
)
|
|
899
|
-
]
|
|
900
|
-
)
|
|
901
|
-
])
|
|
902
|
-
)
|
|
903
|
-
)
|
|
1031
|
+
false
|
|
1032
|
+
)
|
|
1033
|
+
]
|
|
1034
|
+
)
|
|
1035
|
+
])
|
|
1036
|
+
)
|
|
1037
|
+
)
|
|
904
1038
|
],
|
|
905
|
-
ts.NodeFlags.Const
|
|
906
|
-
)
|
|
1039
|
+
ts.NodeFlags.Const
|
|
1040
|
+
)
|
|
907
1041
|
),
|
|
908
1042
|
// Handle response through hook (allows subclasses to intercept and modify response)
|
|
909
1043
|
ts.factory.createVariableStatement(
|
|
@@ -916,80 +1050,62 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
916
1050
|
undefined,
|
|
917
1051
|
ts.factory.createAwaitExpression(
|
|
918
1052
|
ts.factory.createCallExpression(
|
|
919
|
-
ts.factory.createPropertyAccessExpression(
|
|
920
|
-
ts.factory.createThis(),
|
|
921
|
-
ts.factory.createIdentifier('handleResponse'),
|
|
922
|
-
),
|
|
1053
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createThis(), ts.factory.createIdentifier('handleResponse')),
|
|
923
1054
|
[ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('T'), undefined)],
|
|
924
1055
|
[
|
|
925
1056
|
ts.factory.createIdentifier('rawResponse'),
|
|
926
1057
|
ts.factory.createIdentifier('method'),
|
|
927
1058
|
ts.factory.createIdentifier('path'),
|
|
928
|
-
ts.factory.createIdentifier('options')
|
|
929
|
-
]
|
|
930
|
-
)
|
|
931
|
-
)
|
|
932
|
-
)
|
|
1059
|
+
ts.factory.createIdentifier('options')
|
|
1060
|
+
]
|
|
1061
|
+
)
|
|
1062
|
+
)
|
|
1063
|
+
)
|
|
933
1064
|
],
|
|
934
|
-
ts.NodeFlags.Const
|
|
935
|
-
)
|
|
1065
|
+
ts.NodeFlags.Const
|
|
1066
|
+
)
|
|
936
1067
|
),
|
|
937
1068
|
// Check response status
|
|
938
1069
|
ts.factory.createIfStatement(
|
|
939
1070
|
ts.factory.createPrefixUnaryExpression(
|
|
940
1071
|
ts.SyntaxKind.ExclamationToken,
|
|
941
|
-
ts.factory.createPropertyAccessExpression(
|
|
942
|
-
ts.factory.createIdentifier('response'),
|
|
943
|
-
ts.factory.createIdentifier('ok'),
|
|
944
|
-
),
|
|
1072
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('response'), ts.factory.createIdentifier('ok'))
|
|
945
1073
|
),
|
|
946
1074
|
ts.factory.createThrowStatement(
|
|
947
1075
|
ts.factory.createNewExpression(ts.factory.createIdentifier('Error'), undefined, [
|
|
948
1076
|
ts.factory.createTemplateExpression(ts.factory.createTemplateHead('HTTP ', 'HTTP '), [
|
|
949
1077
|
ts.factory.createTemplateSpan(
|
|
950
|
-
ts.factory.createPropertyAccessExpression(
|
|
951
|
-
|
|
952
|
-
ts.factory.createIdentifier('status'),
|
|
953
|
-
),
|
|
954
|
-
ts.factory.createTemplateMiddle(': ', ': '),
|
|
1078
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('response'), ts.factory.createIdentifier('status')),
|
|
1079
|
+
ts.factory.createTemplateMiddle(': ', ': ')
|
|
955
1080
|
),
|
|
956
1081
|
ts.factory.createTemplateSpan(
|
|
957
|
-
ts.factory.createPropertyAccessExpression(
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
),
|
|
963
|
-
]),
|
|
964
|
-
]),
|
|
1082
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('response'), ts.factory.createIdentifier('statusText')),
|
|
1083
|
+
ts.factory.createTemplateTail('', '')
|
|
1084
|
+
)
|
|
1085
|
+
])
|
|
1086
|
+
])
|
|
965
1087
|
),
|
|
966
|
-
undefined
|
|
1088
|
+
undefined
|
|
967
1089
|
),
|
|
968
1090
|
// Return parsed JSON
|
|
969
1091
|
ts.factory.createReturnStatement(
|
|
970
1092
|
ts.factory.createAwaitExpression(
|
|
971
1093
|
ts.factory.createCallExpression(
|
|
972
|
-
ts.factory.createPropertyAccessExpression(
|
|
973
|
-
ts.factory.createIdentifier('response'),
|
|
974
|
-
ts.factory.createIdentifier('json'),
|
|
975
|
-
),
|
|
1094
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('response'), ts.factory.createIdentifier('json')),
|
|
976
1095
|
undefined,
|
|
977
|
-
[]
|
|
978
|
-
)
|
|
979
|
-
)
|
|
980
|
-
)
|
|
1096
|
+
[]
|
|
1097
|
+
)
|
|
1098
|
+
)
|
|
1099
|
+
)
|
|
981
1100
|
],
|
|
982
|
-
true
|
|
983
|
-
)
|
|
1101
|
+
true
|
|
1102
|
+
)
|
|
984
1103
|
);
|
|
985
1104
|
}
|
|
986
1105
|
|
|
987
|
-
private buildClientMethods(
|
|
988
|
-
openapi: OpenApiSpecType,
|
|
989
|
-
schemas: Record<string, ts.VariableStatement>,
|
|
990
|
-
): ts.MethodDeclaration[] {
|
|
1106
|
+
private buildClientMethods(openapi: OpenApiSpecType, schemas: Record<string, ts.VariableStatement>): ts.MethodDeclaration[] {
|
|
991
1107
|
// Track operation IDs to detect duplicates
|
|
992
|
-
const operationIdMap = new Map<string, {method: string; path: string}[]>();
|
|
1108
|
+
const operationIdMap = new Map<string, { method: string; path: string }[]>();
|
|
993
1109
|
|
|
994
1110
|
// First pass: collect all operation IDs and their methods/paths
|
|
995
1111
|
Object.entries(openapi.paths).forEach(([path, pathItem]) => {
|
|
@@ -1001,9 +1117,9 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1001
1117
|
const operationId = safeMethodSchema.operationId;
|
|
1002
1118
|
const existing = operationIdMap.get(operationId);
|
|
1003
1119
|
if (existing) {
|
|
1004
|
-
existing.push({method, path});
|
|
1120
|
+
existing.push({ method, path });
|
|
1005
1121
|
} else {
|
|
1006
|
-
operationIdMap.set(operationId, [{method, path}]);
|
|
1122
|
+
operationIdMap.set(operationId, [{ method, path }]);
|
|
1007
1123
|
}
|
|
1008
1124
|
}
|
|
1009
1125
|
});
|
|
@@ -1035,7 +1151,7 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1035
1151
|
// This will be handled in transformOperationName
|
|
1036
1152
|
const modifiedSchema = {
|
|
1037
1153
|
...safeMethodSchema,
|
|
1038
|
-
operationId: `${operationId}_${methodLower}
|
|
1154
|
+
operationId: `${operationId}_${methodLower}`
|
|
1039
1155
|
};
|
|
1040
1156
|
return this.buildEndpointMethod(method, path, modifiedSchema, schemas);
|
|
1041
1157
|
}
|
|
@@ -1062,9 +1178,9 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1062
1178
|
operationId,
|
|
1063
1179
|
method,
|
|
1064
1180
|
path,
|
|
1065
|
-
...(schema.tags !== undefined && {tags: schema.tags}),
|
|
1066
|
-
...(schema.summary !== undefined && {summary: schema.summary}),
|
|
1067
|
-
...(schema.description !== undefined && {description: schema.description})
|
|
1181
|
+
...(schema.tags !== undefined && { tags: schema.tags }),
|
|
1182
|
+
...(schema.summary !== undefined && { summary: schema.summary }),
|
|
1183
|
+
...(schema.description !== undefined && { description: schema.description })
|
|
1068
1184
|
};
|
|
1069
1185
|
transformed = this.operationNameTransformer(details);
|
|
1070
1186
|
} else if (this.namingConvention) {
|
|
@@ -1089,16 +1205,8 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1089
1205
|
return this.typeBuilder.sanitizeIdentifier(transformed);
|
|
1090
1206
|
}
|
|
1091
1207
|
|
|
1092
|
-
private buildEndpointMethod(
|
|
1093
|
-
|
|
1094
|
-
path: string,
|
|
1095
|
-
schema: MethodSchemaType,
|
|
1096
|
-
schemas: Record<string, ts.VariableStatement>,
|
|
1097
|
-
): ts.MethodDeclaration {
|
|
1098
|
-
const {parameters, pathParams, queryParams, hasRequestBody, contentType} = this.buildMethodParameters(
|
|
1099
|
-
schema,
|
|
1100
|
-
schemas,
|
|
1101
|
-
);
|
|
1208
|
+
private buildEndpointMethod(method: string, path: string, schema: MethodSchemaType, schemas: Record<string, ts.VariableStatement>): ts.MethodDeclaration {
|
|
1209
|
+
const { parameters, pathParams, queryParams, hasRequestBody, contentType } = this.buildMethodParameters(schema, schemas);
|
|
1102
1210
|
const responseType = this.getResponseType(schema, schemas);
|
|
1103
1211
|
const responseSchema = this.getResponseSchema(schema, schemas);
|
|
1104
1212
|
|
|
@@ -1113,40 +1221,28 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1113
1221
|
? ts.factory.createObjectLiteralExpression(
|
|
1114
1222
|
queryParams.map((param) => {
|
|
1115
1223
|
const paramName = this.typeBuilder.sanitizeIdentifier(param.name);
|
|
1116
|
-
return ts.factory.createPropertyAssignment(
|
|
1117
|
-
ts.factory.createStringLiteral(param.name, true),
|
|
1118
|
-
ts.factory.createIdentifier(paramName),
|
|
1119
|
-
);
|
|
1224
|
+
return ts.factory.createPropertyAssignment(ts.factory.createStringLiteral(param.name, true), ts.factory.createIdentifier(paramName));
|
|
1120
1225
|
}),
|
|
1121
|
-
false
|
|
1226
|
+
false
|
|
1122
1227
|
)
|
|
1123
1228
|
: undefined;
|
|
1124
1229
|
|
|
1125
1230
|
// Build request body
|
|
1126
|
-
const requestBodyExpression: ts.Expression | undefined = hasRequestBody
|
|
1127
|
-
? ts.factory.createIdentifier('body')
|
|
1128
|
-
: undefined;
|
|
1231
|
+
const requestBodyExpression: ts.Expression | undefined = hasRequestBody ? ts.factory.createIdentifier('body') : undefined;
|
|
1129
1232
|
|
|
1130
1233
|
// Build options object for makeRequest
|
|
1131
1234
|
const optionsProps: ts.ObjectLiteralElementLike[] = [];
|
|
1132
1235
|
if (queryParamsExpression) {
|
|
1133
|
-
optionsProps.push(
|
|
1134
|
-
ts.factory.createPropertyAssignment(ts.factory.createIdentifier('params'), queryParamsExpression),
|
|
1135
|
-
);
|
|
1236
|
+
optionsProps.push(ts.factory.createPropertyAssignment(ts.factory.createIdentifier('params'), queryParamsExpression));
|
|
1136
1237
|
}
|
|
1238
|
+
|
|
1137
1239
|
if (requestBodyExpression) {
|
|
1138
|
-
optionsProps.push(
|
|
1139
|
-
ts.factory.createPropertyAssignment(ts.factory.createIdentifier('data'), requestBodyExpression),
|
|
1140
|
-
);
|
|
1240
|
+
optionsProps.push(ts.factory.createPropertyAssignment(ts.factory.createIdentifier('data'), requestBodyExpression));
|
|
1141
1241
|
}
|
|
1242
|
+
|
|
1142
1243
|
// Add content type if it's form-urlencoded
|
|
1143
1244
|
if (hasRequestBody && contentType === 'application/x-www-form-urlencoded') {
|
|
1144
|
-
optionsProps.push(
|
|
1145
|
-
ts.factory.createPropertyAssignment(
|
|
1146
|
-
ts.factory.createIdentifier('contentType'),
|
|
1147
|
-
ts.factory.createStringLiteral('application/x-www-form-urlencoded', true),
|
|
1148
|
-
),
|
|
1149
|
-
);
|
|
1245
|
+
optionsProps.push(ts.factory.createPropertyAssignment(ts.factory.createIdentifier('contentType'), ts.factory.createStringLiteral('application/x-www-form-urlencoded', true)));
|
|
1150
1246
|
}
|
|
1151
1247
|
|
|
1152
1248
|
const optionsExpression = ts.factory.createObjectLiteralExpression(optionsProps, false);
|
|
@@ -1155,18 +1251,98 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1155
1251
|
const makeRequestCall = ts.factory.createCallExpression(
|
|
1156
1252
|
ts.factory.createPropertyAccessExpression(ts.factory.createThis(), ts.factory.createIdentifier('makeRequest')),
|
|
1157
1253
|
undefined,
|
|
1158
|
-
[ts.factory.createStringLiteral(method.toUpperCase(), true), pathExpression, optionsExpression]
|
|
1254
|
+
[ts.factory.createStringLiteral(method.toUpperCase(), true), pathExpression, optionsExpression]
|
|
1159
1255
|
);
|
|
1160
1256
|
|
|
1161
|
-
// Add Zod validation if we have a response schema
|
|
1162
1257
|
if (responseSchema) {
|
|
1163
|
-
const
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1258
|
+
const schemaName = responseSchema.text;
|
|
1259
|
+
const schemaNameLower = schemaName.charAt(0).toLowerCase() + schemaName.slice(1);
|
|
1260
|
+
const parsedVarName = `parsed${schemaName}`;
|
|
1261
|
+
|
|
1262
|
+
// const response = await this.makeRequest(...)
|
|
1263
|
+
statements.push(
|
|
1264
|
+
ts.factory.createVariableStatement(
|
|
1265
|
+
undefined,
|
|
1266
|
+
ts.factory.createVariableDeclarationList(
|
|
1267
|
+
[ts.factory.createVariableDeclaration('response', undefined, undefined, ts.factory.createAwaitExpression(makeRequestCall))],
|
|
1268
|
+
ts.NodeFlags.Const
|
|
1269
|
+
)
|
|
1270
|
+
)
|
|
1167
1271
|
);
|
|
1168
1272
|
|
|
1169
|
-
|
|
1273
|
+
// const parsed{Name} = {Schema}.safeParse(response)
|
|
1274
|
+
statements.push(
|
|
1275
|
+
ts.factory.createVariableStatement(
|
|
1276
|
+
undefined,
|
|
1277
|
+
ts.factory.createVariableDeclarationList(
|
|
1278
|
+
[
|
|
1279
|
+
ts.factory.createVariableDeclaration(
|
|
1280
|
+
parsedVarName,
|
|
1281
|
+
undefined,
|
|
1282
|
+
undefined,
|
|
1283
|
+
ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(responseSchema, ts.factory.createIdentifier('safeParse')), undefined, [
|
|
1284
|
+
ts.factory.createIdentifier('response')
|
|
1285
|
+
])
|
|
1286
|
+
)
|
|
1287
|
+
],
|
|
1288
|
+
ts.NodeFlags.Const
|
|
1289
|
+
)
|
|
1290
|
+
)
|
|
1291
|
+
);
|
|
1292
|
+
|
|
1293
|
+
// if (!parsed{Name}.success) { throw new ResponseValidationError<{Type}>(...) }
|
|
1294
|
+
statements.push(
|
|
1295
|
+
ts.factory.createIfStatement(
|
|
1296
|
+
ts.factory.createPrefixUnaryExpression(ts.SyntaxKind.ExclamationToken, ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(parsedVarName), 'success')),
|
|
1297
|
+
ts.factory.createBlock(
|
|
1298
|
+
[
|
|
1299
|
+
ts.factory.createThrowStatement(
|
|
1300
|
+
ts.factory.createNewExpression(
|
|
1301
|
+
ts.factory.createIdentifier('ResponseValidationError'),
|
|
1302
|
+
[ts.factory.createTypeReferenceNode(schemaName)],
|
|
1303
|
+
[
|
|
1304
|
+
ts.factory.createTemplateExpression(ts.factory.createTemplateHead(`Invalid ${schemaNameLower}: `), [
|
|
1305
|
+
ts.factory.createTemplateSpan(
|
|
1306
|
+
ts.factory.createCallExpression(
|
|
1307
|
+
ts.factory.createPropertyAccessExpression(
|
|
1308
|
+
ts.factory.createCallExpression(
|
|
1309
|
+
ts.factory.createPropertyAccessExpression(
|
|
1310
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(parsedVarName), 'error'), 'errors'),
|
|
1311
|
+
'map'
|
|
1312
|
+
),
|
|
1313
|
+
undefined,
|
|
1314
|
+
[
|
|
1315
|
+
ts.factory.createArrowFunction(
|
|
1316
|
+
undefined,
|
|
1317
|
+
undefined,
|
|
1318
|
+
[ts.factory.createParameterDeclaration(undefined, undefined, 'error')],
|
|
1319
|
+
undefined,
|
|
1320
|
+
ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
|
|
1321
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('error'), 'message')
|
|
1322
|
+
)
|
|
1323
|
+
]
|
|
1324
|
+
),
|
|
1325
|
+
'join'
|
|
1326
|
+
),
|
|
1327
|
+
undefined,
|
|
1328
|
+
[ts.factory.createStringLiteral(', ', true)]
|
|
1329
|
+
),
|
|
1330
|
+
ts.factory.createTemplateTail('')
|
|
1331
|
+
)
|
|
1332
|
+
]),
|
|
1333
|
+
ts.factory.createIdentifier('response'),
|
|
1334
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(parsedVarName), 'error')
|
|
1335
|
+
]
|
|
1336
|
+
)
|
|
1337
|
+
)
|
|
1338
|
+
],
|
|
1339
|
+
true
|
|
1340
|
+
)
|
|
1341
|
+
)
|
|
1342
|
+
);
|
|
1343
|
+
|
|
1344
|
+
// return parsed{Name}.data
|
|
1345
|
+
statements.push(ts.factory.createReturnStatement(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(parsedVarName), 'data')));
|
|
1170
1346
|
} else {
|
|
1171
1347
|
statements.push(ts.factory.createReturnStatement(ts.factory.createAwaitExpression(makeRequestCall)));
|
|
1172
1348
|
}
|
|
@@ -1181,7 +1357,7 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1181
1357
|
undefined,
|
|
1182
1358
|
parameters,
|
|
1183
1359
|
responseType,
|
|
1184
|
-
ts.factory.createBlock(statements, true)
|
|
1360
|
+
ts.factory.createBlock(statements, true)
|
|
1185
1361
|
);
|
|
1186
1362
|
|
|
1187
1363
|
// Add JSDoc comment if summary or description exists
|
|
@@ -1190,22 +1366,17 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1190
1366
|
if (jsdocComment) {
|
|
1191
1367
|
// addSyntheticLeadingComment expects the comment content without delimiters
|
|
1192
1368
|
// and will wrap it in /** */ for JSDoc-style comments
|
|
1193
|
-
ts.addSyntheticLeadingComment(
|
|
1194
|
-
methodDeclaration,
|
|
1195
|
-
ts.SyntaxKind.MultiLineCommentTrivia,
|
|
1196
|
-
`*\n${jsdocComment}\n `,
|
|
1197
|
-
true,
|
|
1198
|
-
);
|
|
1369
|
+
ts.addSyntheticLeadingComment(methodDeclaration, ts.SyntaxKind.MultiLineCommentTrivia, `*\n${jsdocComment}\n `, true);
|
|
1199
1370
|
}
|
|
1200
1371
|
|
|
1201
1372
|
return methodDeclaration;
|
|
1202
1373
|
}
|
|
1203
1374
|
|
|
1204
|
-
private buildPathExpression(path: string, pathParams: {name: string; type: string}[]): ts.Expression {
|
|
1375
|
+
private buildPathExpression(path: string, pathParams: { name: string; type: string }[]): ts.Expression {
|
|
1205
1376
|
// Replace {param} with ${param} for template literal
|
|
1206
1377
|
const pathParamNames = new Set(pathParams.map((p) => p.name));
|
|
1207
1378
|
const pathParamRegex = /\{([^}]+)\}/g;
|
|
1208
|
-
const matches: {index: number; length: number; name: string}[] = [];
|
|
1379
|
+
const matches: { index: number; length: number; name: string }[] = [];
|
|
1209
1380
|
|
|
1210
1381
|
// Find all path parameters
|
|
1211
1382
|
for (const match of path.matchAll(pathParamRegex)) {
|
|
@@ -1215,7 +1386,7 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1215
1386
|
matches.push({
|
|
1216
1387
|
index: match.index,
|
|
1217
1388
|
length: match[0].length,
|
|
1218
|
-
name: paramName
|
|
1389
|
+
name: paramName
|
|
1219
1390
|
});
|
|
1220
1391
|
}
|
|
1221
1392
|
}
|
|
@@ -1236,19 +1407,9 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1236
1407
|
const after = isLast ? path.substring(m.index + m.length) : '';
|
|
1237
1408
|
|
|
1238
1409
|
if (isLast) {
|
|
1239
|
-
templateSpans.push(
|
|
1240
|
-
ts.factory.createTemplateSpan(
|
|
1241
|
-
ts.factory.createIdentifier(sanitizedName),
|
|
1242
|
-
ts.factory.createTemplateTail(after, after),
|
|
1243
|
-
),
|
|
1244
|
-
);
|
|
1410
|
+
templateSpans.push(ts.factory.createTemplateSpan(ts.factory.createIdentifier(sanitizedName), ts.factory.createTemplateTail(after, after)));
|
|
1245
1411
|
} else {
|
|
1246
|
-
templateSpans.push(
|
|
1247
|
-
ts.factory.createTemplateSpan(
|
|
1248
|
-
ts.factory.createIdentifier(sanitizedName),
|
|
1249
|
-
ts.factory.createTemplateMiddle(before, before),
|
|
1250
|
-
),
|
|
1251
|
-
);
|
|
1412
|
+
templateSpans.push(ts.factory.createTemplateSpan(ts.factory.createIdentifier(sanitizedName), ts.factory.createTemplateMiddle(before, before)));
|
|
1252
1413
|
}
|
|
1253
1414
|
|
|
1254
1415
|
lastIndex = m.index + m.length;
|
|
@@ -1258,23 +1419,24 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1258
1419
|
if (!firstMatch) {
|
|
1259
1420
|
return ts.factory.createStringLiteral(path, true);
|
|
1260
1421
|
}
|
|
1422
|
+
|
|
1261
1423
|
const head = path.substring(0, firstMatch.index);
|
|
1262
1424
|
return ts.factory.createTemplateExpression(ts.factory.createTemplateHead(head, head), templateSpans);
|
|
1263
1425
|
}
|
|
1264
1426
|
|
|
1265
1427
|
private buildMethodParameters(
|
|
1266
1428
|
schema: MethodSchemaType,
|
|
1267
|
-
schemas: Record<string, ts.VariableStatement
|
|
1429
|
+
schemas: Record<string, ts.VariableStatement>
|
|
1268
1430
|
): {
|
|
1269
1431
|
parameters: ts.ParameterDeclaration[];
|
|
1270
|
-
pathParams: {name: string; type: string}[];
|
|
1271
|
-
queryParams: {name: string; type: string; required: boolean}[];
|
|
1432
|
+
pathParams: { name: string; type: string }[];
|
|
1433
|
+
queryParams: { name: string; type: string; required: boolean }[];
|
|
1272
1434
|
hasRequestBody: boolean;
|
|
1273
1435
|
contentType: string;
|
|
1274
1436
|
} {
|
|
1275
1437
|
const parameters: ts.ParameterDeclaration[] = [];
|
|
1276
|
-
const pathParams: {name: string; type: string}[] = [];
|
|
1277
|
-
const queryParams: {name: string; type: string; required: boolean}[] = [];
|
|
1438
|
+
const pathParams: { name: string; type: string }[] = [];
|
|
1439
|
+
const queryParams: { name: string; type: string; required: boolean }[] = [];
|
|
1278
1440
|
|
|
1279
1441
|
// Extract path and query parameters
|
|
1280
1442
|
if (schema.parameters) {
|
|
@@ -1283,7 +1445,7 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1283
1445
|
const paramType = this.getParameterType(param.schema);
|
|
1284
1446
|
|
|
1285
1447
|
if (param.in === 'path') {
|
|
1286
|
-
pathParams.push({name: param.name, type: paramType});
|
|
1448
|
+
pathParams.push({ name: param.name, type: paramType });
|
|
1287
1449
|
parameters.push(this.typeBuilder.createParameter(paramName, paramType, undefined, false));
|
|
1288
1450
|
} else if (param.in === 'query') {
|
|
1289
1451
|
// Improve type inference for query parameters
|
|
@@ -1291,24 +1453,26 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1291
1453
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
1292
1454
|
typeof param.schema === 'object' && param.schema !== null
|
|
1293
1455
|
? (() => {
|
|
1294
|
-
const paramSchema = param.schema as {type?: string; items?: unknown; enum?: unknown[]};
|
|
1456
|
+
const paramSchema = param.schema as { type?: string; items?: unknown; enum?: unknown[] };
|
|
1295
1457
|
// eslint-disable-next-line @typescript-eslint/dot-notation
|
|
1296
1458
|
if (paramSchema['type'] === 'array' && paramSchema['items']) {
|
|
1297
1459
|
// eslint-disable-next-line @typescript-eslint/dot-notation
|
|
1298
|
-
const itemSchema = paramSchema['items'] as {type?: string};
|
|
1460
|
+
const itemSchema = paramSchema['items'] as { type?: string };
|
|
1299
1461
|
// eslint-disable-next-line @typescript-eslint/dot-notation
|
|
1300
1462
|
if (itemSchema['type'] === 'string') {
|
|
1301
1463
|
return 'string[]' as const;
|
|
1302
1464
|
}
|
|
1465
|
+
|
|
1303
1466
|
// eslint-disable-next-line @typescript-eslint/dot-notation
|
|
1304
1467
|
if (itemSchema['type'] === 'number' || itemSchema['type'] === 'integer') {
|
|
1305
1468
|
return 'number[]' as const;
|
|
1306
1469
|
}
|
|
1307
1470
|
}
|
|
1471
|
+
|
|
1308
1472
|
return paramType;
|
|
1309
1473
|
})()
|
|
1310
1474
|
: paramType;
|
|
1311
|
-
queryParams.push({name: param.name, type: queryParamType, required: param.required ?? false});
|
|
1475
|
+
queryParams.push({ name: param.name, type: queryParamType, required: param.required ?? false });
|
|
1312
1476
|
parameters.push(this.typeBuilder.createParameter(paramName, queryParamType, undefined, !param.required));
|
|
1313
1477
|
}
|
|
1314
1478
|
}
|
|
@@ -1333,6 +1497,7 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1333
1497
|
const refName = ref.split('/').pop() ?? 'unknown';
|
|
1334
1498
|
return this.typeBuilder.sanitizeIdentifier(refName);
|
|
1335
1499
|
}
|
|
1500
|
+
|
|
1336
1501
|
// Fallback to getSchemaTypeName for non-ref schemas
|
|
1337
1502
|
return this.getSchemaTypeName(requestBodySchema, schemas);
|
|
1338
1503
|
})()
|
|
@@ -1342,12 +1507,9 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1342
1507
|
}
|
|
1343
1508
|
|
|
1344
1509
|
// Determine content type for request body
|
|
1345
|
-
const contentType =
|
|
1346
|
-
hasRequestBody && schema.requestBody?.content?.['application/x-www-form-urlencoded']
|
|
1347
|
-
? 'application/x-www-form-urlencoded'
|
|
1348
|
-
: 'application/json';
|
|
1510
|
+
const contentType = hasRequestBody && schema.requestBody?.content?.['application/x-www-form-urlencoded'] ? 'application/x-www-form-urlencoded' : 'application/json';
|
|
1349
1511
|
|
|
1350
|
-
return {parameters, pathParams, queryParams, hasRequestBody, contentType};
|
|
1512
|
+
return { parameters, pathParams, queryParams, hasRequestBody, contentType };
|
|
1351
1513
|
}
|
|
1352
1514
|
|
|
1353
1515
|
private getParameterType(schema: unknown): string {
|
|
@@ -1397,7 +1559,7 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1397
1559
|
return 'unknown';
|
|
1398
1560
|
}
|
|
1399
1561
|
|
|
1400
|
-
const schemaObj = schema as {$ref?: string; type?: string; items?: unknown};
|
|
1562
|
+
const schemaObj = schema as { $ref?: string; type?: string; items?: unknown };
|
|
1401
1563
|
|
|
1402
1564
|
// Check for $ref using both dot notation and bracket notation
|
|
1403
1565
|
// eslint-disable-next-line @typescript-eslint/dot-notation
|
|
@@ -1427,10 +1589,7 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1427
1589
|
}
|
|
1428
1590
|
}
|
|
1429
1591
|
|
|
1430
|
-
private getResponseSchema(
|
|
1431
|
-
schema: MethodSchemaType,
|
|
1432
|
-
_schemas: Record<string, ts.VariableStatement>,
|
|
1433
|
-
): ts.Identifier | undefined {
|
|
1592
|
+
private getResponseSchema(schema: MethodSchemaType, _schemas: Record<string, ts.VariableStatement>): ts.Identifier | undefined {
|
|
1434
1593
|
// Try to find a 200 response first, then 201, then default
|
|
1435
1594
|
const response200 = schema.responses?.['200'];
|
|
1436
1595
|
const response201 = schema.responses?.['201'];
|
|
@@ -1445,7 +1604,7 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1445
1604
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
1446
1605
|
if (responseSchema !== null && typeof responseSchema === 'object' && '$ref' in responseSchema) {
|
|
1447
1606
|
// eslint-disable-next-line @typescript-eslint/dot-notation
|
|
1448
|
-
const ref = (responseSchema as {$ref: string})['$ref'];
|
|
1607
|
+
const ref = (responseSchema as { $ref: string })['$ref'];
|
|
1449
1608
|
if (typeof ref === 'string') {
|
|
1450
1609
|
const refName = ref.split('/').pop() ?? 'unknown';
|
|
1451
1610
|
return ts.factory.createIdentifier(this.typeBuilder.sanitizeIdentifier(refName));
|
|
@@ -1457,10 +1616,7 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1457
1616
|
return undefined;
|
|
1458
1617
|
}
|
|
1459
1618
|
|
|
1460
|
-
private getResponseType(
|
|
1461
|
-
schema: MethodSchemaType,
|
|
1462
|
-
schemas: Record<string, ts.VariableStatement>,
|
|
1463
|
-
): ts.TypeNode | undefined {
|
|
1619
|
+
private getResponseType(schema: MethodSchemaType, schemas: Record<string, ts.VariableStatement>): ts.TypeNode | undefined {
|
|
1464
1620
|
// Try to find a 200 response first, then 201, then default
|
|
1465
1621
|
const response200 = schema.responses?.['200'];
|
|
1466
1622
|
const response201 = schema.responses?.['201'];
|
|
@@ -1468,9 +1624,7 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1468
1624
|
|
|
1469
1625
|
const response = response200 ?? response201 ?? responseDefault;
|
|
1470
1626
|
if (!response?.content?.['application/json']?.schema) {
|
|
1471
|
-
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
|
|
1472
|
-
ts.factory.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword),
|
|
1473
|
-
]);
|
|
1627
|
+
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [ts.factory.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword)]);
|
|
1474
1628
|
}
|
|
1475
1629
|
|
|
1476
1630
|
const responseSchema = response.content['application/json'].schema;
|
|
@@ -1485,15 +1639,12 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1485
1639
|
if (schemas[sanitizedItemTypeName]) {
|
|
1486
1640
|
// Use the type alias directly (it already uses z.infer)
|
|
1487
1641
|
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
|
|
1488
|
-
ts.factory.createArrayTypeNode(
|
|
1489
|
-
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(sanitizedItemTypeName), undefined),
|
|
1490
|
-
),
|
|
1642
|
+
ts.factory.createArrayTypeNode(ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(sanitizedItemTypeName), undefined))
|
|
1491
1643
|
]);
|
|
1492
1644
|
}
|
|
1645
|
+
|
|
1493
1646
|
// If it's a primitive array, use the type name as-is
|
|
1494
|
-
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
|
|
1495
|
-
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(typeName), undefined),
|
|
1496
|
-
]);
|
|
1647
|
+
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(typeName), undefined)]);
|
|
1497
1648
|
}
|
|
1498
1649
|
|
|
1499
1650
|
const sanitizedTypeName = this.typeBuilder.sanitizeIdentifier(typeName);
|
|
@@ -1502,14 +1653,12 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1502
1653
|
if (schemas[sanitizedTypeName]) {
|
|
1503
1654
|
// Use the type name directly (we have a type alias that already uses z.infer)
|
|
1504
1655
|
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
|
|
1505
|
-
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(sanitizedTypeName), undefined)
|
|
1656
|
+
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(sanitizedTypeName), undefined)
|
|
1506
1657
|
]);
|
|
1507
1658
|
}
|
|
1508
1659
|
|
|
1509
1660
|
// For primitive types and Record types, use the type name directly
|
|
1510
|
-
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
|
|
1511
|
-
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(typeName), undefined),
|
|
1512
|
-
]);
|
|
1661
|
+
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(typeName), undefined)]);
|
|
1513
1662
|
}
|
|
1514
1663
|
|
|
1515
1664
|
private buildServerConfiguration(openapi: OpenApiSpecType): ts.Statement[] {
|
|
@@ -1523,21 +1672,15 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1523
1672
|
|
|
1524
1673
|
// Build server configuration array
|
|
1525
1674
|
const serverConfigElements = servers.map((server) => {
|
|
1526
|
-
const properties: ts.PropertyAssignment[] = [
|
|
1527
|
-
ts.factory.createPropertyAssignment('url', ts.factory.createStringLiteral(server.url, true)),
|
|
1528
|
-
];
|
|
1675
|
+
const properties: ts.PropertyAssignment[] = [ts.factory.createPropertyAssignment('url', ts.factory.createStringLiteral(server.url, true))];
|
|
1529
1676
|
|
|
1530
1677
|
if (server.description) {
|
|
1531
|
-
properties.push(
|
|
1532
|
-
ts.factory.createPropertyAssignment('description', ts.factory.createStringLiteral(server.description, true)),
|
|
1533
|
-
);
|
|
1678
|
+
properties.push(ts.factory.createPropertyAssignment('description', ts.factory.createStringLiteral(server.description, true)));
|
|
1534
1679
|
}
|
|
1535
1680
|
|
|
1536
1681
|
if (server.variables && Object.keys(server.variables).length > 0) {
|
|
1537
1682
|
const variableProperties = Object.entries(server.variables).map(([varName, varDef]) => {
|
|
1538
|
-
const varProps: ts.PropertyAssignment[] = [
|
|
1539
|
-
ts.factory.createPropertyAssignment('default', ts.factory.createStringLiteral(varDef.default, true)),
|
|
1540
|
-
];
|
|
1683
|
+
const varProps: ts.PropertyAssignment[] = [ts.factory.createPropertyAssignment('default', ts.factory.createStringLiteral(varDef.default, true))];
|
|
1541
1684
|
|
|
1542
1685
|
if (varDef.enum && varDef.enum.length > 0) {
|
|
1543
1686
|
varProps.push(
|
|
@@ -1545,30 +1688,20 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1545
1688
|
'enum',
|
|
1546
1689
|
ts.factory.createArrayLiteralExpression(
|
|
1547
1690
|
varDef.enum.map((val) => ts.factory.createStringLiteral(val, true)),
|
|
1548
|
-
false
|
|
1549
|
-
)
|
|
1550
|
-
)
|
|
1691
|
+
false
|
|
1692
|
+
)
|
|
1693
|
+
)
|
|
1551
1694
|
);
|
|
1552
1695
|
}
|
|
1553
1696
|
|
|
1554
1697
|
if (varDef.description) {
|
|
1555
|
-
varProps.push(
|
|
1556
|
-
ts.factory.createPropertyAssignment(
|
|
1557
|
-
'description',
|
|
1558
|
-
ts.factory.createStringLiteral(varDef.description, true),
|
|
1559
|
-
),
|
|
1560
|
-
);
|
|
1698
|
+
varProps.push(ts.factory.createPropertyAssignment('description', ts.factory.createStringLiteral(varDef.description, true)));
|
|
1561
1699
|
}
|
|
1562
1700
|
|
|
1563
1701
|
return ts.factory.createPropertyAssignment(varName, ts.factory.createObjectLiteralExpression(varProps, true));
|
|
1564
1702
|
});
|
|
1565
1703
|
|
|
1566
|
-
properties.push(
|
|
1567
|
-
ts.factory.createPropertyAssignment(
|
|
1568
|
-
'variables',
|
|
1569
|
-
ts.factory.createObjectLiteralExpression(variableProperties, true),
|
|
1570
|
-
),
|
|
1571
|
-
);
|
|
1704
|
+
properties.push(ts.factory.createPropertyAssignment('variables', ts.factory.createObjectLiteralExpression(variableProperties, true)));
|
|
1572
1705
|
}
|
|
1573
1706
|
|
|
1574
1707
|
return ts.factory.createObjectLiteralExpression(properties, true);
|
|
@@ -1584,12 +1717,12 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1584
1717
|
ts.factory.createIdentifier('serverConfigurations'),
|
|
1585
1718
|
undefined,
|
|
1586
1719
|
undefined,
|
|
1587
|
-
ts.factory.createArrayLiteralExpression(serverConfigElements, false)
|
|
1588
|
-
)
|
|
1720
|
+
ts.factory.createArrayLiteralExpression(serverConfigElements, false)
|
|
1721
|
+
)
|
|
1589
1722
|
],
|
|
1590
|
-
ts.NodeFlags.Const
|
|
1591
|
-
)
|
|
1592
|
-
)
|
|
1723
|
+
ts.NodeFlags.Const
|
|
1724
|
+
)
|
|
1725
|
+
)
|
|
1593
1726
|
);
|
|
1594
1727
|
|
|
1595
1728
|
// Export default base URL (first server with default variables)
|
|
@@ -1599,17 +1732,10 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1599
1732
|
ts.factory.createVariableStatement(
|
|
1600
1733
|
[ts.factory.createToken(ts.SyntaxKind.ExportKeyword)],
|
|
1601
1734
|
ts.factory.createVariableDeclarationList(
|
|
1602
|
-
[
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
undefined,
|
|
1607
|
-
ts.factory.createStringLiteral(defaultBaseUrl, true),
|
|
1608
|
-
),
|
|
1609
|
-
],
|
|
1610
|
-
ts.NodeFlags.Const,
|
|
1611
|
-
),
|
|
1612
|
-
),
|
|
1735
|
+
[ts.factory.createVariableDeclaration(ts.factory.createIdentifier('defaultBaseUrl'), undefined, undefined, ts.factory.createStringLiteral(defaultBaseUrl, true))],
|
|
1736
|
+
ts.NodeFlags.Const
|
|
1737
|
+
)
|
|
1738
|
+
)
|
|
1613
1739
|
);
|
|
1614
1740
|
|
|
1615
1741
|
// Build ClientOptions type
|
|
@@ -1618,13 +1744,13 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1618
1744
|
undefined,
|
|
1619
1745
|
ts.factory.createIdentifier('baseUrl'),
|
|
1620
1746
|
ts.factory.createToken(ts.SyntaxKind.QuestionToken),
|
|
1621
|
-
ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword)
|
|
1747
|
+
ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword)
|
|
1622
1748
|
),
|
|
1623
1749
|
ts.factory.createPropertySignature(
|
|
1624
1750
|
undefined,
|
|
1625
1751
|
ts.factory.createIdentifier('serverIndex'),
|
|
1626
1752
|
ts.factory.createToken(ts.SyntaxKind.QuestionToken),
|
|
1627
|
-
ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword)
|
|
1753
|
+
ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword)
|
|
1628
1754
|
),
|
|
1629
1755
|
ts.factory.createPropertySignature(
|
|
1630
1756
|
undefined,
|
|
@@ -1632,9 +1758,9 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1632
1758
|
ts.factory.createToken(ts.SyntaxKind.QuestionToken),
|
|
1633
1759
|
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Record'), [
|
|
1634
1760
|
ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
|
|
1635
|
-
ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword)
|
|
1636
|
-
])
|
|
1637
|
-
)
|
|
1761
|
+
ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword)
|
|
1762
|
+
])
|
|
1763
|
+
)
|
|
1638
1764
|
];
|
|
1639
1765
|
|
|
1640
1766
|
statements.push(
|
|
@@ -1642,8 +1768,8 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1642
1768
|
[ts.factory.createToken(ts.SyntaxKind.ExportKeyword)],
|
|
1643
1769
|
ts.factory.createIdentifier('ClientOptions'),
|
|
1644
1770
|
undefined,
|
|
1645
|
-
ts.factory.createTypeLiteralNode(optionProperties)
|
|
1646
|
-
)
|
|
1771
|
+
ts.factory.createTypeLiteralNode(optionProperties)
|
|
1772
|
+
)
|
|
1647
1773
|
);
|
|
1648
1774
|
|
|
1649
1775
|
// Build resolveServerUrl helper function
|
|
@@ -1655,11 +1781,9 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1655
1781
|
private resolveServerUrl(
|
|
1656
1782
|
server: {
|
|
1657
1783
|
url: string;
|
|
1658
|
-
variables?:
|
|
1659
|
-
| Record<string, {default: string; enum?: string[] | undefined; description?: string | undefined}>
|
|
1660
|
-
| undefined;
|
|
1784
|
+
variables?: Record<string, { default: string; enum?: string[] | undefined; description?: string | undefined }> | undefined;
|
|
1661
1785
|
},
|
|
1662
|
-
variables: Record<string, string
|
|
1786
|
+
variables: Record<string, string>
|
|
1663
1787
|
): string {
|
|
1664
1788
|
let url = server.url;
|
|
1665
1789
|
|
|
@@ -1677,22 +1801,16 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1677
1801
|
servers: {
|
|
1678
1802
|
url: string;
|
|
1679
1803
|
description?: string | undefined;
|
|
1680
|
-
variables?:
|
|
1681
|
-
|
|
1682
|
-
| undefined;
|
|
1683
|
-
}[],
|
|
1804
|
+
variables?: Record<string, { default: string; enum?: string[] | undefined; description?: string | undefined }> | undefined;
|
|
1805
|
+
}[]
|
|
1684
1806
|
): ts.FunctionDeclaration {
|
|
1685
1807
|
// Build server configs array inline
|
|
1686
1808
|
const serverConfigElements = servers.map((server) => {
|
|
1687
|
-
const properties: ts.PropertyAssignment[] = [
|
|
1688
|
-
ts.factory.createPropertyAssignment('url', ts.factory.createStringLiteral(server.url, true)),
|
|
1689
|
-
];
|
|
1809
|
+
const properties: ts.PropertyAssignment[] = [ts.factory.createPropertyAssignment('url', ts.factory.createStringLiteral(server.url, true))];
|
|
1690
1810
|
|
|
1691
1811
|
if (server.variables && Object.keys(server.variables).length > 0) {
|
|
1692
1812
|
const variableProperties = Object.entries(server.variables).map(([varName, varDef]) => {
|
|
1693
|
-
const varProps: ts.PropertyAssignment[] = [
|
|
1694
|
-
ts.factory.createPropertyAssignment('default', ts.factory.createStringLiteral(varDef.default, true)),
|
|
1695
|
-
];
|
|
1813
|
+
const varProps: ts.PropertyAssignment[] = [ts.factory.createPropertyAssignment('default', ts.factory.createStringLiteral(varDef.default, true))];
|
|
1696
1814
|
|
|
1697
1815
|
if (varDef.enum && varDef.enum.length > 0) {
|
|
1698
1816
|
varProps.push(
|
|
@@ -1700,21 +1818,16 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1700
1818
|
'enum',
|
|
1701
1819
|
ts.factory.createArrayLiteralExpression(
|
|
1702
1820
|
varDef.enum.map((val) => ts.factory.createStringLiteral(val, true)),
|
|
1703
|
-
false
|
|
1704
|
-
)
|
|
1705
|
-
)
|
|
1821
|
+
false
|
|
1822
|
+
)
|
|
1823
|
+
)
|
|
1706
1824
|
);
|
|
1707
1825
|
}
|
|
1708
1826
|
|
|
1709
1827
|
return ts.factory.createPropertyAssignment(varName, ts.factory.createObjectLiteralExpression(varProps, true));
|
|
1710
1828
|
});
|
|
1711
1829
|
|
|
1712
|
-
properties.push(
|
|
1713
|
-
ts.factory.createPropertyAssignment(
|
|
1714
|
-
'variables',
|
|
1715
|
-
ts.factory.createObjectLiteralExpression(variableProperties, true),
|
|
1716
|
-
),
|
|
1717
|
-
);
|
|
1830
|
+
properties.push(ts.factory.createPropertyAssignment('variables', ts.factory.createObjectLiteralExpression(variableProperties, true)));
|
|
1718
1831
|
}
|
|
1719
1832
|
|
|
1720
1833
|
return ts.factory.createObjectLiteralExpression(properties, true);
|
|
@@ -1733,16 +1846,9 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1733
1846
|
ts.factory.createVariableStatement(
|
|
1734
1847
|
undefined,
|
|
1735
1848
|
ts.factory.createVariableDeclarationList(
|
|
1736
|
-
[
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
undefined,
|
|
1740
|
-
undefined,
|
|
1741
|
-
ts.factory.createArrayLiteralExpression(serverConfigElements, false),
|
|
1742
|
-
),
|
|
1743
|
-
],
|
|
1744
|
-
ts.NodeFlags.Const,
|
|
1745
|
-
),
|
|
1849
|
+
[ts.factory.createVariableDeclaration(configs, undefined, undefined, ts.factory.createArrayLiteralExpression(serverConfigElements, false))],
|
|
1850
|
+
ts.NodeFlags.Const
|
|
1851
|
+
)
|
|
1746
1852
|
),
|
|
1747
1853
|
// const idx = serverIndex ?? 0
|
|
1748
1854
|
ts.factory.createVariableStatement(
|
|
@@ -1756,19 +1862,19 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1756
1862
|
ts.factory.createBinaryExpression(
|
|
1757
1863
|
ts.factory.createIdentifier('serverIndex'),
|
|
1758
1864
|
ts.factory.createToken(ts.SyntaxKind.QuestionQuestionToken),
|
|
1759
|
-
ts.factory.createNumericLiteral('0')
|
|
1760
|
-
)
|
|
1761
|
-
)
|
|
1865
|
+
ts.factory.createNumericLiteral('0')
|
|
1866
|
+
)
|
|
1867
|
+
)
|
|
1762
1868
|
],
|
|
1763
|
-
ts.NodeFlags.Const
|
|
1764
|
-
)
|
|
1869
|
+
ts.NodeFlags.Const
|
|
1870
|
+
)
|
|
1765
1871
|
),
|
|
1766
1872
|
// if (idx < configs.length) { ... }
|
|
1767
1873
|
ts.factory.createIfStatement(
|
|
1768
1874
|
ts.factory.createBinaryExpression(
|
|
1769
1875
|
idx,
|
|
1770
1876
|
ts.factory.createToken(ts.SyntaxKind.LessThanToken),
|
|
1771
|
-
ts.factory.createPropertyAccessExpression(configs, ts.factory.createIdentifier('length'))
|
|
1877
|
+
ts.factory.createPropertyAccessExpression(configs, ts.factory.createIdentifier('length'))
|
|
1772
1878
|
),
|
|
1773
1879
|
ts.factory.createBlock(
|
|
1774
1880
|
[
|
|
@@ -1776,37 +1882,23 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1776
1882
|
ts.factory.createVariableStatement(
|
|
1777
1883
|
undefined,
|
|
1778
1884
|
ts.factory.createVariableDeclarationList(
|
|
1779
|
-
[
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
undefined,
|
|
1783
|
-
undefined,
|
|
1784
|
-
ts.factory.createElementAccessExpression(configs, idx),
|
|
1785
|
-
),
|
|
1786
|
-
],
|
|
1787
|
-
ts.NodeFlags.Const,
|
|
1788
|
-
),
|
|
1885
|
+
[ts.factory.createVariableDeclaration(config, undefined, undefined, ts.factory.createElementAccessExpression(configs, idx))],
|
|
1886
|
+
ts.NodeFlags.Const
|
|
1887
|
+
)
|
|
1789
1888
|
),
|
|
1790
1889
|
// let url = config.url
|
|
1791
1890
|
ts.factory.createVariableStatement(
|
|
1792
1891
|
undefined,
|
|
1793
1892
|
ts.factory.createVariableDeclarationList(
|
|
1794
|
-
[
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
undefined,
|
|
1798
|
-
undefined,
|
|
1799
|
-
ts.factory.createPropertyAccessExpression(config, ts.factory.createIdentifier('url')),
|
|
1800
|
-
),
|
|
1801
|
-
],
|
|
1802
|
-
ts.NodeFlags.Let,
|
|
1803
|
-
),
|
|
1893
|
+
[ts.factory.createVariableDeclaration(url, undefined, undefined, ts.factory.createPropertyAccessExpression(config, ts.factory.createIdentifier('url')))],
|
|
1894
|
+
ts.NodeFlags.Let
|
|
1895
|
+
)
|
|
1804
1896
|
),
|
|
1805
1897
|
// if (config.variables && serverVariables) { ... }
|
|
1806
1898
|
ts.factory.createIfStatement(
|
|
1807
1899
|
ts.factory.createLogicalAnd(
|
|
1808
1900
|
ts.factory.createPropertyAccessExpression(config, ts.factory.createIdentifier('variables')),
|
|
1809
|
-
ts.factory.createIdentifier('serverVariables')
|
|
1901
|
+
ts.factory.createIdentifier('serverVariables')
|
|
1810
1902
|
),
|
|
1811
1903
|
ts.factory.createBlock(
|
|
1812
1904
|
[
|
|
@@ -1818,21 +1910,18 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1818
1910
|
ts.factory.createVariableDeclaration(
|
|
1819
1911
|
ts.factory.createArrayBindingPattern([
|
|
1820
1912
|
ts.factory.createBindingElement(undefined, undefined, key),
|
|
1821
|
-
ts.factory.createBindingElement(undefined, undefined, value)
|
|
1913
|
+
ts.factory.createBindingElement(undefined, undefined, value)
|
|
1822
1914
|
]),
|
|
1823
1915
|
undefined,
|
|
1824
|
-
undefined
|
|
1825
|
-
)
|
|
1916
|
+
undefined
|
|
1917
|
+
)
|
|
1826
1918
|
],
|
|
1827
|
-
ts.NodeFlags.Const
|
|
1919
|
+
ts.NodeFlags.Const
|
|
1828
1920
|
),
|
|
1829
1921
|
ts.factory.createCallExpression(
|
|
1830
|
-
ts.factory.createPropertyAccessExpression(
|
|
1831
|
-
ts.factory.createIdentifier('Object'),
|
|
1832
|
-
ts.factory.createIdentifier('entries'),
|
|
1833
|
-
),
|
|
1922
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('Object'), ts.factory.createIdentifier('entries')),
|
|
1834
1923
|
undefined,
|
|
1835
|
-
[ts.factory.createIdentifier('serverVariables')]
|
|
1924
|
+
[ts.factory.createIdentifier('serverVariables')]
|
|
1836
1925
|
),
|
|
1837
1926
|
ts.factory.createBlock(
|
|
1838
1927
|
[
|
|
@@ -1840,45 +1929,35 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1840
1929
|
ts.factory.createBinaryExpression(
|
|
1841
1930
|
url,
|
|
1842
1931
|
ts.factory.createToken(ts.SyntaxKind.EqualsToken),
|
|
1843
|
-
ts.factory.createCallExpression(
|
|
1844
|
-
ts.factory.
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
ts.factory.
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
),
|
|
1857
|
-
ts.factory.createStringLiteral('g'),
|
|
1858
|
-
]),
|
|
1859
|
-
value,
|
|
1860
|
-
],
|
|
1861
|
-
),
|
|
1862
|
-
),
|
|
1863
|
-
),
|
|
1932
|
+
ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(url, ts.factory.createIdentifier('replace')), undefined, [
|
|
1933
|
+
ts.factory.createNewExpression(ts.factory.createIdentifier('RegExp'), undefined, [
|
|
1934
|
+
ts.factory.createBinaryExpression(
|
|
1935
|
+
ts.factory.createBinaryExpression(ts.factory.createStringLiteral('\\{'), ts.factory.createToken(ts.SyntaxKind.PlusToken), key),
|
|
1936
|
+
ts.factory.createToken(ts.SyntaxKind.PlusToken),
|
|
1937
|
+
ts.factory.createStringLiteral('\\}')
|
|
1938
|
+
),
|
|
1939
|
+
ts.factory.createStringLiteral('g')
|
|
1940
|
+
]),
|
|
1941
|
+
value
|
|
1942
|
+
])
|
|
1943
|
+
)
|
|
1944
|
+
)
|
|
1864
1945
|
],
|
|
1865
|
-
true
|
|
1866
|
-
)
|
|
1867
|
-
)
|
|
1946
|
+
true
|
|
1947
|
+
)
|
|
1948
|
+
)
|
|
1868
1949
|
],
|
|
1869
|
-
true
|
|
1870
|
-
)
|
|
1950
|
+
true
|
|
1951
|
+
)
|
|
1871
1952
|
),
|
|
1872
1953
|
// return url
|
|
1873
|
-
ts.factory.createReturnStatement(url)
|
|
1954
|
+
ts.factory.createReturnStatement(url)
|
|
1874
1955
|
],
|
|
1875
|
-
true
|
|
1876
|
-
)
|
|
1956
|
+
true
|
|
1957
|
+
)
|
|
1877
1958
|
),
|
|
1878
1959
|
// return default (first server with defaults)
|
|
1879
|
-
ts.factory.createReturnStatement(
|
|
1880
|
-
ts.factory.createStringLiteral(servers[0] ? this.resolveServerUrl(servers[0], {}) : '/', true),
|
|
1881
|
-
),
|
|
1960
|
+
ts.factory.createReturnStatement(ts.factory.createStringLiteral(servers[0] ? this.resolveServerUrl(servers[0], {}) : '/', true))
|
|
1882
1961
|
];
|
|
1883
1962
|
|
|
1884
1963
|
return ts.factory.createFunctionDeclaration(
|
|
@@ -1892,11 +1971,8 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1892
1971
|
undefined,
|
|
1893
1972
|
ts.factory.createIdentifier('serverIndex'),
|
|
1894
1973
|
ts.factory.createToken(ts.SyntaxKind.QuestionToken),
|
|
1895
|
-
ts.factory.createUnionTypeNode([
|
|
1896
|
-
|
|
1897
|
-
ts.factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword),
|
|
1898
|
-
]),
|
|
1899
|
-
undefined,
|
|
1974
|
+
ts.factory.createUnionTypeNode([ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword), ts.factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword)]),
|
|
1975
|
+
undefined
|
|
1900
1976
|
),
|
|
1901
1977
|
ts.factory.createParameterDeclaration(
|
|
1902
1978
|
undefined,
|
|
@@ -1905,13 +1981,13 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1905
1981
|
ts.factory.createToken(ts.SyntaxKind.QuestionToken),
|
|
1906
1982
|
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Record'), [
|
|
1907
1983
|
ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
|
|
1908
|
-
ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword)
|
|
1984
|
+
ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword)
|
|
1909
1985
|
]),
|
|
1910
|
-
ts.factory.createObjectLiteralExpression([], false)
|
|
1911
|
-
)
|
|
1986
|
+
ts.factory.createObjectLiteralExpression([], false)
|
|
1987
|
+
)
|
|
1912
1988
|
],
|
|
1913
1989
|
ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
|
|
1914
|
-
ts.factory.createBlock(bodyStatements, true)
|
|
1990
|
+
ts.factory.createBlock(bodyStatements, true)
|
|
1915
1991
|
);
|
|
1916
1992
|
}
|
|
1917
1993
|
|
|
@@ -1931,12 +2007,7 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1931
2007
|
/**
|
|
1932
2008
|
* Builds a JSDoc comment string from operation metadata
|
|
1933
2009
|
*/
|
|
1934
|
-
private buildJSDocComment(
|
|
1935
|
-
summary: string | undefined,
|
|
1936
|
-
description: string | undefined,
|
|
1937
|
-
schema: MethodSchemaType,
|
|
1938
|
-
responseType: ts.TypeNode | undefined,
|
|
1939
|
-
): string {
|
|
2010
|
+
private buildJSDocComment(summary: string | undefined, description: string | undefined, schema: MethodSchemaType, responseType: ts.TypeNode | undefined): string {
|
|
1940
2011
|
const lines: string[] = [];
|
|
1941
2012
|
|
|
1942
2013
|
// Add summary or description as the main comment
|
|
@@ -1957,6 +2028,7 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1957
2028
|
if (lines.length > 0) {
|
|
1958
2029
|
lines.push(' *');
|
|
1959
2030
|
}
|
|
2031
|
+
|
|
1960
2032
|
descLines.forEach((line) => {
|
|
1961
2033
|
lines.push(` * ${line.trim() || ''}`);
|
|
1962
2034
|
});
|
|
@@ -1968,6 +2040,7 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1968
2040
|
if (lines.length > 0) {
|
|
1969
2041
|
lines.push(' *');
|
|
1970
2042
|
}
|
|
2043
|
+
|
|
1971
2044
|
for (const param of schema.parameters) {
|
|
1972
2045
|
const paramName = this.typeBuilder.sanitizeIdentifier(param.name);
|
|
1973
2046
|
const paramDesc = param.description ? ` ${param.description}` : '';
|
|
@@ -1995,18 +2068,11 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1995
2068
|
) {
|
|
1996
2069
|
// Extract the inner type from Promise<T>
|
|
1997
2070
|
const innerType = responseType.typeArguments[0];
|
|
1998
|
-
returnTypeText = this.printer.printNode(
|
|
1999
|
-
ts.EmitHint.Unspecified,
|
|
2000
|
-
innerType,
|
|
2001
|
-
ts.createSourceFile('', '', ts.ScriptTarget.Latest),
|
|
2002
|
-
);
|
|
2071
|
+
returnTypeText = this.printer.printNode(ts.EmitHint.Unspecified, innerType, ts.createSourceFile('', '', ts.ScriptTarget.Latest));
|
|
2003
2072
|
} else {
|
|
2004
|
-
returnTypeText = this.printer.printNode(
|
|
2005
|
-
ts.EmitHint.Unspecified,
|
|
2006
|
-
responseType,
|
|
2007
|
-
ts.createSourceFile('', '', ts.ScriptTarget.Latest),
|
|
2008
|
-
);
|
|
2073
|
+
returnTypeText = this.printer.printNode(ts.EmitHint.Unspecified, responseType, ts.createSourceFile('', '', ts.ScriptTarget.Latest));
|
|
2009
2074
|
}
|
|
2075
|
+
|
|
2010
2076
|
lines.push(` * @returns {${returnTypeText}}`);
|
|
2011
2077
|
}
|
|
2012
2078
|
|
|
@@ -2025,37 +2091,28 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
2025
2091
|
|
|
2026
2092
|
const initialExpression = !safeInitial.success
|
|
2027
2093
|
? ts.factory.createCallExpression(
|
|
2028
|
-
ts.factory.createPropertyAccessExpression(
|
|
2029
|
-
ts.factory.createIdentifier('z'),
|
|
2030
|
-
ts.factory.createIdentifier(this.ZodAST.shape.type.parse(initial)),
|
|
2031
|
-
),
|
|
2094
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('z'), ts.factory.createIdentifier(this.ZodAST.shape.type.parse(initial))),
|
|
2032
2095
|
undefined,
|
|
2033
|
-
[]
|
|
2096
|
+
[]
|
|
2034
2097
|
)
|
|
2035
2098
|
: ts.factory.createCallExpression(
|
|
2036
|
-
ts.factory.createPropertyAccessExpression(
|
|
2037
|
-
ts.factory.createIdentifier('z'),
|
|
2038
|
-
ts.factory.createIdentifier(safeInitial.data.type),
|
|
2039
|
-
),
|
|
2099
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('z'), ts.factory.createIdentifier(safeInitial.data.type)),
|
|
2040
2100
|
undefined,
|
|
2041
|
-
(safeInitial.data.args ?? []) as ts.Expression[]
|
|
2101
|
+
(safeInitial.data.args ?? []) as ts.Expression[]
|
|
2042
2102
|
);
|
|
2043
2103
|
|
|
2044
2104
|
return rest.reduce((expression, exp: unknown) => {
|
|
2045
2105
|
const safeExp = this.ZodAST.safeParse(exp);
|
|
2046
2106
|
return !safeExp.success
|
|
2047
2107
|
? ts.factory.createCallExpression(
|
|
2048
|
-
ts.factory.createPropertyAccessExpression(
|
|
2049
|
-
expression,
|
|
2050
|
-
ts.factory.createIdentifier(typeof exp === 'string' ? exp : String(exp)),
|
|
2051
|
-
),
|
|
2108
|
+
ts.factory.createPropertyAccessExpression(expression, ts.factory.createIdentifier(typeof exp === 'string' ? exp : String(exp))),
|
|
2052
2109
|
undefined,
|
|
2053
|
-
[]
|
|
2110
|
+
[]
|
|
2054
2111
|
)
|
|
2055
2112
|
: ts.factory.createCallExpression(
|
|
2056
2113
|
ts.factory.createPropertyAccessExpression(expression, ts.factory.createIdentifier(safeExp.data.type)),
|
|
2057
2114
|
undefined,
|
|
2058
|
-
(safeExp.data.args ?? []) as ts.Expression[]
|
|
2115
|
+
(safeExp.data.args ?? []) as ts.Expression[]
|
|
2059
2116
|
);
|
|
2060
2117
|
}, initialExpression);
|
|
2061
2118
|
}
|
|
@@ -2071,13 +2128,7 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
2071
2128
|
|
|
2072
2129
|
if (this.isReference(prop)) {
|
|
2073
2130
|
const refSchema = this.buildFromReference(prop);
|
|
2074
|
-
return required
|
|
2075
|
-
? refSchema
|
|
2076
|
-
: ts.factory.createCallExpression(
|
|
2077
|
-
ts.factory.createPropertyAccessExpression(refSchema, ts.factory.createIdentifier('optional')),
|
|
2078
|
-
undefined,
|
|
2079
|
-
[],
|
|
2080
|
-
);
|
|
2131
|
+
return required ? refSchema : ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(refSchema, ts.factory.createIdentifier('optional')), undefined, []);
|
|
2081
2132
|
}
|
|
2082
2133
|
|
|
2083
2134
|
if (prop['anyOf'] && Array.isArray(prop['anyOf']) && prop['anyOf'].length > 0) {
|
|
@@ -2105,21 +2156,14 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
2105
2156
|
// Use z.enum() for string enums
|
|
2106
2157
|
const enumValues = prop['enum'].map((val) => ts.factory.createStringLiteral(val as string, true));
|
|
2107
2158
|
const enumExpression = ts.factory.createCallExpression(
|
|
2108
|
-
ts.factory.createPropertyAccessExpression(
|
|
2109
|
-
ts.factory.createIdentifier('z'),
|
|
2110
|
-
ts.factory.createIdentifier('enum'),
|
|
2111
|
-
),
|
|
2159
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('enum')),
|
|
2112
2160
|
undefined,
|
|
2113
|
-
[ts.factory.createArrayLiteralExpression(enumValues, false)]
|
|
2161
|
+
[ts.factory.createArrayLiteralExpression(enumValues, false)]
|
|
2114
2162
|
);
|
|
2115
2163
|
|
|
2116
2164
|
return required
|
|
2117
2165
|
? enumExpression
|
|
2118
|
-
: ts.factory.createCallExpression(
|
|
2119
|
-
ts.factory.createPropertyAccessExpression(enumExpression, ts.factory.createIdentifier('optional')),
|
|
2120
|
-
undefined,
|
|
2121
|
-
[],
|
|
2122
|
-
);
|
|
2166
|
+
: ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(enumExpression, ts.factory.createIdentifier('optional')), undefined, []);
|
|
2123
2167
|
} else {
|
|
2124
2168
|
// Use z.union([z.literal(...), ...]) for numeric/boolean/mixed enums
|
|
2125
2169
|
const literalSchemas = prop['enum'].map((val) => {
|
|
@@ -2129,10 +2173,7 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
2129
2173
|
} else if (typeof val === 'number') {
|
|
2130
2174
|
// Handle negative numbers correctly
|
|
2131
2175
|
if (val < 0) {
|
|
2132
|
-
literalValue = ts.factory.createPrefixUnaryExpression(
|
|
2133
|
-
ts.SyntaxKind.MinusToken,
|
|
2134
|
-
ts.factory.createNumericLiteral(String(Math.abs(val))),
|
|
2135
|
-
);
|
|
2176
|
+
literalValue = ts.factory.createPrefixUnaryExpression(ts.SyntaxKind.MinusToken, ts.factory.createNumericLiteral(String(Math.abs(val))));
|
|
2136
2177
|
} else {
|
|
2137
2178
|
literalValue = ts.factory.createNumericLiteral(String(val));
|
|
2138
2179
|
}
|
|
@@ -2142,32 +2183,20 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
2142
2183
|
literalValue = ts.factory.createStringLiteral(String(val), true);
|
|
2143
2184
|
}
|
|
2144
2185
|
|
|
2145
|
-
return ts.factory.createCallExpression(
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
ts.factory.createIdentifier('literal'),
|
|
2149
|
-
),
|
|
2150
|
-
undefined,
|
|
2151
|
-
[literalValue],
|
|
2152
|
-
);
|
|
2186
|
+
return ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('literal')), undefined, [
|
|
2187
|
+
literalValue
|
|
2188
|
+
]);
|
|
2153
2189
|
});
|
|
2154
2190
|
|
|
2155
2191
|
const unionExpression = ts.factory.createCallExpression(
|
|
2156
|
-
ts.factory.createPropertyAccessExpression(
|
|
2157
|
-
ts.factory.createIdentifier('z'),
|
|
2158
|
-
ts.factory.createIdentifier('union'),
|
|
2159
|
-
),
|
|
2192
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('union')),
|
|
2160
2193
|
undefined,
|
|
2161
|
-
[ts.factory.createArrayLiteralExpression(literalSchemas, false)]
|
|
2194
|
+
[ts.factory.createArrayLiteralExpression(literalSchemas, false)]
|
|
2162
2195
|
);
|
|
2163
2196
|
|
|
2164
2197
|
return required
|
|
2165
2198
|
? unionExpression
|
|
2166
|
-
: ts.factory.createCallExpression(
|
|
2167
|
-
ts.factory.createPropertyAccessExpression(unionExpression, ts.factory.createIdentifier('optional')),
|
|
2168
|
-
undefined,
|
|
2169
|
-
[],
|
|
2170
|
-
);
|
|
2199
|
+
: ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(unionExpression, ts.factory.createIdentifier('optional')), undefined, []);
|
|
2171
2200
|
}
|
|
2172
2201
|
}
|
|
2173
2202
|
|
|
@@ -2177,33 +2206,26 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
2177
2206
|
let arraySchema = this.buildZodAST([
|
|
2178
2207
|
{
|
|
2179
2208
|
type: 'array',
|
|
2180
|
-
args: [itemsSchema]
|
|
2181
|
-
}
|
|
2209
|
+
args: [itemsSchema]
|
|
2210
|
+
}
|
|
2182
2211
|
]);
|
|
2183
2212
|
|
|
2184
2213
|
// Apply array constraints
|
|
2185
2214
|
if (typeof prop['minItems'] === 'number') {
|
|
2186
|
-
arraySchema = ts.factory.createCallExpression(
|
|
2187
|
-
ts.factory.
|
|
2188
|
-
|
|
2189
|
-
[ts.factory.createNumericLiteral(String(prop['minItems']))],
|
|
2190
|
-
);
|
|
2215
|
+
arraySchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(arraySchema, ts.factory.createIdentifier('min')), undefined, [
|
|
2216
|
+
ts.factory.createNumericLiteral(String(prop['minItems']))
|
|
2217
|
+
]);
|
|
2191
2218
|
}
|
|
2219
|
+
|
|
2192
2220
|
if (typeof prop['maxItems'] === 'number') {
|
|
2193
|
-
arraySchema = ts.factory.createCallExpression(
|
|
2194
|
-
ts.factory.
|
|
2195
|
-
|
|
2196
|
-
[ts.factory.createNumericLiteral(String(prop['maxItems']))],
|
|
2197
|
-
);
|
|
2221
|
+
arraySchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(arraySchema, ts.factory.createIdentifier('max')), undefined, [
|
|
2222
|
+
ts.factory.createNumericLiteral(String(prop['maxItems']))
|
|
2223
|
+
]);
|
|
2198
2224
|
}
|
|
2199
2225
|
|
|
2200
2226
|
return required
|
|
2201
2227
|
? arraySchema
|
|
2202
|
-
: ts.factory.createCallExpression(
|
|
2203
|
-
ts.factory.createPropertyAccessExpression(arraySchema, ts.factory.createIdentifier('optional')),
|
|
2204
|
-
undefined,
|
|
2205
|
-
[],
|
|
2206
|
-
);
|
|
2228
|
+
: ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(arraySchema, ts.factory.createIdentifier('optional')), undefined, []);
|
|
2207
2229
|
}
|
|
2208
2230
|
case 'object': {
|
|
2209
2231
|
const propObj = prop satisfies {
|
|
@@ -2222,110 +2244,86 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
2222
2244
|
args: [
|
|
2223
2245
|
ts.factory.createObjectLiteralExpression(
|
|
2224
2246
|
propertiesEntries.map(([name, propValue]): ts.ObjectLiteralElementLike => {
|
|
2225
|
-
return ts.factory.createPropertyAssignment(
|
|
2226
|
-
ts.factory.createIdentifier(name),
|
|
2227
|
-
this.buildProperty(propValue, propRequired.includes(name)),
|
|
2228
|
-
);
|
|
2247
|
+
return ts.factory.createPropertyAssignment(ts.factory.createIdentifier(name), this.buildProperty(propValue, propRequired.includes(name)));
|
|
2229
2248
|
}),
|
|
2230
|
-
true
|
|
2231
|
-
)
|
|
2232
|
-
]
|
|
2233
|
-
}
|
|
2249
|
+
true
|
|
2250
|
+
)
|
|
2251
|
+
]
|
|
2252
|
+
}
|
|
2234
2253
|
]);
|
|
2235
2254
|
|
|
2236
2255
|
// Apply object constraints
|
|
2237
2256
|
let constrainedSchema = objectSchema;
|
|
2238
2257
|
if (typeof prop['minProperties'] === 'number') {
|
|
2239
|
-
constrainedSchema = ts.factory.createCallExpression(
|
|
2240
|
-
ts.factory.
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
ts.factory.
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
ts.factory.
|
|
2252
|
-
ts.factory.createPropertyAccessExpression(
|
|
2253
|
-
ts.factory.createIdentifier('Object'),
|
|
2254
|
-
ts.factory.createIdentifier('keys'),
|
|
2255
|
-
),
|
|
2256
|
-
undefined,
|
|
2257
|
-
[ts.factory.createIdentifier('obj')],
|
|
2258
|
-
),
|
|
2259
|
-
ts.factory.createIdentifier('length'),
|
|
2260
|
-
),
|
|
2261
|
-
ts.factory.createToken(ts.SyntaxKind.GreaterThanEqualsToken),
|
|
2262
|
-
ts.factory.createNumericLiteral(String(prop['minProperties'])),
|
|
2263
|
-
),
|
|
2264
|
-
),
|
|
2265
|
-
ts.factory.createObjectLiteralExpression([
|
|
2266
|
-
ts.factory.createPropertyAssignment(
|
|
2267
|
-
ts.factory.createIdentifier('message'),
|
|
2268
|
-
ts.factory.createStringLiteral(
|
|
2269
|
-
`Object must have at least ${String(prop['minProperties'])} properties`,
|
|
2258
|
+
constrainedSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(constrainedSchema, ts.factory.createIdentifier('refine')), undefined, [
|
|
2259
|
+
ts.factory.createArrowFunction(
|
|
2260
|
+
undefined,
|
|
2261
|
+
undefined,
|
|
2262
|
+
[ts.factory.createParameterDeclaration(undefined, undefined, 'obj', undefined, undefined, undefined)],
|
|
2263
|
+
undefined,
|
|
2264
|
+
ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
|
|
2265
|
+
ts.factory.createBinaryExpression(
|
|
2266
|
+
ts.factory.createPropertyAccessExpression(
|
|
2267
|
+
ts.factory.createCallExpression(
|
|
2268
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('Object'), ts.factory.createIdentifier('keys')),
|
|
2269
|
+
undefined,
|
|
2270
|
+
[ts.factory.createIdentifier('obj')]
|
|
2270
2271
|
),
|
|
2272
|
+
ts.factory.createIdentifier('length')
|
|
2271
2273
|
),
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2274
|
+
ts.factory.createToken(ts.SyntaxKind.GreaterThanEqualsToken),
|
|
2275
|
+
ts.factory.createNumericLiteral(String(prop['minProperties']))
|
|
2276
|
+
)
|
|
2277
|
+
),
|
|
2278
|
+
ts.factory.createObjectLiteralExpression([
|
|
2279
|
+
ts.factory.createPropertyAssignment(
|
|
2280
|
+
ts.factory.createIdentifier('message'),
|
|
2281
|
+
ts.factory.createStringLiteral(`Object must have at least ${String(prop['minProperties'])} properties`)
|
|
2282
|
+
)
|
|
2283
|
+
])
|
|
2284
|
+
]);
|
|
2275
2285
|
}
|
|
2286
|
+
|
|
2276
2287
|
if (typeof prop['maxProperties'] === 'number') {
|
|
2277
|
-
constrainedSchema = ts.factory.createCallExpression(
|
|
2278
|
-
ts.factory.
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
ts.factory.
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
ts.factory.
|
|
2290
|
-
ts.factory.createPropertyAccessExpression(
|
|
2291
|
-
ts.factory.createIdentifier('Object'),
|
|
2292
|
-
ts.factory.createIdentifier('keys'),
|
|
2293
|
-
),
|
|
2294
|
-
undefined,
|
|
2295
|
-
[ts.factory.createIdentifier('obj')],
|
|
2296
|
-
),
|
|
2297
|
-
ts.factory.createIdentifier('length'),
|
|
2298
|
-
),
|
|
2299
|
-
ts.factory.createToken(ts.SyntaxKind.LessThanEqualsToken),
|
|
2300
|
-
ts.factory.createNumericLiteral(String(prop['maxProperties'])),
|
|
2301
|
-
),
|
|
2302
|
-
),
|
|
2303
|
-
ts.factory.createObjectLiteralExpression([
|
|
2304
|
-
ts.factory.createPropertyAssignment(
|
|
2305
|
-
ts.factory.createIdentifier('message'),
|
|
2306
|
-
ts.factory.createStringLiteral(
|
|
2307
|
-
`Object must have at most ${String(prop['maxProperties'])} properties`,
|
|
2288
|
+
constrainedSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(constrainedSchema, ts.factory.createIdentifier('refine')), undefined, [
|
|
2289
|
+
ts.factory.createArrowFunction(
|
|
2290
|
+
undefined,
|
|
2291
|
+
undefined,
|
|
2292
|
+
[ts.factory.createParameterDeclaration(undefined, undefined, 'obj', undefined, undefined, undefined)],
|
|
2293
|
+
undefined,
|
|
2294
|
+
ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
|
|
2295
|
+
ts.factory.createBinaryExpression(
|
|
2296
|
+
ts.factory.createPropertyAccessExpression(
|
|
2297
|
+
ts.factory.createCallExpression(
|
|
2298
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('Object'), ts.factory.createIdentifier('keys')),
|
|
2299
|
+
undefined,
|
|
2300
|
+
[ts.factory.createIdentifier('obj')]
|
|
2308
2301
|
),
|
|
2302
|
+
ts.factory.createIdentifier('length')
|
|
2309
2303
|
),
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2304
|
+
ts.factory.createToken(ts.SyntaxKind.LessThanEqualsToken),
|
|
2305
|
+
ts.factory.createNumericLiteral(String(prop['maxProperties']))
|
|
2306
|
+
)
|
|
2307
|
+
),
|
|
2308
|
+
ts.factory.createObjectLiteralExpression([
|
|
2309
|
+
ts.factory.createPropertyAssignment(
|
|
2310
|
+
ts.factory.createIdentifier('message'),
|
|
2311
|
+
ts.factory.createStringLiteral(`Object must have at most ${String(prop['maxProperties'])} properties`)
|
|
2312
|
+
)
|
|
2313
|
+
])
|
|
2314
|
+
]);
|
|
2313
2315
|
}
|
|
2314
2316
|
|
|
2315
2317
|
return required
|
|
2316
2318
|
? constrainedSchema
|
|
2317
|
-
: ts.factory.createCallExpression(
|
|
2318
|
-
ts.factory.createPropertyAccessExpression(constrainedSchema, ts.factory.createIdentifier('optional')),
|
|
2319
|
-
undefined,
|
|
2320
|
-
[],
|
|
2321
|
-
);
|
|
2319
|
+
: ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(constrainedSchema, ts.factory.createIdentifier('optional')), undefined, []);
|
|
2322
2320
|
}
|
|
2323
2321
|
|
|
2324
2322
|
return this.buildZodAST([
|
|
2325
2323
|
{
|
|
2326
2324
|
type: 'record',
|
|
2327
|
-
args: [this.buildZodAST(['string']), this.buildZodAST(['unknown'])]
|
|
2328
|
-
}
|
|
2325
|
+
args: [this.buildZodAST(['string']), this.buildZodAST(['unknown'])]
|
|
2326
|
+
}
|
|
2329
2327
|
]);
|
|
2330
2328
|
}
|
|
2331
2329
|
case 'integer': {
|
|
@@ -2333,35 +2331,26 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
2333
2331
|
|
|
2334
2332
|
// Apply number constraints
|
|
2335
2333
|
if (prop['minimum'] !== undefined && typeof prop['minimum'] === 'number') {
|
|
2336
|
-
const minValue =
|
|
2337
|
-
prop['exclusiveMinimum'] && typeof prop['exclusiveMinimum'] === 'boolean'
|
|
2338
|
-
? prop['minimum'] + 1
|
|
2339
|
-
: prop['minimum'];
|
|
2334
|
+
const minValue = prop['exclusiveMinimum'] && typeof prop['exclusiveMinimum'] === 'boolean' ? prop['minimum'] + 1 : prop['minimum'];
|
|
2340
2335
|
numberSchema = ts.factory.createCallExpression(
|
|
2341
2336
|
ts.factory.createPropertyAccessExpression(
|
|
2342
2337
|
numberSchema,
|
|
2343
|
-
ts.factory.createIdentifier(
|
|
2344
|
-
prop['exclusiveMinimum'] && typeof prop['exclusiveMinimum'] === 'boolean' ? 'gt' : 'gte',
|
|
2345
|
-
),
|
|
2338
|
+
ts.factory.createIdentifier(prop['exclusiveMinimum'] && typeof prop['exclusiveMinimum'] === 'boolean' ? 'gt' : 'gte')
|
|
2346
2339
|
),
|
|
2347
2340
|
undefined,
|
|
2348
|
-
[ts.factory.createNumericLiteral(String(minValue))]
|
|
2341
|
+
[ts.factory.createNumericLiteral(String(minValue))]
|
|
2349
2342
|
);
|
|
2350
2343
|
}
|
|
2344
|
+
|
|
2351
2345
|
if (prop['maximum'] !== undefined && typeof prop['maximum'] === 'number') {
|
|
2352
|
-
const maxValue =
|
|
2353
|
-
prop['exclusiveMaximum'] && typeof prop['exclusiveMaximum'] === 'boolean'
|
|
2354
|
-
? prop['maximum'] - 1
|
|
2355
|
-
: prop['maximum'];
|
|
2346
|
+
const maxValue = prop['exclusiveMaximum'] && typeof prop['exclusiveMaximum'] === 'boolean' ? prop['maximum'] - 1 : prop['maximum'];
|
|
2356
2347
|
numberSchema = ts.factory.createCallExpression(
|
|
2357
|
-
ts.factory.createPropertyAccessExpression(
|
|
2358
|
-
numberSchema,
|
|
2359
|
-
ts.factory.createIdentifier(prop['exclusiveMaximum'] ? 'lt' : 'lte'),
|
|
2360
|
-
),
|
|
2348
|
+
ts.factory.createPropertyAccessExpression(numberSchema, ts.factory.createIdentifier(prop['exclusiveMaximum'] ? 'lt' : 'lte')),
|
|
2361
2349
|
undefined,
|
|
2362
|
-
[ts.factory.createNumericLiteral(String(maxValue))]
|
|
2350
|
+
[ts.factory.createNumericLiteral(String(maxValue))]
|
|
2363
2351
|
);
|
|
2364
2352
|
}
|
|
2353
|
+
|
|
2365
2354
|
if (typeof prop['multipleOf'] === 'number') {
|
|
2366
2355
|
const refineFunction = ts.factory.createArrowFunction(
|
|
2367
2356
|
undefined,
|
|
@@ -2373,67 +2362,53 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
2373
2362
|
ts.factory.createBinaryExpression(
|
|
2374
2363
|
ts.factory.createIdentifier('val'),
|
|
2375
2364
|
ts.factory.createToken(ts.SyntaxKind.PercentToken),
|
|
2376
|
-
ts.factory.createNumericLiteral(String(prop['multipleOf']))
|
|
2365
|
+
ts.factory.createNumericLiteral(String(prop['multipleOf']))
|
|
2377
2366
|
),
|
|
2378
2367
|
ts.factory.createToken(ts.SyntaxKind.EqualsEqualsEqualsToken),
|
|
2379
|
-
ts.factory.createNumericLiteral('0')
|
|
2380
|
-
)
|
|
2368
|
+
ts.factory.createNumericLiteral('0')
|
|
2369
|
+
)
|
|
2381
2370
|
);
|
|
2382
2371
|
const refineOptions = ts.factory.createObjectLiteralExpression([
|
|
2383
2372
|
ts.factory.createPropertyAssignment(
|
|
2384
2373
|
ts.factory.createIdentifier('message'),
|
|
2385
|
-
ts.factory.createStringLiteral(`Number must be a multiple of ${String(prop['multipleOf'])}`)
|
|
2386
|
-
)
|
|
2374
|
+
ts.factory.createStringLiteral(`Number must be a multiple of ${String(prop['multipleOf'])}`)
|
|
2375
|
+
)
|
|
2376
|
+
]);
|
|
2377
|
+
numberSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(numberSchema, ts.factory.createIdentifier('refine')), undefined, [
|
|
2378
|
+
refineFunction,
|
|
2379
|
+
refineOptions
|
|
2387
2380
|
]);
|
|
2388
|
-
numberSchema = ts.factory.createCallExpression(
|
|
2389
|
-
ts.factory.createPropertyAccessExpression(numberSchema, ts.factory.createIdentifier('refine')),
|
|
2390
|
-
undefined,
|
|
2391
|
-
[refineFunction, refineOptions],
|
|
2392
|
-
);
|
|
2393
2381
|
}
|
|
2394
2382
|
|
|
2395
2383
|
return required
|
|
2396
2384
|
? numberSchema
|
|
2397
|
-
: ts.factory.createCallExpression(
|
|
2398
|
-
ts.factory.createPropertyAccessExpression(numberSchema, ts.factory.createIdentifier('optional')),
|
|
2399
|
-
undefined,
|
|
2400
|
-
[],
|
|
2401
|
-
);
|
|
2385
|
+
: ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(numberSchema, ts.factory.createIdentifier('optional')), undefined, []);
|
|
2402
2386
|
}
|
|
2403
2387
|
case 'number': {
|
|
2404
2388
|
let numberSchema = this.buildZodAST(['number']);
|
|
2405
2389
|
|
|
2406
2390
|
// Apply number constraints
|
|
2407
2391
|
if (prop['minimum'] !== undefined && typeof prop['minimum'] === 'number') {
|
|
2408
|
-
const minValue =
|
|
2409
|
-
prop['exclusiveMinimum'] && typeof prop['exclusiveMinimum'] === 'boolean'
|
|
2410
|
-
? prop['minimum'] + 1
|
|
2411
|
-
: prop['minimum'];
|
|
2392
|
+
const minValue = prop['exclusiveMinimum'] && typeof prop['exclusiveMinimum'] === 'boolean' ? prop['minimum'] + 1 : prop['minimum'];
|
|
2412
2393
|
numberSchema = ts.factory.createCallExpression(
|
|
2413
2394
|
ts.factory.createPropertyAccessExpression(
|
|
2414
2395
|
numberSchema,
|
|
2415
|
-
ts.factory.createIdentifier(
|
|
2416
|
-
prop['exclusiveMinimum'] && typeof prop['exclusiveMinimum'] === 'boolean' ? 'gt' : 'gte',
|
|
2417
|
-
),
|
|
2396
|
+
ts.factory.createIdentifier(prop['exclusiveMinimum'] && typeof prop['exclusiveMinimum'] === 'boolean' ? 'gt' : 'gte')
|
|
2418
2397
|
),
|
|
2419
2398
|
undefined,
|
|
2420
|
-
[ts.factory.createNumericLiteral(String(minValue))]
|
|
2399
|
+
[ts.factory.createNumericLiteral(String(minValue))]
|
|
2421
2400
|
);
|
|
2422
2401
|
}
|
|
2402
|
+
|
|
2423
2403
|
if (prop['maximum'] !== undefined && typeof prop['maximum'] === 'number') {
|
|
2424
|
-
const maxValue =
|
|
2425
|
-
prop['exclusiveMaximum'] && typeof prop['exclusiveMaximum'] === 'boolean'
|
|
2426
|
-
? prop['maximum'] - 1
|
|
2427
|
-
: prop['maximum'];
|
|
2404
|
+
const maxValue = prop['exclusiveMaximum'] && typeof prop['exclusiveMaximum'] === 'boolean' ? prop['maximum'] - 1 : prop['maximum'];
|
|
2428
2405
|
numberSchema = ts.factory.createCallExpression(
|
|
2429
|
-
ts.factory.createPropertyAccessExpression(
|
|
2430
|
-
numberSchema,
|
|
2431
|
-
ts.factory.createIdentifier(prop['exclusiveMaximum'] ? 'lt' : 'lte'),
|
|
2432
|
-
),
|
|
2406
|
+
ts.factory.createPropertyAccessExpression(numberSchema, ts.factory.createIdentifier(prop['exclusiveMaximum'] ? 'lt' : 'lte')),
|
|
2433
2407
|
undefined,
|
|
2434
|
-
[ts.factory.createNumericLiteral(String(maxValue))]
|
|
2408
|
+
[ts.factory.createNumericLiteral(String(maxValue))]
|
|
2435
2409
|
);
|
|
2436
2410
|
}
|
|
2411
|
+
|
|
2437
2412
|
if (typeof prop['multipleOf'] === 'number') {
|
|
2438
2413
|
const refineFunction = ts.factory.createArrowFunction(
|
|
2439
2414
|
undefined,
|
|
@@ -2445,32 +2420,27 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
2445
2420
|
ts.factory.createBinaryExpression(
|
|
2446
2421
|
ts.factory.createIdentifier('val'),
|
|
2447
2422
|
ts.factory.createToken(ts.SyntaxKind.PercentToken),
|
|
2448
|
-
ts.factory.createNumericLiteral(String(prop['multipleOf']))
|
|
2423
|
+
ts.factory.createNumericLiteral(String(prop['multipleOf']))
|
|
2449
2424
|
),
|
|
2450
2425
|
ts.factory.createToken(ts.SyntaxKind.EqualsEqualsEqualsToken),
|
|
2451
|
-
ts.factory.createNumericLiteral('0')
|
|
2452
|
-
)
|
|
2426
|
+
ts.factory.createNumericLiteral('0')
|
|
2427
|
+
)
|
|
2453
2428
|
);
|
|
2454
2429
|
const refineOptions = ts.factory.createObjectLiteralExpression([
|
|
2455
2430
|
ts.factory.createPropertyAssignment(
|
|
2456
2431
|
ts.factory.createIdentifier('message'),
|
|
2457
|
-
ts.factory.createStringLiteral(`Number must be a multiple of ${String(prop['multipleOf'])}`)
|
|
2458
|
-
)
|
|
2432
|
+
ts.factory.createStringLiteral(`Number must be a multiple of ${String(prop['multipleOf'])}`)
|
|
2433
|
+
)
|
|
2434
|
+
]);
|
|
2435
|
+
numberSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(numberSchema, ts.factory.createIdentifier('refine')), undefined, [
|
|
2436
|
+
refineFunction,
|
|
2437
|
+
refineOptions
|
|
2459
2438
|
]);
|
|
2460
|
-
numberSchema = ts.factory.createCallExpression(
|
|
2461
|
-
ts.factory.createPropertyAccessExpression(numberSchema, ts.factory.createIdentifier('refine')),
|
|
2462
|
-
undefined,
|
|
2463
|
-
[refineFunction, refineOptions],
|
|
2464
|
-
);
|
|
2465
2439
|
}
|
|
2466
2440
|
|
|
2467
2441
|
return required
|
|
2468
2442
|
? numberSchema
|
|
2469
|
-
: ts.factory.createCallExpression(
|
|
2470
|
-
ts.factory.createPropertyAccessExpression(numberSchema, ts.factory.createIdentifier('optional')),
|
|
2471
|
-
undefined,
|
|
2472
|
-
[],
|
|
2473
|
-
);
|
|
2443
|
+
: ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(numberSchema, ts.factory.createIdentifier('optional')), undefined, []);
|
|
2474
2444
|
}
|
|
2475
2445
|
case 'string': {
|
|
2476
2446
|
let stringSchema = this.buildZodAST(['string']);
|
|
@@ -2480,67 +2450,48 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
2480
2450
|
switch (prop['format']) {
|
|
2481
2451
|
case 'email':
|
|
2482
2452
|
stringSchema = ts.factory.createCallExpression(
|
|
2483
|
-
ts.factory.createPropertyAccessExpression(
|
|
2484
|
-
ts.factory.createIdentifier('z'),
|
|
2485
|
-
ts.factory.createIdentifier('email'),
|
|
2486
|
-
),
|
|
2453
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('email')),
|
|
2487
2454
|
undefined,
|
|
2488
|
-
[]
|
|
2455
|
+
[]
|
|
2489
2456
|
);
|
|
2490
2457
|
break;
|
|
2491
2458
|
case 'uri':
|
|
2492
2459
|
case 'url':
|
|
2493
2460
|
stringSchema = ts.factory.createCallExpression(
|
|
2494
|
-
ts.factory.createPropertyAccessExpression(
|
|
2495
|
-
ts.factory.createIdentifier('z'),
|
|
2496
|
-
ts.factory.createIdentifier('url'),
|
|
2497
|
-
),
|
|
2461
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('url')),
|
|
2498
2462
|
undefined,
|
|
2499
|
-
[]
|
|
2463
|
+
[]
|
|
2500
2464
|
);
|
|
2501
2465
|
break;
|
|
2502
2466
|
case 'uuid':
|
|
2503
2467
|
stringSchema = ts.factory.createCallExpression(
|
|
2504
|
-
ts.factory.createPropertyAccessExpression(
|
|
2505
|
-
ts.factory.createIdentifier('z'),
|
|
2506
|
-
ts.factory.createIdentifier('uuid'),
|
|
2507
|
-
),
|
|
2468
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('uuid')),
|
|
2508
2469
|
undefined,
|
|
2509
|
-
[]
|
|
2470
|
+
[]
|
|
2510
2471
|
);
|
|
2511
2472
|
break;
|
|
2512
2473
|
case 'date-time':
|
|
2513
2474
|
stringSchema = ts.factory.createCallExpression(
|
|
2514
2475
|
ts.factory.createPropertyAccessExpression(
|
|
2515
|
-
ts.factory.createPropertyAccessExpression(
|
|
2516
|
-
|
|
2517
|
-
ts.factory.createIdentifier('iso'),
|
|
2518
|
-
),
|
|
2519
|
-
ts.factory.createIdentifier('datetime'),
|
|
2476
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('iso')),
|
|
2477
|
+
ts.factory.createIdentifier('datetime')
|
|
2520
2478
|
),
|
|
2521
2479
|
undefined,
|
|
2522
|
-
[this.buildDefaultValue({local: true})]
|
|
2480
|
+
[this.buildDefaultValue({ local: true })]
|
|
2523
2481
|
);
|
|
2524
2482
|
break;
|
|
2525
2483
|
case 'date':
|
|
2526
2484
|
stringSchema = ts.factory.createCallExpression(
|
|
2527
2485
|
ts.factory.createPropertyAccessExpression(
|
|
2528
|
-
ts.factory.createPropertyAccessExpression(
|
|
2529
|
-
|
|
2530
|
-
ts.factory.createIdentifier('iso'),
|
|
2531
|
-
),
|
|
2532
|
-
ts.factory.createIdentifier('date'),
|
|
2486
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('iso')),
|
|
2487
|
+
ts.factory.createIdentifier('date')
|
|
2533
2488
|
),
|
|
2534
2489
|
undefined,
|
|
2535
|
-
[]
|
|
2490
|
+
[]
|
|
2536
2491
|
);
|
|
2537
2492
|
break;
|
|
2538
2493
|
case 'time':
|
|
2539
|
-
stringSchema = ts.factory.createCallExpression(
|
|
2540
|
-
ts.factory.createPropertyAccessExpression(stringSchema, ts.factory.createIdentifier('time')),
|
|
2541
|
-
undefined,
|
|
2542
|
-
[],
|
|
2543
|
-
);
|
|
2494
|
+
stringSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(stringSchema, ts.factory.createIdentifier('time')), undefined, []);
|
|
2544
2495
|
break;
|
|
2545
2496
|
// Add more formats as needed
|
|
2546
2497
|
}
|
|
@@ -2548,74 +2499,49 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
2548
2499
|
|
|
2549
2500
|
// Apply string constraints
|
|
2550
2501
|
if (typeof prop['minLength'] === 'number') {
|
|
2551
|
-
stringSchema = ts.factory.createCallExpression(
|
|
2552
|
-
ts.factory.
|
|
2553
|
-
|
|
2554
|
-
[ts.factory.createNumericLiteral(String(prop['minLength']))],
|
|
2555
|
-
);
|
|
2502
|
+
stringSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(stringSchema, ts.factory.createIdentifier('min')), undefined, [
|
|
2503
|
+
ts.factory.createNumericLiteral(String(prop['minLength']))
|
|
2504
|
+
]);
|
|
2556
2505
|
}
|
|
2506
|
+
|
|
2557
2507
|
if (typeof prop['maxLength'] === 'number') {
|
|
2558
|
-
stringSchema = ts.factory.createCallExpression(
|
|
2559
|
-
ts.factory.
|
|
2560
|
-
|
|
2561
|
-
[ts.factory.createNumericLiteral(String(prop['maxLength']))],
|
|
2562
|
-
);
|
|
2508
|
+
stringSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(stringSchema, ts.factory.createIdentifier('max')), undefined, [
|
|
2509
|
+
ts.factory.createNumericLiteral(String(prop['maxLength']))
|
|
2510
|
+
]);
|
|
2563
2511
|
}
|
|
2512
|
+
|
|
2564
2513
|
if (prop['pattern'] && typeof prop['pattern'] === 'string') {
|
|
2565
|
-
stringSchema = ts.factory.createCallExpression(
|
|
2566
|
-
ts.factory.
|
|
2567
|
-
|
|
2568
|
-
[
|
|
2569
|
-
ts.factory.createNewExpression(ts.factory.createIdentifier('RegExp'), undefined, [
|
|
2570
|
-
ts.factory.createStringLiteral(prop['pattern'], true),
|
|
2571
|
-
]),
|
|
2572
|
-
],
|
|
2573
|
-
);
|
|
2514
|
+
stringSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(stringSchema, ts.factory.createIdentifier('regex')), undefined, [
|
|
2515
|
+
ts.factory.createNewExpression(ts.factory.createIdentifier('RegExp'), undefined, [ts.factory.createStringLiteral(prop['pattern'], true)])
|
|
2516
|
+
]);
|
|
2574
2517
|
}
|
|
2575
2518
|
|
|
2576
2519
|
// Apply default value if not required
|
|
2577
2520
|
if (!required && prop['default'] !== undefined) {
|
|
2578
2521
|
const defaultValue = this.buildDefaultValue(prop['default']);
|
|
2579
|
-
stringSchema = ts.factory.createCallExpression(
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
[defaultValue],
|
|
2583
|
-
);
|
|
2522
|
+
stringSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(stringSchema, ts.factory.createIdentifier('default')), undefined, [
|
|
2523
|
+
defaultValue
|
|
2524
|
+
]);
|
|
2584
2525
|
}
|
|
2585
2526
|
|
|
2586
2527
|
return required
|
|
2587
2528
|
? stringSchema
|
|
2588
|
-
: ts.factory.createCallExpression(
|
|
2589
|
-
ts.factory.createPropertyAccessExpression(stringSchema, ts.factory.createIdentifier('optional')),
|
|
2590
|
-
undefined,
|
|
2591
|
-
[],
|
|
2592
|
-
);
|
|
2529
|
+
: ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(stringSchema, ts.factory.createIdentifier('optional')), undefined, []);
|
|
2593
2530
|
}
|
|
2594
2531
|
case 'boolean': {
|
|
2595
2532
|
let booleanSchema = this.buildZodAST(['boolean']);
|
|
2596
2533
|
|
|
2597
2534
|
// Apply default value if not required
|
|
2598
2535
|
if (!required && prop['default'] !== undefined) {
|
|
2599
|
-
const defaultValue =
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
: ts.factory.createFalse()
|
|
2604
|
-
: ts.factory.createFalse();
|
|
2605
|
-
booleanSchema = ts.factory.createCallExpression(
|
|
2606
|
-
ts.factory.createPropertyAccessExpression(booleanSchema, ts.factory.createIdentifier('default')),
|
|
2607
|
-
undefined,
|
|
2608
|
-
[defaultValue],
|
|
2609
|
-
);
|
|
2536
|
+
const defaultValue = typeof prop['default'] === 'boolean' ? (prop['default'] ? ts.factory.createTrue() : ts.factory.createFalse()) : ts.factory.createFalse();
|
|
2537
|
+
booleanSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(booleanSchema, ts.factory.createIdentifier('default')), undefined, [
|
|
2538
|
+
defaultValue
|
|
2539
|
+
]);
|
|
2610
2540
|
}
|
|
2611
2541
|
|
|
2612
2542
|
return required
|
|
2613
2543
|
? booleanSchema
|
|
2614
|
-
: ts.factory.createCallExpression(
|
|
2615
|
-
ts.factory.createPropertyAccessExpression(booleanSchema, ts.factory.createIdentifier('optional')),
|
|
2616
|
-
undefined,
|
|
2617
|
-
[],
|
|
2618
|
-
);
|
|
2544
|
+
: ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(booleanSchema, ts.factory.createIdentifier('optional')), undefined, []);
|
|
2619
2545
|
}
|
|
2620
2546
|
case 'unknown':
|
|
2621
2547
|
default:
|
|
@@ -2627,54 +2553,52 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
2627
2553
|
if (typeof value === 'string') {
|
|
2628
2554
|
return ts.factory.createStringLiteral(value, true);
|
|
2629
2555
|
}
|
|
2556
|
+
|
|
2630
2557
|
if (typeof value === 'number') {
|
|
2631
2558
|
return ts.factory.createNumericLiteral(String(value));
|
|
2632
2559
|
}
|
|
2560
|
+
|
|
2633
2561
|
if (typeof value === 'boolean') {
|
|
2634
2562
|
return value ? ts.factory.createTrue() : ts.factory.createFalse();
|
|
2635
2563
|
}
|
|
2564
|
+
|
|
2636
2565
|
if (value === null) {
|
|
2637
2566
|
return ts.factory.createNull();
|
|
2638
2567
|
}
|
|
2568
|
+
|
|
2639
2569
|
if (Array.isArray(value)) {
|
|
2640
2570
|
return ts.factory.createArrayLiteralExpression(
|
|
2641
2571
|
value.map((item) => this.buildDefaultValue(item)),
|
|
2642
|
-
false
|
|
2572
|
+
false
|
|
2643
2573
|
);
|
|
2644
2574
|
}
|
|
2575
|
+
|
|
2645
2576
|
if (typeof value === 'object') {
|
|
2646
2577
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
2647
2578
|
if (value === null) {
|
|
2648
2579
|
return ts.factory.createNull();
|
|
2649
2580
|
}
|
|
2581
|
+
|
|
2650
2582
|
return ts.factory.createObjectLiteralExpression(
|
|
2651
|
-
Object.entries(value).map(([key, val]) =>
|
|
2652
|
-
|
|
2653
|
-
),
|
|
2654
|
-
true,
|
|
2583
|
+
Object.entries(value).map(([key, val]) => ts.factory.createPropertyAssignment(ts.factory.createIdentifier(key), this.buildDefaultValue(val))),
|
|
2584
|
+
true
|
|
2655
2585
|
);
|
|
2656
2586
|
}
|
|
2587
|
+
|
|
2657
2588
|
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
|
|
2658
2589
|
return ts.factory.createStringLiteral(String(value), true);
|
|
2659
2590
|
}
|
|
2591
|
+
|
|
2660
2592
|
// For objects and arrays, we need to handle them differently
|
|
2661
2593
|
// This should not happen in practice, but we handle it for type safety
|
|
2662
2594
|
return ts.factory.createStringLiteral(JSON.stringify(value), true);
|
|
2663
2595
|
}
|
|
2664
2596
|
|
|
2665
|
-
private handleLogicalOperator(
|
|
2666
|
-
operator: 'anyOf' | 'oneOf' | 'allOf' | 'not',
|
|
2667
|
-
schemas: unknown[],
|
|
2668
|
-
required: boolean,
|
|
2669
|
-
): ts.CallExpression {
|
|
2597
|
+
private handleLogicalOperator(operator: 'anyOf' | 'oneOf' | 'allOf' | 'not', schemas: unknown[], required: boolean): ts.CallExpression {
|
|
2670
2598
|
const logicalExpression = this.buildLogicalOperator(operator, schemas);
|
|
2671
2599
|
return required
|
|
2672
2600
|
? logicalExpression
|
|
2673
|
-
: ts.factory.createCallExpression(
|
|
2674
|
-
ts.factory.createPropertyAccessExpression(logicalExpression, ts.factory.createIdentifier('optional')),
|
|
2675
|
-
undefined,
|
|
2676
|
-
[],
|
|
2677
|
-
);
|
|
2601
|
+
: ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(logicalExpression, ts.factory.createIdentifier('optional')), undefined, []);
|
|
2678
2602
|
}
|
|
2679
2603
|
|
|
2680
2604
|
private buildLogicalOperator(operator: 'anyOf' | 'oneOf' | 'allOf' | 'not', schemas: unknown[]): ts.CallExpression {
|
|
@@ -2682,14 +2606,9 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
2682
2606
|
case 'anyOf':
|
|
2683
2607
|
case 'oneOf': {
|
|
2684
2608
|
const unionSchemas = schemas.map((schema) => this.buildSchemaFromLogicalOperator(schema));
|
|
2685
|
-
return ts.factory.createCallExpression(
|
|
2686
|
-
ts.factory.
|
|
2687
|
-
|
|
2688
|
-
ts.factory.createIdentifier('union'),
|
|
2689
|
-
),
|
|
2690
|
-
undefined,
|
|
2691
|
-
[ts.factory.createArrayLiteralExpression(unionSchemas, false)],
|
|
2692
|
-
);
|
|
2609
|
+
return ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('union')), undefined, [
|
|
2610
|
+
ts.factory.createArrayLiteralExpression(unionSchemas, false)
|
|
2611
|
+
]);
|
|
2693
2612
|
}
|
|
2694
2613
|
case 'allOf': {
|
|
2695
2614
|
if (schemas.length === 0) {
|
|
@@ -2700,12 +2619,9 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
2700
2619
|
return schemas.slice(1).reduce<ts.Expression>((acc, schema) => {
|
|
2701
2620
|
const schemaExpression = this.buildSchemaFromLogicalOperator(schema);
|
|
2702
2621
|
return ts.factory.createCallExpression(
|
|
2703
|
-
ts.factory.createPropertyAccessExpression(
|
|
2704
|
-
ts.factory.createIdentifier('z'),
|
|
2705
|
-
ts.factory.createIdentifier('intersection'),
|
|
2706
|
-
),
|
|
2622
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('intersection')),
|
|
2707
2623
|
undefined,
|
|
2708
|
-
[acc, schemaExpression]
|
|
2624
|
+
[acc, schemaExpression]
|
|
2709
2625
|
);
|
|
2710
2626
|
}, firstSchema) as ts.CallExpression;
|
|
2711
2627
|
}
|
|
@@ -2713,11 +2629,8 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
2713
2629
|
const notSchema = this.buildSchemaFromLogicalOperator(schemas[0]);
|
|
2714
2630
|
return ts.factory.createCallExpression(
|
|
2715
2631
|
ts.factory.createPropertyAccessExpression(
|
|
2716
|
-
ts.factory.createPropertyAccessExpression(
|
|
2717
|
-
|
|
2718
|
-
ts.factory.createIdentifier('any'),
|
|
2719
|
-
),
|
|
2720
|
-
ts.factory.createIdentifier('refine'),
|
|
2632
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('any')),
|
|
2633
|
+
ts.factory.createIdentifier('refine')
|
|
2721
2634
|
),
|
|
2722
2635
|
undefined,
|
|
2723
2636
|
[
|
|
@@ -2729,20 +2642,15 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
2729
2642
|
ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
|
|
2730
2643
|
ts.factory.createPrefixUnaryExpression(
|
|
2731
2644
|
ts.SyntaxKind.ExclamationToken,
|
|
2732
|
-
ts.factory.createCallExpression(
|
|
2733
|
-
ts.factory.
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
),
|
|
2737
|
-
),
|
|
2645
|
+
ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(notSchema, ts.factory.createIdentifier('safeParse')), undefined, [
|
|
2646
|
+
ts.factory.createIdentifier('val')
|
|
2647
|
+
])
|
|
2648
|
+
)
|
|
2738
2649
|
),
|
|
2739
2650
|
ts.factory.createObjectLiteralExpression([
|
|
2740
|
-
ts.factory.createPropertyAssignment(
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
),
|
|
2744
|
-
]),
|
|
2745
|
-
],
|
|
2651
|
+
ts.factory.createPropertyAssignment(ts.factory.createIdentifier('message'), ts.factory.createStringLiteral('Value must not match the excluded schema'))
|
|
2652
|
+
])
|
|
2653
|
+
]
|
|
2746
2654
|
);
|
|
2747
2655
|
}
|
|
2748
2656
|
default:
|
|
@@ -2766,7 +2674,7 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
2766
2674
|
|
|
2767
2675
|
private buildBasicTypeFromSchema(schema: unknown): ts.CallExpression | ts.Identifier {
|
|
2768
2676
|
if (typeof schema === 'object' && schema !== null && 'type' in schema) {
|
|
2769
|
-
const schemaObj = schema as {type: string; properties?: Record<string, unknown>; items?: unknown};
|
|
2677
|
+
const schemaObj = schema as { type: string; properties?: Record<string, unknown>; items?: unknown };
|
|
2770
2678
|
|
|
2771
2679
|
switch (schemaObj.type) {
|
|
2772
2680
|
case 'string':
|
|
@@ -2789,7 +2697,7 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
2789
2697
|
return this.buildZodAST(['unknown']);
|
|
2790
2698
|
}
|
|
2791
2699
|
|
|
2792
|
-
private buildObjectTypeFromSchema(schemaObj: {properties?: Record<string, unknown>}): ts.CallExpression {
|
|
2700
|
+
private buildObjectTypeFromSchema(schemaObj: { properties?: Record<string, unknown> }): ts.CallExpression {
|
|
2793
2701
|
const properties = Object.entries(schemaObj.properties ?? {});
|
|
2794
2702
|
|
|
2795
2703
|
if (properties.length > 0) {
|
|
@@ -2799,71 +2707,63 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
2799
2707
|
args: [
|
|
2800
2708
|
ts.factory.createObjectLiteralExpression(
|
|
2801
2709
|
properties.map(([name, property]): ts.ObjectLiteralElementLike => {
|
|
2802
|
-
return ts.factory.createPropertyAssignment(
|
|
2803
|
-
ts.factory.createIdentifier(name),
|
|
2804
|
-
this.buildSchemaFromLogicalOperator(property),
|
|
2805
|
-
);
|
|
2710
|
+
return ts.factory.createPropertyAssignment(ts.factory.createIdentifier(name), this.buildSchemaFromLogicalOperator(property));
|
|
2806
2711
|
}),
|
|
2807
|
-
true
|
|
2808
|
-
)
|
|
2809
|
-
]
|
|
2810
|
-
}
|
|
2712
|
+
true
|
|
2713
|
+
)
|
|
2714
|
+
]
|
|
2715
|
+
}
|
|
2811
2716
|
]);
|
|
2812
2717
|
}
|
|
2813
2718
|
|
|
2814
2719
|
return this.buildZodAST([
|
|
2815
2720
|
{
|
|
2816
2721
|
type: 'record',
|
|
2817
|
-
args: [this.buildZodAST(['string']), this.buildZodAST(['unknown'])]
|
|
2818
|
-
}
|
|
2722
|
+
args: [this.buildZodAST(['string']), this.buildZodAST(['unknown'])]
|
|
2723
|
+
}
|
|
2819
2724
|
]);
|
|
2820
2725
|
}
|
|
2821
2726
|
|
|
2822
|
-
private buildArrayTypeFromSchema(schemaObj: {items?: unknown}): ts.CallExpression {
|
|
2727
|
+
private buildArrayTypeFromSchema(schemaObj: { items?: unknown }): ts.CallExpression {
|
|
2823
2728
|
if (schemaObj.items) {
|
|
2824
2729
|
return this.buildZodAST([
|
|
2825
2730
|
{
|
|
2826
2731
|
type: 'array',
|
|
2827
|
-
args: [this.buildSchemaFromLogicalOperator(schemaObj.items)]
|
|
2828
|
-
}
|
|
2732
|
+
args: [this.buildSchemaFromLogicalOperator(schemaObj.items)]
|
|
2733
|
+
}
|
|
2829
2734
|
]);
|
|
2830
2735
|
}
|
|
2736
|
+
|
|
2831
2737
|
return this.buildZodAST(['array']);
|
|
2832
2738
|
}
|
|
2833
2739
|
|
|
2834
2740
|
private isReference(reference: unknown): reference is ReferenceType {
|
|
2835
2741
|
if (typeof reference === 'object' && reference !== null && '$ref' in reference) {
|
|
2836
|
-
const ref = reference satisfies {$ref?: unknown};
|
|
2742
|
+
const ref = reference satisfies { $ref?: unknown };
|
|
2837
2743
|
return typeof ref.$ref === 'string' && ref.$ref.length > 0;
|
|
2838
2744
|
}
|
|
2745
|
+
|
|
2839
2746
|
return false;
|
|
2840
2747
|
}
|
|
2841
2748
|
|
|
2842
2749
|
private buildFromReference(reference: ReferenceType): ts.CallExpression | ts.Identifier {
|
|
2843
|
-
const {$ref = ''} = Reference.parse(reference);
|
|
2750
|
+
const { $ref = '' } = Reference.parse(reference);
|
|
2844
2751
|
const refName = $ref.split('/').pop() ?? 'never';
|
|
2845
2752
|
const sanitizedRefName = this.typeBuilder.sanitizeIdentifier(refName);
|
|
2846
2753
|
|
|
2847
2754
|
// Check if this reference creates a circular dependency
|
|
2848
2755
|
if (this.isCircularReference(refName)) {
|
|
2849
2756
|
// Generate: z.lazy(() => RefSchema)
|
|
2850
|
-
return ts.factory.createCallExpression(
|
|
2851
|
-
ts.factory.
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
ts.factory.
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
[],
|
|
2861
|
-
undefined,
|
|
2862
|
-
ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
|
|
2863
|
-
ts.factory.createIdentifier(sanitizedRefName),
|
|
2864
|
-
),
|
|
2865
|
-
],
|
|
2866
|
-
);
|
|
2757
|
+
return ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('lazy')), undefined, [
|
|
2758
|
+
ts.factory.createArrowFunction(
|
|
2759
|
+
undefined,
|
|
2760
|
+
undefined,
|
|
2761
|
+
[],
|
|
2762
|
+
undefined,
|
|
2763
|
+
ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
|
|
2764
|
+
ts.factory.createIdentifier(sanitizedRefName)
|
|
2765
|
+
)
|
|
2766
|
+
]);
|
|
2867
2767
|
}
|
|
2868
2768
|
|
|
2869
2769
|
return ts.factory.createIdentifier(sanitizedRefName);
|
|
@@ -2883,11 +2783,7 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
2883
2783
|
|
|
2884
2784
|
// Case 2: Reference to a schema that's part of a circular dependency chain
|
|
2885
2785
|
// and we're currently building a schema that's also in that chain
|
|
2886
|
-
if (
|
|
2887
|
-
this.circularSchemas.has(refName) &&
|
|
2888
|
-
this.currentSchemaName !== null &&
|
|
2889
|
-
this.circularSchemas.has(this.currentSchemaName)
|
|
2890
|
-
) {
|
|
2786
|
+
if (this.circularSchemas.has(refName) && this.currentSchemaName !== null && this.circularSchemas.has(this.currentSchemaName)) {
|
|
2891
2787
|
return true;
|
|
2892
2788
|
}
|
|
2893
2789
|
|
|
@@ -2905,11 +2801,7 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
2905
2801
|
// Build dependency graph
|
|
2906
2802
|
const graph = new Map<string, string[]>();
|
|
2907
2803
|
for (const [name, schema] of Object.entries(schemas)) {
|
|
2908
|
-
const dependencies =
|
|
2909
|
-
.query(schema, '$..["$ref"]')
|
|
2910
|
-
.filter((ref: string) => ref.startsWith('#/components/schemas/'))
|
|
2911
|
-
.map((ref: string) => ref.replace('#/components/schemas/', ''))
|
|
2912
|
-
.filter((dep: string) => dep in schemas);
|
|
2804
|
+
const dependencies = this.extractSchemaReferences(schema).filter((dep: string) => dep in schemas);
|
|
2913
2805
|
graph.set(name, dependencies);
|
|
2914
2806
|
}
|
|
2915
2807
|
|
|
@@ -2989,16 +2881,14 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
2989
2881
|
if (visiting.has(name)) {
|
|
2990
2882
|
return;
|
|
2991
2883
|
}
|
|
2884
|
+
|
|
2992
2885
|
if (visited.has(name)) {
|
|
2993
2886
|
return;
|
|
2994
2887
|
}
|
|
2995
2888
|
|
|
2996
2889
|
visiting.add(name);
|
|
2997
2890
|
const schema = schemas[name];
|
|
2998
|
-
const dependencies =
|
|
2999
|
-
.query(schema, '$..["$ref"]')
|
|
3000
|
-
.filter((ref: string) => ref.startsWith('#/components/schemas/'))
|
|
3001
|
-
.map((ref: string) => ref.replace('#/components/schemas/', ''));
|
|
2891
|
+
const dependencies = this.extractSchemaReferences(schema);
|
|
3002
2892
|
|
|
3003
2893
|
for (const dep of dependencies) {
|
|
3004
2894
|
if (schemas[dep]) {
|