zod-codegen 1.6.3 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.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 +17 -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 +3 -1
- package/dist/src/services/code-generator.service.d.ts.map +1 -1
- package/dist/src/services/code-generator.service.js +236 -219
- package/dist/src/services/file-reader.service.d.ts +2 -0
- package/dist/src/services/file-reader.service.d.ts.map +1 -1
- package/dist/src/services/file-reader.service.js +25 -11
- 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 +123 -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 +153 -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 +799 -1120
- package/src/services/file-reader.service.ts +35 -15
- 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 +53 -31
- 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 +431 -330
- package/tests/unit/file-reader.test.ts +58 -18
- 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 -371
- package/scripts/update-manifest.ts +0 -49
- package/src/assets/manifest.json +0 -5
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import jp from 'jsonpath';
|
|
2
1
|
import * as ts from 'typescript';
|
|
3
2
|
import { z } from 'zod';
|
|
4
3
|
import { MethodSchema, Reference, SchemaProperties } from '../types/openapi.js';
|
|
4
|
+
import { transformNamingConvention } from '../utils/naming-convention.js';
|
|
5
5
|
import { TypeScriptImportBuilderService } from './import-builder.service.js';
|
|
6
6
|
import { TypeScriptTypeBuilderService } from './type-builder.service.js';
|
|
7
|
-
import { transformNamingConvention, } from '../utils/naming-convention.js';
|
|
8
7
|
export class TypeScriptCodeGeneratorService {
|
|
9
8
|
typeBuilder = new TypeScriptTypeBuilderService();
|
|
10
9
|
importBuilder = new TypeScriptImportBuilderService();
|
|
@@ -20,10 +19,33 @@ export class TypeScriptCodeGeneratorService {
|
|
|
20
19
|
}
|
|
21
20
|
ZodAST = z.object({
|
|
22
21
|
type: z.enum(['string', 'number', 'boolean', 'object', 'array', 'unknown', 'record']),
|
|
23
|
-
args: z.array(z.unknown()).optional()
|
|
22
|
+
args: z.array(z.unknown()).optional()
|
|
24
23
|
});
|
|
24
|
+
extractSchemaReferences(schema) {
|
|
25
|
+
const references = new Set();
|
|
26
|
+
const walk = (node) => {
|
|
27
|
+
if (Array.isArray(node)) {
|
|
28
|
+
for (const item of node) {
|
|
29
|
+
walk(item);
|
|
30
|
+
}
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (node === null || typeof node !== 'object') {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
for (const [key, value] of Object.entries(node)) {
|
|
37
|
+
if (key === '$ref' && typeof value === 'string' && value.startsWith('#/components/schemas/')) {
|
|
38
|
+
references.add(value.replace('#/components/schemas/', ''));
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
walk(value);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
walk(schema);
|
|
45
|
+
return [...references];
|
|
46
|
+
}
|
|
25
47
|
generate(spec) {
|
|
26
|
-
const file = ts.createSourceFile('
|
|
48
|
+
const file = ts.createSourceFile('api.ts', '', ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
|
|
27
49
|
const nodes = this.buildAST(spec);
|
|
28
50
|
return this.printer.printList(ts.ListFormat.MultiLine, ts.factory.createNodeArray(nodes), file);
|
|
29
51
|
}
|
|
@@ -63,8 +85,9 @@ export class TypeScriptCodeGeneratorService {
|
|
|
63
85
|
...Object.values(schemas),
|
|
64
86
|
...schemaTypeAliases,
|
|
65
87
|
...serverConfig,
|
|
88
|
+
this.buildResponseValidationErrorClass(),
|
|
66
89
|
this.createComment('Client class'),
|
|
67
|
-
clientClass
|
|
90
|
+
clientClass
|
|
68
91
|
];
|
|
69
92
|
}
|
|
70
93
|
buildSchemas(openapi) {
|
|
@@ -75,8 +98,9 @@ export class TypeScriptCodeGeneratorService {
|
|
|
75
98
|
const sortedSchemaNames = this.topologicalSort(schemasMap);
|
|
76
99
|
return sortedSchemaNames.reduce((schemaRegistered, name) => {
|
|
77
100
|
const schema = openapi.components?.schemas?.[name];
|
|
78
|
-
if (!schema)
|
|
101
|
+
if (!schema) {
|
|
79
102
|
return schemaRegistered;
|
|
103
|
+
}
|
|
80
104
|
// Set context for current schema being built
|
|
81
105
|
this.currentSchemaName = name;
|
|
82
106
|
const schemaExpression = this.buildSchema(schema);
|
|
@@ -84,13 +108,13 @@ export class TypeScriptCodeGeneratorService {
|
|
|
84
108
|
this.currentSchemaName = null;
|
|
85
109
|
const sanitizedName = this.typeBuilder.sanitizeIdentifier(name);
|
|
86
110
|
// Add type annotation: z.ZodType<Name>
|
|
87
|
-
const typeAnnotation = ts.factory.createTypeReferenceNode(ts.factory.createQualifiedName(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('ZodType')), [
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
], ts.NodeFlags.Const));
|
|
111
|
+
const typeAnnotation = ts.factory.createTypeReferenceNode(ts.factory.createQualifiedName(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('ZodType')), [
|
|
112
|
+
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(sanitizedName), undefined)
|
|
113
|
+
]);
|
|
114
|
+
const variableStatement = ts.factory.createVariableStatement([ts.factory.createToken(ts.SyntaxKind.ExportKeyword)], ts.factory.createVariableDeclarationList([ts.factory.createVariableDeclaration(ts.factory.createIdentifier(sanitizedName), undefined, typeAnnotation, schemaExpression)], ts.NodeFlags.Const));
|
|
91
115
|
return {
|
|
92
116
|
...schemaRegistered,
|
|
93
|
-
[name]: variableStatement
|
|
117
|
+
[name]: variableStatement
|
|
94
118
|
};
|
|
95
119
|
}, {});
|
|
96
120
|
}
|
|
@@ -109,8 +133,9 @@ export class TypeScriptCodeGeneratorService {
|
|
|
109
133
|
const statements = [];
|
|
110
134
|
for (const name of sortedSchemaNames) {
|
|
111
135
|
const schema = openapi.components?.schemas?.[name];
|
|
112
|
-
if (!schema)
|
|
136
|
+
if (!schema) {
|
|
113
137
|
continue;
|
|
138
|
+
}
|
|
114
139
|
const sanitizedName = this.typeBuilder.sanitizeIdentifier(name);
|
|
115
140
|
const safeSchema = SchemaProperties.safeParse(schema);
|
|
116
141
|
if (!safeSchema.success) {
|
|
@@ -201,9 +226,7 @@ export class TypeScriptCodeGeneratorService {
|
|
|
201
226
|
case 'boolean':
|
|
202
227
|
return ts.factory.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword);
|
|
203
228
|
case 'array': {
|
|
204
|
-
const itemsType = prop['items']
|
|
205
|
-
? this.buildTypeNode(prop['items'])
|
|
206
|
-
: ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword);
|
|
229
|
+
const itemsType = prop['items'] ? this.buildTypeNode(prop['items']) : ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword);
|
|
207
230
|
return ts.factory.createArrayTypeNode(itemsType);
|
|
208
231
|
}
|
|
209
232
|
case 'object': {
|
|
@@ -215,7 +238,7 @@ export class TypeScriptCodeGeneratorService {
|
|
|
215
238
|
// Empty object or additionalProperties - use Record<string, unknown>
|
|
216
239
|
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Record'), [
|
|
217
240
|
ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
|
|
218
|
-
ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword)
|
|
241
|
+
ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword)
|
|
219
242
|
]);
|
|
220
243
|
}
|
|
221
244
|
default:
|
|
@@ -246,6 +269,25 @@ export class TypeScriptCodeGeneratorService {
|
|
|
246
269
|
});
|
|
247
270
|
return ts.factory.createInterfaceDeclaration([ts.factory.createToken(ts.SyntaxKind.ExportKeyword)], ts.factory.createIdentifier(name), undefined, undefined, members);
|
|
248
271
|
}
|
|
272
|
+
buildResponseValidationErrorClass() {
|
|
273
|
+
const typeParamT = ts.factory.createTypeParameterDeclaration(undefined, 'T');
|
|
274
|
+
const responseProperty = ts.factory.createPropertyDeclaration([ts.factory.createToken(ts.SyntaxKind.ReadonlyKeyword)], 'response', undefined, ts.factory.createTypeReferenceNode('Response'), undefined);
|
|
275
|
+
const errorProperty = ts.factory.createPropertyDeclaration([ts.factory.createToken(ts.SyntaxKind.ReadonlyKeyword)], 'error', undefined, ts.factory.createTypeReferenceNode(ts.factory.createQualifiedName(ts.factory.createIdentifier('z'), 'ZodError'), [ts.factory.createTypeReferenceNode('T')]), undefined);
|
|
276
|
+
const constructorDecl = ts.factory.createConstructorDeclaration(undefined, [
|
|
277
|
+
ts.factory.createParameterDeclaration(undefined, undefined, 'message', undefined, ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword)),
|
|
278
|
+
ts.factory.createParameterDeclaration(undefined, undefined, 'response', undefined, ts.factory.createTypeReferenceNode('Response')),
|
|
279
|
+
ts.factory.createParameterDeclaration(undefined, undefined, 'error', undefined, ts.factory.createTypeReferenceNode(ts.factory.createQualifiedName(ts.factory.createIdentifier('z'), 'ZodError'), [ts.factory.createTypeReferenceNode('T')]))
|
|
280
|
+
], ts.factory.createBlock([
|
|
281
|
+
ts.factory.createExpressionStatement(ts.factory.createCallExpression(ts.factory.createSuper(), undefined, [ts.factory.createIdentifier('message')])),
|
|
282
|
+
ts.factory.createExpressionStatement(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createThis(), 'name'), ts.SyntaxKind.EqualsToken, ts.factory.createAsExpression(ts.factory.createStringLiteral('ResponseValidationError', true), ts.factory.createTypeReferenceNode('const')))),
|
|
283
|
+
ts.factory.createExpressionStatement(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createThis(), 'response'), ts.SyntaxKind.EqualsToken, ts.factory.createIdentifier('response'))),
|
|
284
|
+
ts.factory.createExpressionStatement(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createThis(), 'error'), ts.SyntaxKind.EqualsToken, ts.factory.createIdentifier('error')))
|
|
285
|
+
], true));
|
|
286
|
+
const dataGetter = ts.factory.createGetAccessorDeclaration(undefined, 'data', [], ts.factory.createTypeReferenceNode('T'), ts.factory.createBlock([
|
|
287
|
+
ts.factory.createReturnStatement(ts.factory.createAsExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createPropertyAccessExpression(ts.factory.createThis(), 'response'), 'json'), undefined, []), ts.factory.createTypeReferenceNode('T')))
|
|
288
|
+
], true));
|
|
289
|
+
return ts.factory.createClassDeclaration([ts.factory.createToken(ts.SyntaxKind.ExportKeyword)], 'ResponseValidationError', [typeParamT], [ts.factory.createHeritageClause(ts.SyntaxKind.ExtendsKeyword, [ts.factory.createExpressionWithTypeArguments(ts.factory.createIdentifier('Error'), undefined)])], [responseProperty, errorProperty, constructorDecl, dataGetter]);
|
|
290
|
+
}
|
|
249
291
|
buildClientClass(openapi, schemas) {
|
|
250
292
|
const clientName = this.generateClientName(openapi.info.title);
|
|
251
293
|
const methods = this.buildClientMethods(openapi, schemas);
|
|
@@ -255,7 +297,7 @@ export class TypeScriptCodeGeneratorService {
|
|
|
255
297
|
this.buildGetBaseRequestOptionsMethod(),
|
|
256
298
|
this.buildHandleResponseMethod(),
|
|
257
299
|
this.buildHttpRequestMethod(),
|
|
258
|
-
...methods
|
|
300
|
+
...methods
|
|
259
301
|
]);
|
|
260
302
|
}
|
|
261
303
|
buildConstructor(openapi) {
|
|
@@ -263,24 +305,21 @@ export class TypeScriptCodeGeneratorService {
|
|
|
263
305
|
if (hasServers) {
|
|
264
306
|
// Options-based constructor
|
|
265
307
|
return ts.factory.createConstructorDeclaration(undefined, [
|
|
266
|
-
ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createIdentifier('options'), undefined, ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('ClientOptions'), undefined), undefined)
|
|
308
|
+
ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createIdentifier('options'), undefined, ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('ClientOptions'), undefined), undefined)
|
|
267
309
|
], ts.factory.createBlock([
|
|
268
310
|
ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([
|
|
269
311
|
ts.factory.createVariableDeclaration(ts.factory.createIdentifier('resolvedUrl'), undefined, undefined, ts.factory.createConditionalExpression(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('baseUrl')), ts.factory.createToken(ts.SyntaxKind.ExclamationEqualsEqualsToken), ts.factory.createNull()), ts.factory.createToken(ts.SyntaxKind.QuestionToken), ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('baseUrl')), ts.factory.createToken(ts.SyntaxKind.ColonToken), ts.factory.createCallExpression(ts.factory.createIdentifier('resolveServerUrl'), undefined, [
|
|
270
312
|
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('serverIndex')),
|
|
271
|
-
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('serverVariables'))
|
|
272
|
-
])))
|
|
313
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('serverVariables'))
|
|
314
|
+
])))
|
|
273
315
|
], ts.NodeFlags.Const)),
|
|
274
|
-
ts.factory.createExpressionStatement(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createThis(), ts.factory.createPrivateIdentifier('#baseUrl')), ts.factory.createToken(ts.SyntaxKind.EqualsToken), ts.factory.createIdentifier('resolvedUrl')))
|
|
316
|
+
ts.factory.createExpressionStatement(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createThis(), ts.factory.createPrivateIdentifier('#baseUrl')), ts.factory.createToken(ts.SyntaxKind.EqualsToken), ts.factory.createIdentifier('resolvedUrl')))
|
|
275
317
|
], true));
|
|
276
318
|
}
|
|
277
319
|
else {
|
|
278
320
|
// Fallback: simple baseUrl parameter
|
|
279
|
-
return ts.factory.createConstructorDeclaration(undefined, [
|
|
280
|
-
|
|
281
|
-
this.typeBuilder.createParameter('_', 'unknown', undefined, true),
|
|
282
|
-
], ts.factory.createBlock([
|
|
283
|
-
ts.factory.createExpressionStatement(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createThis(), ts.factory.createPrivateIdentifier('#baseUrl')), ts.factory.createToken(ts.SyntaxKind.EqualsToken), ts.factory.createIdentifier('baseUrl'))),
|
|
321
|
+
return ts.factory.createConstructorDeclaration(undefined, [this.typeBuilder.createParameter('baseUrl', 'string', ts.factory.createStringLiteral('/', true)), this.typeBuilder.createParameter('_', 'unknown', undefined, true)], ts.factory.createBlock([
|
|
322
|
+
ts.factory.createExpressionStatement(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createThis(), ts.factory.createPrivateIdentifier('#baseUrl')), ts.factory.createToken(ts.SyntaxKind.EqualsToken), ts.factory.createIdentifier('baseUrl')))
|
|
284
323
|
], true));
|
|
285
324
|
}
|
|
286
325
|
}
|
|
@@ -290,9 +329,9 @@ export class TypeScriptCodeGeneratorService {
|
|
|
290
329
|
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('RequestInit'), undefined),
|
|
291
330
|
ts.factory.createUnionTypeNode([
|
|
292
331
|
ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral('method', true)),
|
|
293
|
-
ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral('body', true))
|
|
294
|
-
])
|
|
295
|
-
])
|
|
332
|
+
ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral('body', true))
|
|
333
|
+
])
|
|
334
|
+
])
|
|
296
335
|
]), ts.factory.createBlock([ts.factory.createReturnStatement(ts.factory.createObjectLiteralExpression([], false))], true));
|
|
297
336
|
}
|
|
298
337
|
buildHandleResponseMethod() {
|
|
@@ -300,76 +339,66 @@ export class TypeScriptCodeGeneratorService {
|
|
|
300
339
|
this.typeBuilder.createParameter('response', 'Response'),
|
|
301
340
|
this.typeBuilder.createParameter('method', 'string'),
|
|
302
341
|
this.typeBuilder.createParameter('path', 'string'),
|
|
303
|
-
this.typeBuilder.createParameter('options', '{params?: Record<string, string | number | boolean>; data?: unknown; contentType?: string; headers?: Record<string, string>}')
|
|
304
|
-
], ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
|
|
305
|
-
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Response'), undefined),
|
|
306
|
-
]), ts.factory.createBlock([ts.factory.createReturnStatement(ts.factory.createIdentifier('response'))], true));
|
|
342
|
+
this.typeBuilder.createParameter('options', '{params?: Record<string, string | number | boolean>; data?: unknown; contentType?: string; headers?: Record<string, string>}')
|
|
343
|
+
], ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Response'), undefined)]), ts.factory.createBlock([ts.factory.createReturnStatement(ts.factory.createIdentifier('response'))], true));
|
|
307
344
|
}
|
|
308
345
|
buildHttpRequestMethod() {
|
|
309
346
|
return ts.factory.createMethodDeclaration([ts.factory.createToken(ts.SyntaxKind.ProtectedKeyword), ts.factory.createToken(ts.SyntaxKind.AsyncKeyword)], undefined, ts.factory.createIdentifier('makeRequest'), undefined, [this.typeBuilder.createGenericType('T')], [
|
|
310
347
|
this.typeBuilder.createParameter('method', 'string'),
|
|
311
348
|
this.typeBuilder.createParameter('path', 'string'),
|
|
312
|
-
this.typeBuilder.createParameter('options', '{params?: Record<string, string | number | boolean>; data?: unknown; contentType?: string; headers?: Record<string, string>}', ts.factory.createObjectLiteralExpression([], false), false)
|
|
313
|
-
], ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
|
|
314
|
-
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('T'), undefined),
|
|
315
|
-
]), ts.factory.createBlock([
|
|
349
|
+
this.typeBuilder.createParameter('options', '{params?: Record<string, string | number | boolean>; data?: unknown; contentType?: string; headers?: Record<string, string>}', ts.factory.createObjectLiteralExpression([], false), false)
|
|
350
|
+
], ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('T'), undefined)]), ts.factory.createBlock([
|
|
316
351
|
// Create initial URL object that we will use to build the final URL
|
|
317
352
|
ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([
|
|
318
353
|
ts.factory.createVariableDeclaration(ts.factory.createIdentifier('baseUrl'), undefined, undefined, ts.factory.createNewExpression(ts.factory.createIdentifier('URL'), undefined, [
|
|
319
354
|
ts.factory.createIdentifier('path'),
|
|
320
|
-
ts.factory.createPropertyAccessExpression(ts.factory.createThis(), ts.factory.createPrivateIdentifier('#baseUrl'))
|
|
321
|
-
]))
|
|
355
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createThis(), ts.factory.createPrivateIdentifier('#baseUrl'))
|
|
356
|
+
]))
|
|
322
357
|
], ts.NodeFlags.Const)),
|
|
323
358
|
ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([
|
|
324
|
-
ts.factory.createVariableDeclaration(ts.factory.createIdentifier('url'), undefined, undefined, ts.factory.createConditionalExpression(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('params')), ts.factory.createToken(ts.SyntaxKind.AmpersandAmpersandToken), ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('Object'), ts.factory.createIdentifier('keys')), undefined, [
|
|
325
|
-
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('params')),
|
|
326
|
-
]), ts.factory.createIdentifier('length')), ts.factory.createToken(ts.SyntaxKind.GreaterThanToken), ts.factory.createNumericLiteral('0'))), undefined, ts.factory.createCallExpression(ts.factory.createParenthesizedExpression(ts.factory.createArrowFunction(undefined, undefined, [], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createBlock([
|
|
327
|
-
ts.factory.createExpressionStatement(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('Object'), ts.factory.createIdentifier('entries')), undefined, [
|
|
328
|
-
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('params')),
|
|
329
|
-
]), ts.factory.createIdentifier('filter')), undefined, [
|
|
359
|
+
ts.factory.createVariableDeclaration(ts.factory.createIdentifier('url'), undefined, undefined, ts.factory.createConditionalExpression(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('params')), ts.factory.createToken(ts.SyntaxKind.AmpersandAmpersandToken), ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('Object'), ts.factory.createIdentifier('keys')), undefined, [ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('params'))]), ts.factory.createIdentifier('length')), ts.factory.createToken(ts.SyntaxKind.GreaterThanToken), ts.factory.createNumericLiteral('0'))), undefined, ts.factory.createCallExpression(ts.factory.createParenthesizedExpression(ts.factory.createArrowFunction(undefined, undefined, [], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createBlock([
|
|
360
|
+
ts.factory.createExpressionStatement(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('Object'), ts.factory.createIdentifier('entries')), undefined, [ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('params'))]), ts.factory.createIdentifier('filter')), undefined, [
|
|
330
361
|
ts.factory.createArrowFunction(undefined, undefined, [
|
|
331
362
|
ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createArrayBindingPattern([
|
|
332
363
|
ts.factory.createBindingElement(undefined, undefined, ts.factory.createIdentifier(''), undefined),
|
|
333
|
-
ts.factory.createBindingElement(undefined, undefined, ts.factory.createIdentifier('value'), undefined)
|
|
334
|
-
]), undefined, undefined)
|
|
335
|
-
], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createBinaryExpression(ts.factory.createIdentifier('value'), ts.SyntaxKind.ExclamationEqualsEqualsToken, ts.factory.createIdentifier('undefined')))
|
|
364
|
+
ts.factory.createBindingElement(undefined, undefined, ts.factory.createIdentifier('value'), undefined)
|
|
365
|
+
]), undefined, undefined)
|
|
366
|
+
], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createBinaryExpression(ts.factory.createIdentifier('value'), ts.SyntaxKind.ExclamationEqualsEqualsToken, ts.factory.createIdentifier('undefined')))
|
|
336
367
|
]), ts.factory.createIdentifier('forEach')), undefined, [
|
|
337
368
|
ts.factory.createArrowFunction(undefined, undefined, [
|
|
338
369
|
ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createArrayBindingPattern([
|
|
339
370
|
ts.factory.createBindingElement(undefined, undefined, ts.factory.createIdentifier('key'), undefined),
|
|
340
|
-
ts.factory.createBindingElement(undefined, undefined, ts.factory.createIdentifier('value'), undefined)
|
|
341
|
-
]), undefined, undefined)
|
|
371
|
+
ts.factory.createBindingElement(undefined, undefined, ts.factory.createIdentifier('value'), undefined)
|
|
372
|
+
]), undefined, undefined)
|
|
342
373
|
], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createBlock([
|
|
343
374
|
ts.factory.createExpressionStatement(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('baseUrl'), ts.factory.createIdentifier('searchParams')), ts.factory.createIdentifier('set')), undefined, [
|
|
344
375
|
ts.factory.createIdentifier('key'),
|
|
345
|
-
ts.factory.createCallExpression(ts.factory.createIdentifier('String'), undefined, [ts.factory.createIdentifier('value')])
|
|
346
|
-
]))
|
|
347
|
-
], false))
|
|
376
|
+
ts.factory.createCallExpression(ts.factory.createIdentifier('String'), undefined, [ts.factory.createIdentifier('value')])
|
|
377
|
+
]))
|
|
378
|
+
], false))
|
|
348
379
|
])),
|
|
349
|
-
ts.factory.createReturnStatement(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('baseUrl'), ts.factory.createIdentifier('toString')), undefined, []))
|
|
350
|
-
], true))), undefined, []), undefined, ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('baseUrl'), ts.factory.createIdentifier('toString')), undefined, [])))
|
|
380
|
+
ts.factory.createReturnStatement(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('baseUrl'), ts.factory.createIdentifier('toString')), undefined, []))
|
|
381
|
+
], true))), undefined, []), undefined, ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('baseUrl'), ts.factory.createIdentifier('toString')), undefined, [])))
|
|
351
382
|
], ts.NodeFlags.Const)),
|
|
352
383
|
// Get base request options (headers, signal, credentials, etc.)
|
|
353
384
|
ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([
|
|
354
|
-
ts.factory.createVariableDeclaration(ts.factory.createIdentifier('baseOptions'), undefined, undefined, ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createThis(), ts.factory.createIdentifier('getBaseRequestOptions')), undefined, []))
|
|
385
|
+
ts.factory.createVariableDeclaration(ts.factory.createIdentifier('baseOptions'), undefined, undefined, ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createThis(), ts.factory.createIdentifier('getBaseRequestOptions')), undefined, []))
|
|
355
386
|
], ts.NodeFlags.Const)),
|
|
356
387
|
// Build Content-Type header
|
|
357
388
|
ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([
|
|
358
|
-
ts.factory.createVariableDeclaration(ts.factory.createIdentifier('contentType'), undefined, undefined, ts.factory.createConditionalExpression(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('contentType')), ts.factory.createToken(ts.SyntaxKind.EqualsEqualsEqualsToken), ts.factory.createStringLiteral('application/x-www-form-urlencoded', true)), undefined, ts.factory.createStringLiteral('application/x-www-form-urlencoded', true), undefined, ts.factory.createStringLiteral('application/json', true)))
|
|
389
|
+
ts.factory.createVariableDeclaration(ts.factory.createIdentifier('contentType'), undefined, undefined, ts.factory.createConditionalExpression(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('contentType')), ts.factory.createToken(ts.SyntaxKind.EqualsEqualsEqualsToken), ts.factory.createStringLiteral('application/x-www-form-urlencoded', true)), undefined, ts.factory.createStringLiteral('application/x-www-form-urlencoded', true), undefined, ts.factory.createStringLiteral('application/json', true)))
|
|
359
390
|
], ts.NodeFlags.Const)),
|
|
360
391
|
// Merge headers: base headers, Content-Type, and request-specific headers
|
|
361
392
|
ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([
|
|
362
|
-
ts.factory.createVariableDeclaration(ts.factory.createIdentifier('baseHeaders'), undefined, undefined, ts.factory.createConditionalExpression(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('baseOptions'), ts.factory.createIdentifier('headers')), ts.factory.createToken(ts.SyntaxKind.ExclamationEqualsEqualsToken), ts.factory.createIdentifier('undefined')), undefined, ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('baseOptions'), ts.factory.createIdentifier('headers')), undefined, ts.factory.createObjectLiteralExpression([], false)))
|
|
393
|
+
ts.factory.createVariableDeclaration(ts.factory.createIdentifier('baseHeaders'), undefined, undefined, ts.factory.createConditionalExpression(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('baseOptions'), ts.factory.createIdentifier('headers')), ts.factory.createToken(ts.SyntaxKind.ExclamationEqualsEqualsToken), ts.factory.createIdentifier('undefined')), undefined, ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('baseOptions'), ts.factory.createIdentifier('headers')), undefined, ts.factory.createObjectLiteralExpression([], false)))
|
|
363
394
|
], ts.NodeFlags.Const)),
|
|
364
395
|
ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([
|
|
365
396
|
ts.factory.createVariableDeclaration(ts.factory.createIdentifier('headers'), undefined, undefined, ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('Object'), ts.factory.createIdentifier('assign')), undefined, [
|
|
366
397
|
ts.factory.createObjectLiteralExpression([], false),
|
|
367
398
|
ts.factory.createIdentifier('baseHeaders'),
|
|
368
|
-
ts.factory.createObjectLiteralExpression([
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
ts.factory.createConditionalExpression(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('headers')), ts.factory.createToken(ts.SyntaxKind.ExclamationEqualsEqualsToken), ts.factory.createIdentifier('undefined')), undefined, ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('headers')), undefined, ts.factory.createObjectLiteralExpression([], false)),
|
|
372
|
-
])),
|
|
399
|
+
ts.factory.createObjectLiteralExpression([ts.factory.createPropertyAssignment(ts.factory.createStringLiteral('Content-Type', true), ts.factory.createIdentifier('contentType'))], false),
|
|
400
|
+
ts.factory.createConditionalExpression(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('headers')), ts.factory.createToken(ts.SyntaxKind.ExclamationEqualsEqualsToken), ts.factory.createIdentifier('undefined')), undefined, ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('headers')), undefined, ts.factory.createObjectLiteralExpression([], false))
|
|
401
|
+
]))
|
|
373
402
|
], ts.NodeFlags.Const)),
|
|
374
403
|
// Build body with form-urlencoded support
|
|
375
404
|
ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([
|
|
@@ -377,29 +406,25 @@ export class TypeScriptCodeGeneratorService {
|
|
|
377
406
|
// Form-urlencoded: convert object to URLSearchParams
|
|
378
407
|
ts.factory.createCallExpression(ts.factory.createParenthesizedExpression(ts.factory.createArrowFunction(undefined, undefined, [], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createBlock([
|
|
379
408
|
ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([
|
|
380
|
-
ts.factory.createVariableDeclaration(ts.factory.createIdentifier('params'), undefined, undefined, ts.factory.createNewExpression(ts.factory.createIdentifier('URLSearchParams'), undefined, []))
|
|
409
|
+
ts.factory.createVariableDeclaration(ts.factory.createIdentifier('params'), undefined, undefined, ts.factory.createNewExpression(ts.factory.createIdentifier('URLSearchParams'), undefined, []))
|
|
381
410
|
], ts.NodeFlags.Const)),
|
|
382
|
-
ts.factory.createExpressionStatement(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('Object'), ts.factory.createIdentifier('entries')), undefined, [
|
|
383
|
-
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('data')),
|
|
384
|
-
]), ts.factory.createIdentifier('forEach')), undefined, [
|
|
411
|
+
ts.factory.createExpressionStatement(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('Object'), ts.factory.createIdentifier('entries')), undefined, [ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('data'))]), ts.factory.createIdentifier('forEach')), undefined, [
|
|
385
412
|
ts.factory.createArrowFunction(undefined, undefined, [
|
|
386
413
|
ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createArrayBindingPattern([
|
|
387
414
|
ts.factory.createBindingElement(undefined, undefined, ts.factory.createIdentifier('key'), undefined),
|
|
388
|
-
ts.factory.createBindingElement(undefined, undefined, ts.factory.createIdentifier('value'), undefined)
|
|
389
|
-
]), undefined, undefined)
|
|
415
|
+
ts.factory.createBindingElement(undefined, undefined, ts.factory.createIdentifier('value'), undefined)
|
|
416
|
+
]), undefined, undefined)
|
|
390
417
|
], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createBlock([
|
|
391
418
|
ts.factory.createExpressionStatement(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('params'), ts.factory.createIdentifier('set')), undefined, [
|
|
392
419
|
ts.factory.createIdentifier('key'),
|
|
393
|
-
ts.factory.createCallExpression(ts.factory.createIdentifier('String'), undefined, [ts.factory.createIdentifier('value')])
|
|
394
|
-
]))
|
|
395
|
-
], false))
|
|
420
|
+
ts.factory.createCallExpression(ts.factory.createIdentifier('String'), undefined, [ts.factory.createIdentifier('value')])
|
|
421
|
+
]))
|
|
422
|
+
], false))
|
|
396
423
|
])),
|
|
397
|
-
ts.factory.createReturnStatement(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('params'), ts.factory.createIdentifier('toString')), undefined, []))
|
|
424
|
+
ts.factory.createReturnStatement(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('params'), ts.factory.createIdentifier('toString')), undefined, []))
|
|
398
425
|
], false))), undefined, []), undefined,
|
|
399
426
|
// JSON: stringify the data
|
|
400
|
-
ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('JSON'), ts.factory.createIdentifier('stringify')), undefined, [
|
|
401
|
-
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('data')),
|
|
402
|
-
])), undefined, ts.factory.createNull())),
|
|
427
|
+
ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('JSON'), ts.factory.createIdentifier('stringify')), undefined, [ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('options'), ts.factory.createIdentifier('data'))])), undefined, ts.factory.createNull()))
|
|
403
428
|
], ts.NodeFlags.Const)),
|
|
404
429
|
// Make fetch request: merge base options with method, headers, and body
|
|
405
430
|
ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([
|
|
@@ -411,10 +436,10 @@ export class TypeScriptCodeGeneratorService {
|
|
|
411
436
|
ts.factory.createObjectLiteralExpression([
|
|
412
437
|
ts.factory.createShorthandPropertyAssignment(ts.factory.createIdentifier('method'), undefined),
|
|
413
438
|
ts.factory.createPropertyAssignment(ts.factory.createIdentifier('headers'), ts.factory.createIdentifier('headers')),
|
|
414
|
-
ts.factory.createPropertyAssignment(ts.factory.createIdentifier('body'), ts.factory.createIdentifier('body'))
|
|
415
|
-
], false)
|
|
416
|
-
])
|
|
417
|
-
])))
|
|
439
|
+
ts.factory.createPropertyAssignment(ts.factory.createIdentifier('body'), ts.factory.createIdentifier('body'))
|
|
440
|
+
], false)
|
|
441
|
+
])
|
|
442
|
+
])))
|
|
418
443
|
], ts.NodeFlags.Const)),
|
|
419
444
|
// Handle response through hook (allows subclasses to intercept and modify response)
|
|
420
445
|
ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([
|
|
@@ -422,18 +447,18 @@ export class TypeScriptCodeGeneratorService {
|
|
|
422
447
|
ts.factory.createIdentifier('rawResponse'),
|
|
423
448
|
ts.factory.createIdentifier('method'),
|
|
424
449
|
ts.factory.createIdentifier('path'),
|
|
425
|
-
ts.factory.createIdentifier('options')
|
|
426
|
-
])))
|
|
450
|
+
ts.factory.createIdentifier('options')
|
|
451
|
+
])))
|
|
427
452
|
], ts.NodeFlags.Const)),
|
|
428
453
|
// Check response status
|
|
429
454
|
ts.factory.createIfStatement(ts.factory.createPrefixUnaryExpression(ts.SyntaxKind.ExclamationToken, ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('response'), ts.factory.createIdentifier('ok'))), ts.factory.createThrowStatement(ts.factory.createNewExpression(ts.factory.createIdentifier('Error'), undefined, [
|
|
430
455
|
ts.factory.createTemplateExpression(ts.factory.createTemplateHead('HTTP ', 'HTTP '), [
|
|
431
456
|
ts.factory.createTemplateSpan(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('response'), ts.factory.createIdentifier('status')), ts.factory.createTemplateMiddle(': ', ': ')),
|
|
432
|
-
ts.factory.createTemplateSpan(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('response'), ts.factory.createIdentifier('statusText')), ts.factory.createTemplateTail('', ''))
|
|
433
|
-
])
|
|
457
|
+
ts.factory.createTemplateSpan(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('response'), ts.factory.createIdentifier('statusText')), ts.factory.createTemplateTail('', ''))
|
|
458
|
+
])
|
|
434
459
|
])), undefined),
|
|
435
460
|
// Return parsed JSON
|
|
436
|
-
ts.factory.createReturnStatement(ts.factory.createAwaitExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('response'), ts.factory.createIdentifier('json')), undefined, [])))
|
|
461
|
+
ts.factory.createReturnStatement(ts.factory.createAwaitExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('response'), ts.factory.createIdentifier('json')), undefined, [])))
|
|
437
462
|
], true));
|
|
438
463
|
}
|
|
439
464
|
buildClientMethods(openapi, schemas) {
|
|
@@ -479,7 +504,7 @@ export class TypeScriptCodeGeneratorService {
|
|
|
479
504
|
// This will be handled in transformOperationName
|
|
480
505
|
const modifiedSchema = {
|
|
481
506
|
...safeMethodSchema,
|
|
482
|
-
operationId: `${operationId}_${methodLower}
|
|
507
|
+
operationId: `${operationId}_${methodLower}`
|
|
483
508
|
};
|
|
484
509
|
return this.buildEndpointMethod(method, path, modifiedSchema, schemas);
|
|
485
510
|
}
|
|
@@ -504,7 +529,7 @@ export class TypeScriptCodeGeneratorService {
|
|
|
504
529
|
path,
|
|
505
530
|
...(schema.tags !== undefined && { tags: schema.tags }),
|
|
506
531
|
...(schema.summary !== undefined && { summary: schema.summary }),
|
|
507
|
-
...(schema.description !== undefined && { description: schema.description })
|
|
532
|
+
...(schema.description !== undefined && { description: schema.description })
|
|
508
533
|
};
|
|
509
534
|
transformed = this.operationNameTransformer(details);
|
|
510
535
|
}
|
|
@@ -543,9 +568,7 @@ export class TypeScriptCodeGeneratorService {
|
|
|
543
568
|
}), false)
|
|
544
569
|
: undefined;
|
|
545
570
|
// Build request body
|
|
546
|
-
const requestBodyExpression = hasRequestBody
|
|
547
|
-
? ts.factory.createIdentifier('body')
|
|
548
|
-
: undefined;
|
|
571
|
+
const requestBodyExpression = hasRequestBody ? ts.factory.createIdentifier('body') : undefined;
|
|
549
572
|
// Build options object for makeRequest
|
|
550
573
|
const optionsProps = [];
|
|
551
574
|
if (queryParamsExpression) {
|
|
@@ -561,10 +584,32 @@ export class TypeScriptCodeGeneratorService {
|
|
|
561
584
|
const optionsExpression = ts.factory.createObjectLiteralExpression(optionsProps, false);
|
|
562
585
|
// Call makeRequest
|
|
563
586
|
const makeRequestCall = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createThis(), ts.factory.createIdentifier('makeRequest')), undefined, [ts.factory.createStringLiteral(method.toUpperCase(), true), pathExpression, optionsExpression]);
|
|
564
|
-
// Add Zod validation if we have a response schema
|
|
565
587
|
if (responseSchema) {
|
|
566
|
-
const
|
|
567
|
-
|
|
588
|
+
const schemaName = responseSchema.text;
|
|
589
|
+
const schemaNameLower = schemaName.charAt(0).toLowerCase() + schemaName.slice(1);
|
|
590
|
+
const parsedVarName = `parsed${schemaName}`;
|
|
591
|
+
// const response = await this.makeRequest(...)
|
|
592
|
+
statements.push(ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([ts.factory.createVariableDeclaration('response', undefined, undefined, ts.factory.createAwaitExpression(makeRequestCall))], ts.NodeFlags.Const)));
|
|
593
|
+
// const parsed{Name} = {Schema}.safeParse(response)
|
|
594
|
+
statements.push(ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([
|
|
595
|
+
ts.factory.createVariableDeclaration(parsedVarName, undefined, undefined, ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(responseSchema, ts.factory.createIdentifier('safeParse')), undefined, [
|
|
596
|
+
ts.factory.createIdentifier('response')
|
|
597
|
+
]))
|
|
598
|
+
], ts.NodeFlags.Const)));
|
|
599
|
+
// if (!parsed{Name}.success) { throw new ResponseValidationError<{Type}>(...) }
|
|
600
|
+
statements.push(ts.factory.createIfStatement(ts.factory.createPrefixUnaryExpression(ts.SyntaxKind.ExclamationToken, ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(parsedVarName), 'success')), ts.factory.createBlock([
|
|
601
|
+
ts.factory.createThrowStatement(ts.factory.createNewExpression(ts.factory.createIdentifier('ResponseValidationError'), [ts.factory.createTypeReferenceNode(schemaName)], [
|
|
602
|
+
ts.factory.createTemplateExpression(ts.factory.createTemplateHead(`Invalid ${schemaNameLower}: `), [
|
|
603
|
+
ts.factory.createTemplateSpan(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createPropertyAccessExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(parsedVarName), 'error'), 'errors'), 'map'), undefined, [
|
|
604
|
+
ts.factory.createArrowFunction(undefined, undefined, [ts.factory.createParameterDeclaration(undefined, undefined, 'error')], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('error'), 'message'))
|
|
605
|
+
]), 'join'), undefined, [ts.factory.createStringLiteral(', ', true)]), ts.factory.createTemplateTail(''))
|
|
606
|
+
]),
|
|
607
|
+
ts.factory.createIdentifier('response'),
|
|
608
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(parsedVarName), 'error')
|
|
609
|
+
]))
|
|
610
|
+
], true)));
|
|
611
|
+
// return parsed{Name}.data
|
|
612
|
+
statements.push(ts.factory.createReturnStatement(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(parsedVarName), 'data')));
|
|
568
613
|
}
|
|
569
614
|
else {
|
|
570
615
|
statements.push(ts.factory.createReturnStatement(ts.factory.createAwaitExpression(makeRequestCall)));
|
|
@@ -593,7 +638,7 @@ export class TypeScriptCodeGeneratorService {
|
|
|
593
638
|
matches.push({
|
|
594
639
|
index: match.index,
|
|
595
640
|
length: match[0].length,
|
|
596
|
-
name: paramName
|
|
641
|
+
name: paramName
|
|
597
642
|
});
|
|
598
643
|
}
|
|
599
644
|
}
|
|
@@ -688,9 +733,7 @@ export class TypeScriptCodeGeneratorService {
|
|
|
688
733
|
parameters.push(this.typeBuilder.createParameter('body', bodyType, undefined, !schema.requestBody?.required));
|
|
689
734
|
}
|
|
690
735
|
// Determine content type for request body
|
|
691
|
-
const contentType = hasRequestBody && schema.requestBody?.content?.['application/x-www-form-urlencoded']
|
|
692
|
-
? 'application/x-www-form-urlencoded'
|
|
693
|
-
: 'application/json';
|
|
736
|
+
const contentType = hasRequestBody && schema.requestBody?.content?.['application/x-www-form-urlencoded'] ? 'application/x-www-form-urlencoded' : 'application/json';
|
|
694
737
|
return { parameters, pathParams, queryParams, hasRequestBody, contentType };
|
|
695
738
|
}
|
|
696
739
|
getParameterType(schema) {
|
|
@@ -784,9 +827,7 @@ export class TypeScriptCodeGeneratorService {
|
|
|
784
827
|
const responseDefault = schema.responses?.['default'];
|
|
785
828
|
const response = response200 ?? response201 ?? responseDefault;
|
|
786
829
|
if (!response?.content?.['application/json']?.schema) {
|
|
787
|
-
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
|
|
788
|
-
ts.factory.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword),
|
|
789
|
-
]);
|
|
830
|
+
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [ts.factory.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword)]);
|
|
790
831
|
}
|
|
791
832
|
const responseSchema = response.content['application/json'].schema;
|
|
792
833
|
const typeName = this.getSchemaTypeName(responseSchema, schemas);
|
|
@@ -798,26 +839,22 @@ export class TypeScriptCodeGeneratorService {
|
|
|
798
839
|
if (schemas[sanitizedItemTypeName]) {
|
|
799
840
|
// Use the type alias directly (it already uses z.infer)
|
|
800
841
|
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
|
|
801
|
-
ts.factory.createArrayTypeNode(ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(sanitizedItemTypeName), undefined))
|
|
842
|
+
ts.factory.createArrayTypeNode(ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(sanitizedItemTypeName), undefined))
|
|
802
843
|
]);
|
|
803
844
|
}
|
|
804
845
|
// If it's a primitive array, use the type name as-is
|
|
805
|
-
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
|
|
806
|
-
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(typeName), undefined),
|
|
807
|
-
]);
|
|
846
|
+
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(typeName), undefined)]);
|
|
808
847
|
}
|
|
809
848
|
const sanitizedTypeName = this.typeBuilder.sanitizeIdentifier(typeName);
|
|
810
849
|
// Check if it's a custom schema type (we have a type alias for it)
|
|
811
850
|
if (schemas[sanitizedTypeName]) {
|
|
812
851
|
// Use the type name directly (we have a type alias that already uses z.infer)
|
|
813
852
|
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
|
|
814
|
-
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(sanitizedTypeName), undefined)
|
|
853
|
+
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(sanitizedTypeName), undefined)
|
|
815
854
|
]);
|
|
816
855
|
}
|
|
817
856
|
// For primitive types and Record types, use the type name directly
|
|
818
|
-
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
|
|
819
|
-
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(typeName), undefined),
|
|
820
|
-
]);
|
|
857
|
+
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(typeName), undefined)]);
|
|
821
858
|
}
|
|
822
859
|
buildServerConfiguration(openapi) {
|
|
823
860
|
const servers = openapi.servers;
|
|
@@ -827,17 +864,13 @@ export class TypeScriptCodeGeneratorService {
|
|
|
827
864
|
const statements = [];
|
|
828
865
|
// Build server configuration array
|
|
829
866
|
const serverConfigElements = servers.map((server) => {
|
|
830
|
-
const properties = [
|
|
831
|
-
ts.factory.createPropertyAssignment('url', ts.factory.createStringLiteral(server.url, true)),
|
|
832
|
-
];
|
|
867
|
+
const properties = [ts.factory.createPropertyAssignment('url', ts.factory.createStringLiteral(server.url, true))];
|
|
833
868
|
if (server.description) {
|
|
834
869
|
properties.push(ts.factory.createPropertyAssignment('description', ts.factory.createStringLiteral(server.description, true)));
|
|
835
870
|
}
|
|
836
871
|
if (server.variables && Object.keys(server.variables).length > 0) {
|
|
837
872
|
const variableProperties = Object.entries(server.variables).map(([varName, varDef]) => {
|
|
838
|
-
const varProps = [
|
|
839
|
-
ts.factory.createPropertyAssignment('default', ts.factory.createStringLiteral(varDef.default, true)),
|
|
840
|
-
];
|
|
873
|
+
const varProps = [ts.factory.createPropertyAssignment('default', ts.factory.createStringLiteral(varDef.default, true))];
|
|
841
874
|
if (varDef.enum && varDef.enum.length > 0) {
|
|
842
875
|
varProps.push(ts.factory.createPropertyAssignment('enum', ts.factory.createArrayLiteralExpression(varDef.enum.map((val) => ts.factory.createStringLiteral(val, true)), false)));
|
|
843
876
|
}
|
|
@@ -852,22 +885,20 @@ export class TypeScriptCodeGeneratorService {
|
|
|
852
885
|
});
|
|
853
886
|
// Export server configuration
|
|
854
887
|
statements.push(ts.factory.createVariableStatement([ts.factory.createToken(ts.SyntaxKind.ExportKeyword)], ts.factory.createVariableDeclarationList([
|
|
855
|
-
ts.factory.createVariableDeclaration(ts.factory.createIdentifier('serverConfigurations'), undefined, undefined, ts.factory.createArrayLiteralExpression(serverConfigElements, false))
|
|
888
|
+
ts.factory.createVariableDeclaration(ts.factory.createIdentifier('serverConfigurations'), undefined, undefined, ts.factory.createArrayLiteralExpression(serverConfigElements, false))
|
|
856
889
|
], ts.NodeFlags.Const)));
|
|
857
890
|
// Export default base URL (first server with default variables)
|
|
858
891
|
const firstServer = servers[0];
|
|
859
892
|
const defaultBaseUrl = firstServer ? this.resolveServerUrl(firstServer, {}) : '/';
|
|
860
|
-
statements.push(ts.factory.createVariableStatement([ts.factory.createToken(ts.SyntaxKind.ExportKeyword)], ts.factory.createVariableDeclarationList([
|
|
861
|
-
ts.factory.createVariableDeclaration(ts.factory.createIdentifier('defaultBaseUrl'), undefined, undefined, ts.factory.createStringLiteral(defaultBaseUrl, true)),
|
|
862
|
-
], ts.NodeFlags.Const)));
|
|
893
|
+
statements.push(ts.factory.createVariableStatement([ts.factory.createToken(ts.SyntaxKind.ExportKeyword)], ts.factory.createVariableDeclarationList([ts.factory.createVariableDeclaration(ts.factory.createIdentifier('defaultBaseUrl'), undefined, undefined, ts.factory.createStringLiteral(defaultBaseUrl, true))], ts.NodeFlags.Const)));
|
|
863
894
|
// Build ClientOptions type
|
|
864
895
|
const optionProperties = [
|
|
865
896
|
ts.factory.createPropertySignature(undefined, ts.factory.createIdentifier('baseUrl'), ts.factory.createToken(ts.SyntaxKind.QuestionToken), ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword)),
|
|
866
897
|
ts.factory.createPropertySignature(undefined, ts.factory.createIdentifier('serverIndex'), ts.factory.createToken(ts.SyntaxKind.QuestionToken), ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword)),
|
|
867
898
|
ts.factory.createPropertySignature(undefined, ts.factory.createIdentifier('serverVariables'), ts.factory.createToken(ts.SyntaxKind.QuestionToken), ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Record'), [
|
|
868
899
|
ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
|
|
869
|
-
ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword)
|
|
870
|
-
]))
|
|
900
|
+
ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword)
|
|
901
|
+
]))
|
|
871
902
|
];
|
|
872
903
|
statements.push(ts.factory.createTypeAliasDeclaration([ts.factory.createToken(ts.SyntaxKind.ExportKeyword)], ts.factory.createIdentifier('ClientOptions'), undefined, ts.factory.createTypeLiteralNode(optionProperties)));
|
|
873
904
|
// Build resolveServerUrl helper function
|
|
@@ -887,14 +918,10 @@ export class TypeScriptCodeGeneratorService {
|
|
|
887
918
|
buildResolveServerUrlFunction(servers) {
|
|
888
919
|
// Build server configs array inline
|
|
889
920
|
const serverConfigElements = servers.map((server) => {
|
|
890
|
-
const properties = [
|
|
891
|
-
ts.factory.createPropertyAssignment('url', ts.factory.createStringLiteral(server.url, true)),
|
|
892
|
-
];
|
|
921
|
+
const properties = [ts.factory.createPropertyAssignment('url', ts.factory.createStringLiteral(server.url, true))];
|
|
893
922
|
if (server.variables && Object.keys(server.variables).length > 0) {
|
|
894
923
|
const variableProperties = Object.entries(server.variables).map(([varName, varDef]) => {
|
|
895
|
-
const varProps = [
|
|
896
|
-
ts.factory.createPropertyAssignment('default', ts.factory.createStringLiteral(varDef.default, true)),
|
|
897
|
-
];
|
|
924
|
+
const varProps = [ts.factory.createPropertyAssignment('default', ts.factory.createStringLiteral(varDef.default, true))];
|
|
898
925
|
if (varDef.enum && varDef.enum.length > 0) {
|
|
899
926
|
varProps.push(ts.factory.createPropertyAssignment('enum', ts.factory.createArrayLiteralExpression(varDef.enum.map((val) => ts.factory.createStringLiteral(val, true)), false)));
|
|
900
927
|
}
|
|
@@ -913,56 +940,47 @@ export class TypeScriptCodeGeneratorService {
|
|
|
913
940
|
const value = ts.factory.createIdentifier('value');
|
|
914
941
|
const bodyStatements = [
|
|
915
942
|
// const configs = [...]
|
|
916
|
-
ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([
|
|
917
|
-
ts.factory.createVariableDeclaration(configs, undefined, undefined, ts.factory.createArrayLiteralExpression(serverConfigElements, false)),
|
|
918
|
-
], ts.NodeFlags.Const)),
|
|
943
|
+
ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([ts.factory.createVariableDeclaration(configs, undefined, undefined, ts.factory.createArrayLiteralExpression(serverConfigElements, false))], ts.NodeFlags.Const)),
|
|
919
944
|
// const idx = serverIndex ?? 0
|
|
920
945
|
ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([
|
|
921
|
-
ts.factory.createVariableDeclaration(idx, undefined, undefined, ts.factory.createBinaryExpression(ts.factory.createIdentifier('serverIndex'), ts.factory.createToken(ts.SyntaxKind.QuestionQuestionToken), ts.factory.createNumericLiteral('0')))
|
|
946
|
+
ts.factory.createVariableDeclaration(idx, undefined, undefined, ts.factory.createBinaryExpression(ts.factory.createIdentifier('serverIndex'), ts.factory.createToken(ts.SyntaxKind.QuestionQuestionToken), ts.factory.createNumericLiteral('0')))
|
|
922
947
|
], ts.NodeFlags.Const)),
|
|
923
948
|
// if (idx < configs.length) { ... }
|
|
924
949
|
ts.factory.createIfStatement(ts.factory.createBinaryExpression(idx, ts.factory.createToken(ts.SyntaxKind.LessThanToken), ts.factory.createPropertyAccessExpression(configs, ts.factory.createIdentifier('length'))), ts.factory.createBlock([
|
|
925
950
|
// const config = configs[idx]
|
|
926
|
-
ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([
|
|
927
|
-
ts.factory.createVariableDeclaration(config, undefined, undefined, ts.factory.createElementAccessExpression(configs, idx)),
|
|
928
|
-
], ts.NodeFlags.Const)),
|
|
951
|
+
ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([ts.factory.createVariableDeclaration(config, undefined, undefined, ts.factory.createElementAccessExpression(configs, idx))], ts.NodeFlags.Const)),
|
|
929
952
|
// let url = config.url
|
|
930
|
-
ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([
|
|
931
|
-
ts.factory.createVariableDeclaration(url, undefined, undefined, ts.factory.createPropertyAccessExpression(config, ts.factory.createIdentifier('url'))),
|
|
932
|
-
], ts.NodeFlags.Let)),
|
|
953
|
+
ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([ts.factory.createVariableDeclaration(url, undefined, undefined, ts.factory.createPropertyAccessExpression(config, ts.factory.createIdentifier('url')))], ts.NodeFlags.Let)),
|
|
933
954
|
// if (config.variables && serverVariables) { ... }
|
|
934
955
|
ts.factory.createIfStatement(ts.factory.createLogicalAnd(ts.factory.createPropertyAccessExpression(config, ts.factory.createIdentifier('variables')), ts.factory.createIdentifier('serverVariables')), ts.factory.createBlock([
|
|
935
956
|
// for (const [key, value] of Object.entries(serverVariables)) { url = url.replace(...) }
|
|
936
957
|
ts.factory.createForOfStatement(undefined, ts.factory.createVariableDeclarationList([
|
|
937
958
|
ts.factory.createVariableDeclaration(ts.factory.createArrayBindingPattern([
|
|
938
959
|
ts.factory.createBindingElement(undefined, undefined, key),
|
|
939
|
-
ts.factory.createBindingElement(undefined, undefined, value)
|
|
940
|
-
]), undefined, undefined)
|
|
960
|
+
ts.factory.createBindingElement(undefined, undefined, value)
|
|
961
|
+
]), undefined, undefined)
|
|
941
962
|
], ts.NodeFlags.Const), ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('Object'), ts.factory.createIdentifier('entries')), undefined, [ts.factory.createIdentifier('serverVariables')]), ts.factory.createBlock([
|
|
942
963
|
ts.factory.createExpressionStatement(ts.factory.createBinaryExpression(url, ts.factory.createToken(ts.SyntaxKind.EqualsToken), ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(url, ts.factory.createIdentifier('replace')), undefined, [
|
|
943
964
|
ts.factory.createNewExpression(ts.factory.createIdentifier('RegExp'), undefined, [
|
|
944
965
|
ts.factory.createBinaryExpression(ts.factory.createBinaryExpression(ts.factory.createStringLiteral('\\{'), ts.factory.createToken(ts.SyntaxKind.PlusToken), key), ts.factory.createToken(ts.SyntaxKind.PlusToken), ts.factory.createStringLiteral('\\}')),
|
|
945
|
-
ts.factory.createStringLiteral('g')
|
|
966
|
+
ts.factory.createStringLiteral('g')
|
|
946
967
|
]),
|
|
947
|
-
value
|
|
948
|
-
])))
|
|
949
|
-
], true))
|
|
968
|
+
value
|
|
969
|
+
])))
|
|
970
|
+
], true))
|
|
950
971
|
], true)),
|
|
951
972
|
// return url
|
|
952
|
-
ts.factory.createReturnStatement(url)
|
|
973
|
+
ts.factory.createReturnStatement(url)
|
|
953
974
|
], true)),
|
|
954
975
|
// return default (first server with defaults)
|
|
955
|
-
ts.factory.createReturnStatement(ts.factory.createStringLiteral(servers[0] ? this.resolveServerUrl(servers[0], {}) : '/', true))
|
|
976
|
+
ts.factory.createReturnStatement(ts.factory.createStringLiteral(servers[0] ? this.resolveServerUrl(servers[0], {}) : '/', true))
|
|
956
977
|
];
|
|
957
978
|
return ts.factory.createFunctionDeclaration(undefined, undefined, ts.factory.createIdentifier('resolveServerUrl'), undefined, [
|
|
958
|
-
ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createIdentifier('serverIndex'), ts.factory.createToken(ts.SyntaxKind.QuestionToken), ts.factory.createUnionTypeNode([
|
|
959
|
-
ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword),
|
|
960
|
-
ts.factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword),
|
|
961
|
-
]), undefined),
|
|
979
|
+
ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createIdentifier('serverIndex'), ts.factory.createToken(ts.SyntaxKind.QuestionToken), ts.factory.createUnionTypeNode([ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword), ts.factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword)]), undefined),
|
|
962
980
|
ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createIdentifier('serverVariables'), ts.factory.createToken(ts.SyntaxKind.QuestionToken), ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Record'), [
|
|
963
981
|
ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
|
|
964
|
-
ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword)
|
|
965
|
-
]), ts.factory.createObjectLiteralExpression([], false))
|
|
982
|
+
ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword)
|
|
983
|
+
]), ts.factory.createObjectLiteralExpression([], false))
|
|
966
984
|
], ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword), ts.factory.createBlock(bodyStatements, true));
|
|
967
985
|
}
|
|
968
986
|
generateClientName(title) {
|
|
@@ -1066,9 +1084,7 @@ export class TypeScriptCodeGeneratorService {
|
|
|
1066
1084
|
const prop = safeProperty.data;
|
|
1067
1085
|
if (this.isReference(prop)) {
|
|
1068
1086
|
const refSchema = this.buildFromReference(prop);
|
|
1069
|
-
return required
|
|
1070
|
-
? refSchema
|
|
1071
|
-
: ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(refSchema, ts.factory.createIdentifier('optional')), undefined, []);
|
|
1087
|
+
return required ? refSchema : ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(refSchema, ts.factory.createIdentifier('optional')), undefined, []);
|
|
1072
1088
|
}
|
|
1073
1089
|
if (prop['anyOf'] && Array.isArray(prop['anyOf']) && prop['anyOf'].length > 0) {
|
|
1074
1090
|
return this.handleLogicalOperator('anyOf', prop['anyOf'], required);
|
|
@@ -1116,7 +1132,9 @@ export class TypeScriptCodeGeneratorService {
|
|
|
1116
1132
|
else {
|
|
1117
1133
|
literalValue = ts.factory.createStringLiteral(String(val), true);
|
|
1118
1134
|
}
|
|
1119
|
-
return ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('literal')), undefined, [
|
|
1135
|
+
return ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('literal')), undefined, [
|
|
1136
|
+
literalValue
|
|
1137
|
+
]);
|
|
1120
1138
|
});
|
|
1121
1139
|
const unionExpression = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('union')), undefined, [ts.factory.createArrayLiteralExpression(literalSchemas, false)]);
|
|
1122
1140
|
return required
|
|
@@ -1130,15 +1148,19 @@ export class TypeScriptCodeGeneratorService {
|
|
|
1130
1148
|
let arraySchema = this.buildZodAST([
|
|
1131
1149
|
{
|
|
1132
1150
|
type: 'array',
|
|
1133
|
-
args: [itemsSchema]
|
|
1134
|
-
}
|
|
1151
|
+
args: [itemsSchema]
|
|
1152
|
+
}
|
|
1135
1153
|
]);
|
|
1136
1154
|
// Apply array constraints
|
|
1137
1155
|
if (typeof prop['minItems'] === 'number') {
|
|
1138
|
-
arraySchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(arraySchema, ts.factory.createIdentifier('min')), undefined, [
|
|
1156
|
+
arraySchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(arraySchema, ts.factory.createIdentifier('min')), undefined, [
|
|
1157
|
+
ts.factory.createNumericLiteral(String(prop['minItems']))
|
|
1158
|
+
]);
|
|
1139
1159
|
}
|
|
1140
1160
|
if (typeof prop['maxItems'] === 'number') {
|
|
1141
|
-
arraySchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(arraySchema, ts.factory.createIdentifier('max')), undefined, [
|
|
1161
|
+
arraySchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(arraySchema, ts.factory.createIdentifier('max')), undefined, [
|
|
1162
|
+
ts.factory.createNumericLiteral(String(prop['maxItems']))
|
|
1163
|
+
]);
|
|
1142
1164
|
}
|
|
1143
1165
|
return required
|
|
1144
1166
|
? arraySchema
|
|
@@ -1156,9 +1178,9 @@ export class TypeScriptCodeGeneratorService {
|
|
|
1156
1178
|
args: [
|
|
1157
1179
|
ts.factory.createObjectLiteralExpression(propertiesEntries.map(([name, propValue]) => {
|
|
1158
1180
|
return ts.factory.createPropertyAssignment(ts.factory.createIdentifier(name), this.buildProperty(propValue, propRequired.includes(name)));
|
|
1159
|
-
}), true)
|
|
1160
|
-
]
|
|
1161
|
-
}
|
|
1181
|
+
}), true)
|
|
1182
|
+
]
|
|
1183
|
+
}
|
|
1162
1184
|
]);
|
|
1163
1185
|
// Apply object constraints
|
|
1164
1186
|
let constrainedSchema = objectSchema;
|
|
@@ -1166,16 +1188,16 @@ export class TypeScriptCodeGeneratorService {
|
|
|
1166
1188
|
constrainedSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(constrainedSchema, ts.factory.createIdentifier('refine')), undefined, [
|
|
1167
1189
|
ts.factory.createArrowFunction(undefined, undefined, [ts.factory.createParameterDeclaration(undefined, undefined, 'obj', undefined, undefined, undefined)], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('Object'), ts.factory.createIdentifier('keys')), undefined, [ts.factory.createIdentifier('obj')]), ts.factory.createIdentifier('length')), ts.factory.createToken(ts.SyntaxKind.GreaterThanEqualsToken), ts.factory.createNumericLiteral(String(prop['minProperties'])))),
|
|
1168
1190
|
ts.factory.createObjectLiteralExpression([
|
|
1169
|
-
ts.factory.createPropertyAssignment(ts.factory.createIdentifier('message'), ts.factory.createStringLiteral(`Object must have at least ${String(prop['minProperties'])} properties`))
|
|
1170
|
-
])
|
|
1191
|
+
ts.factory.createPropertyAssignment(ts.factory.createIdentifier('message'), ts.factory.createStringLiteral(`Object must have at least ${String(prop['minProperties'])} properties`))
|
|
1192
|
+
])
|
|
1171
1193
|
]);
|
|
1172
1194
|
}
|
|
1173
1195
|
if (typeof prop['maxProperties'] === 'number') {
|
|
1174
1196
|
constrainedSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(constrainedSchema, ts.factory.createIdentifier('refine')), undefined, [
|
|
1175
1197
|
ts.factory.createArrowFunction(undefined, undefined, [ts.factory.createParameterDeclaration(undefined, undefined, 'obj', undefined, undefined, undefined)], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('Object'), ts.factory.createIdentifier('keys')), undefined, [ts.factory.createIdentifier('obj')]), ts.factory.createIdentifier('length')), ts.factory.createToken(ts.SyntaxKind.LessThanEqualsToken), ts.factory.createNumericLiteral(String(prop['maxProperties'])))),
|
|
1176
1198
|
ts.factory.createObjectLiteralExpression([
|
|
1177
|
-
ts.factory.createPropertyAssignment(ts.factory.createIdentifier('message'), ts.factory.createStringLiteral(`Object must have at most ${String(prop['maxProperties'])} properties`))
|
|
1178
|
-
])
|
|
1199
|
+
ts.factory.createPropertyAssignment(ts.factory.createIdentifier('message'), ts.factory.createStringLiteral(`Object must have at most ${String(prop['maxProperties'])} properties`))
|
|
1200
|
+
])
|
|
1179
1201
|
]);
|
|
1180
1202
|
}
|
|
1181
1203
|
return required
|
|
@@ -1185,31 +1207,30 @@ export class TypeScriptCodeGeneratorService {
|
|
|
1185
1207
|
return this.buildZodAST([
|
|
1186
1208
|
{
|
|
1187
1209
|
type: 'record',
|
|
1188
|
-
args: [this.buildZodAST(['string']), this.buildZodAST(['unknown'])]
|
|
1189
|
-
}
|
|
1210
|
+
args: [this.buildZodAST(['string']), this.buildZodAST(['unknown'])]
|
|
1211
|
+
}
|
|
1190
1212
|
]);
|
|
1191
1213
|
}
|
|
1192
1214
|
case 'integer': {
|
|
1193
1215
|
let numberSchema = this.buildZodAST(['number', 'int']);
|
|
1194
1216
|
// Apply number constraints
|
|
1195
1217
|
if (prop['minimum'] !== undefined && typeof prop['minimum'] === 'number') {
|
|
1196
|
-
const minValue = prop['exclusiveMinimum'] && typeof prop['exclusiveMinimum'] === 'boolean'
|
|
1197
|
-
? prop['minimum'] + 1
|
|
1198
|
-
: prop['minimum'];
|
|
1218
|
+
const minValue = prop['exclusiveMinimum'] && typeof prop['exclusiveMinimum'] === 'boolean' ? prop['minimum'] + 1 : prop['minimum'];
|
|
1199
1219
|
numberSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(numberSchema, ts.factory.createIdentifier(prop['exclusiveMinimum'] && typeof prop['exclusiveMinimum'] === 'boolean' ? 'gt' : 'gte')), undefined, [ts.factory.createNumericLiteral(String(minValue))]);
|
|
1200
1220
|
}
|
|
1201
1221
|
if (prop['maximum'] !== undefined && typeof prop['maximum'] === 'number') {
|
|
1202
|
-
const maxValue = prop['exclusiveMaximum'] && typeof prop['exclusiveMaximum'] === 'boolean'
|
|
1203
|
-
? prop['maximum'] - 1
|
|
1204
|
-
: prop['maximum'];
|
|
1222
|
+
const maxValue = prop['exclusiveMaximum'] && typeof prop['exclusiveMaximum'] === 'boolean' ? prop['maximum'] - 1 : prop['maximum'];
|
|
1205
1223
|
numberSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(numberSchema, ts.factory.createIdentifier(prop['exclusiveMaximum'] ? 'lt' : 'lte')), undefined, [ts.factory.createNumericLiteral(String(maxValue))]);
|
|
1206
1224
|
}
|
|
1207
1225
|
if (typeof prop['multipleOf'] === 'number') {
|
|
1208
1226
|
const refineFunction = ts.factory.createArrowFunction(undefined, undefined, [ts.factory.createParameterDeclaration(undefined, undefined, 'val', undefined, undefined, undefined)], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createBinaryExpression(ts.factory.createBinaryExpression(ts.factory.createIdentifier('val'), ts.factory.createToken(ts.SyntaxKind.PercentToken), ts.factory.createNumericLiteral(String(prop['multipleOf']))), ts.factory.createToken(ts.SyntaxKind.EqualsEqualsEqualsToken), ts.factory.createNumericLiteral('0')));
|
|
1209
1227
|
const refineOptions = ts.factory.createObjectLiteralExpression([
|
|
1210
|
-
ts.factory.createPropertyAssignment(ts.factory.createIdentifier('message'), ts.factory.createStringLiteral(`Number must be a multiple of ${String(prop['multipleOf'])}`))
|
|
1228
|
+
ts.factory.createPropertyAssignment(ts.factory.createIdentifier('message'), ts.factory.createStringLiteral(`Number must be a multiple of ${String(prop['multipleOf'])}`))
|
|
1229
|
+
]);
|
|
1230
|
+
numberSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(numberSchema, ts.factory.createIdentifier('refine')), undefined, [
|
|
1231
|
+
refineFunction,
|
|
1232
|
+
refineOptions
|
|
1211
1233
|
]);
|
|
1212
|
-
numberSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(numberSchema, ts.factory.createIdentifier('refine')), undefined, [refineFunction, refineOptions]);
|
|
1213
1234
|
}
|
|
1214
1235
|
return required
|
|
1215
1236
|
? numberSchema
|
|
@@ -1219,23 +1240,22 @@ export class TypeScriptCodeGeneratorService {
|
|
|
1219
1240
|
let numberSchema = this.buildZodAST(['number']);
|
|
1220
1241
|
// Apply number constraints
|
|
1221
1242
|
if (prop['minimum'] !== undefined && typeof prop['minimum'] === 'number') {
|
|
1222
|
-
const minValue = prop['exclusiveMinimum'] && typeof prop['exclusiveMinimum'] === 'boolean'
|
|
1223
|
-
? prop['minimum'] + 1
|
|
1224
|
-
: prop['minimum'];
|
|
1243
|
+
const minValue = prop['exclusiveMinimum'] && typeof prop['exclusiveMinimum'] === 'boolean' ? prop['minimum'] + 1 : prop['minimum'];
|
|
1225
1244
|
numberSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(numberSchema, ts.factory.createIdentifier(prop['exclusiveMinimum'] && typeof prop['exclusiveMinimum'] === 'boolean' ? 'gt' : 'gte')), undefined, [ts.factory.createNumericLiteral(String(minValue))]);
|
|
1226
1245
|
}
|
|
1227
1246
|
if (prop['maximum'] !== undefined && typeof prop['maximum'] === 'number') {
|
|
1228
|
-
const maxValue = prop['exclusiveMaximum'] && typeof prop['exclusiveMaximum'] === 'boolean'
|
|
1229
|
-
? prop['maximum'] - 1
|
|
1230
|
-
: prop['maximum'];
|
|
1247
|
+
const maxValue = prop['exclusiveMaximum'] && typeof prop['exclusiveMaximum'] === 'boolean' ? prop['maximum'] - 1 : prop['maximum'];
|
|
1231
1248
|
numberSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(numberSchema, ts.factory.createIdentifier(prop['exclusiveMaximum'] ? 'lt' : 'lte')), undefined, [ts.factory.createNumericLiteral(String(maxValue))]);
|
|
1232
1249
|
}
|
|
1233
1250
|
if (typeof prop['multipleOf'] === 'number') {
|
|
1234
1251
|
const refineFunction = ts.factory.createArrowFunction(undefined, undefined, [ts.factory.createParameterDeclaration(undefined, undefined, 'val', undefined, undefined, undefined)], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createBinaryExpression(ts.factory.createBinaryExpression(ts.factory.createIdentifier('val'), ts.factory.createToken(ts.SyntaxKind.PercentToken), ts.factory.createNumericLiteral(String(prop['multipleOf']))), ts.factory.createToken(ts.SyntaxKind.EqualsEqualsEqualsToken), ts.factory.createNumericLiteral('0')));
|
|
1235
1252
|
const refineOptions = ts.factory.createObjectLiteralExpression([
|
|
1236
|
-
ts.factory.createPropertyAssignment(ts.factory.createIdentifier('message'), ts.factory.createStringLiteral(`Number must be a multiple of ${String(prop['multipleOf'])}`))
|
|
1253
|
+
ts.factory.createPropertyAssignment(ts.factory.createIdentifier('message'), ts.factory.createStringLiteral(`Number must be a multiple of ${String(prop['multipleOf'])}`))
|
|
1254
|
+
]);
|
|
1255
|
+
numberSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(numberSchema, ts.factory.createIdentifier('refine')), undefined, [
|
|
1256
|
+
refineFunction,
|
|
1257
|
+
refineOptions
|
|
1237
1258
|
]);
|
|
1238
|
-
numberSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(numberSchema, ts.factory.createIdentifier('refine')), undefined, [refineFunction, refineOptions]);
|
|
1239
1259
|
}
|
|
1240
1260
|
return required
|
|
1241
1261
|
? numberSchema
|
|
@@ -1270,22 +1290,26 @@ export class TypeScriptCodeGeneratorService {
|
|
|
1270
1290
|
}
|
|
1271
1291
|
// Apply string constraints
|
|
1272
1292
|
if (typeof prop['minLength'] === 'number') {
|
|
1273
|
-
stringSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(stringSchema, ts.factory.createIdentifier('min')), undefined, [
|
|
1293
|
+
stringSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(stringSchema, ts.factory.createIdentifier('min')), undefined, [
|
|
1294
|
+
ts.factory.createNumericLiteral(String(prop['minLength']))
|
|
1295
|
+
]);
|
|
1274
1296
|
}
|
|
1275
1297
|
if (typeof prop['maxLength'] === 'number') {
|
|
1276
|
-
stringSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(stringSchema, ts.factory.createIdentifier('max')), undefined, [
|
|
1298
|
+
stringSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(stringSchema, ts.factory.createIdentifier('max')), undefined, [
|
|
1299
|
+
ts.factory.createNumericLiteral(String(prop['maxLength']))
|
|
1300
|
+
]);
|
|
1277
1301
|
}
|
|
1278
1302
|
if (prop['pattern'] && typeof prop['pattern'] === 'string') {
|
|
1279
1303
|
stringSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(stringSchema, ts.factory.createIdentifier('regex')), undefined, [
|
|
1280
|
-
ts.factory.createNewExpression(ts.factory.createIdentifier('RegExp'), undefined, [
|
|
1281
|
-
ts.factory.createStringLiteral(prop['pattern'], true),
|
|
1282
|
-
]),
|
|
1304
|
+
ts.factory.createNewExpression(ts.factory.createIdentifier('RegExp'), undefined, [ts.factory.createStringLiteral(prop['pattern'], true)])
|
|
1283
1305
|
]);
|
|
1284
1306
|
}
|
|
1285
1307
|
// Apply default value if not required
|
|
1286
1308
|
if (!required && prop['default'] !== undefined) {
|
|
1287
1309
|
const defaultValue = this.buildDefaultValue(prop['default']);
|
|
1288
|
-
stringSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(stringSchema, ts.factory.createIdentifier('default')), undefined, [
|
|
1310
|
+
stringSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(stringSchema, ts.factory.createIdentifier('default')), undefined, [
|
|
1311
|
+
defaultValue
|
|
1312
|
+
]);
|
|
1289
1313
|
}
|
|
1290
1314
|
return required
|
|
1291
1315
|
? stringSchema
|
|
@@ -1295,12 +1319,10 @@ export class TypeScriptCodeGeneratorService {
|
|
|
1295
1319
|
let booleanSchema = this.buildZodAST(['boolean']);
|
|
1296
1320
|
// Apply default value if not required
|
|
1297
1321
|
if (!required && prop['default'] !== undefined) {
|
|
1298
|
-
const defaultValue = typeof prop['default'] === 'boolean'
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
: ts.factory.createFalse();
|
|
1303
|
-
booleanSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(booleanSchema, ts.factory.createIdentifier('default')), undefined, [defaultValue]);
|
|
1322
|
+
const defaultValue = typeof prop['default'] === 'boolean' ? (prop['default'] ? ts.factory.createTrue() : ts.factory.createFalse()) : ts.factory.createFalse();
|
|
1323
|
+
booleanSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(booleanSchema, ts.factory.createIdentifier('default')), undefined, [
|
|
1324
|
+
defaultValue
|
|
1325
|
+
]);
|
|
1304
1326
|
}
|
|
1305
1327
|
return required
|
|
1306
1328
|
? booleanSchema
|
|
@@ -1352,7 +1374,9 @@ export class TypeScriptCodeGeneratorService {
|
|
|
1352
1374
|
case 'anyOf':
|
|
1353
1375
|
case 'oneOf': {
|
|
1354
1376
|
const unionSchemas = schemas.map((schema) => this.buildSchemaFromLogicalOperator(schema));
|
|
1355
|
-
return ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('union')), undefined, [
|
|
1377
|
+
return ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('union')), undefined, [
|
|
1378
|
+
ts.factory.createArrayLiteralExpression(unionSchemas, false)
|
|
1379
|
+
]);
|
|
1356
1380
|
}
|
|
1357
1381
|
case 'allOf': {
|
|
1358
1382
|
if (schemas.length === 0) {
|
|
@@ -1367,10 +1391,12 @@ export class TypeScriptCodeGeneratorService {
|
|
|
1367
1391
|
case 'not': {
|
|
1368
1392
|
const notSchema = this.buildSchemaFromLogicalOperator(schemas[0]);
|
|
1369
1393
|
return ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('any')), ts.factory.createIdentifier('refine')), undefined, [
|
|
1370
|
-
ts.factory.createArrowFunction(undefined, undefined, [ts.factory.createParameterDeclaration(undefined, undefined, 'val', undefined, undefined, undefined)], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createPrefixUnaryExpression(ts.SyntaxKind.ExclamationToken, ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(notSchema, ts.factory.createIdentifier('safeParse')), undefined, [
|
|
1394
|
+
ts.factory.createArrowFunction(undefined, undefined, [ts.factory.createParameterDeclaration(undefined, undefined, 'val', undefined, undefined, undefined)], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createPrefixUnaryExpression(ts.SyntaxKind.ExclamationToken, ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(notSchema, ts.factory.createIdentifier('safeParse')), undefined, [
|
|
1395
|
+
ts.factory.createIdentifier('val')
|
|
1396
|
+
]))),
|
|
1371
1397
|
ts.factory.createObjectLiteralExpression([
|
|
1372
|
-
ts.factory.createPropertyAssignment(ts.factory.createIdentifier('message'), ts.factory.createStringLiteral('Value must not match the excluded schema'))
|
|
1373
|
-
])
|
|
1398
|
+
ts.factory.createPropertyAssignment(ts.factory.createIdentifier('message'), ts.factory.createStringLiteral('Value must not match the excluded schema'))
|
|
1399
|
+
])
|
|
1374
1400
|
]);
|
|
1375
1401
|
}
|
|
1376
1402
|
default:
|
|
@@ -1419,16 +1445,16 @@ export class TypeScriptCodeGeneratorService {
|
|
|
1419
1445
|
args: [
|
|
1420
1446
|
ts.factory.createObjectLiteralExpression(properties.map(([name, property]) => {
|
|
1421
1447
|
return ts.factory.createPropertyAssignment(ts.factory.createIdentifier(name), this.buildSchemaFromLogicalOperator(property));
|
|
1422
|
-
}), true)
|
|
1423
|
-
]
|
|
1424
|
-
}
|
|
1448
|
+
}), true)
|
|
1449
|
+
]
|
|
1450
|
+
}
|
|
1425
1451
|
]);
|
|
1426
1452
|
}
|
|
1427
1453
|
return this.buildZodAST([
|
|
1428
1454
|
{
|
|
1429
1455
|
type: 'record',
|
|
1430
|
-
args: [this.buildZodAST(['string']), this.buildZodAST(['unknown'])]
|
|
1431
|
-
}
|
|
1456
|
+
args: [this.buildZodAST(['string']), this.buildZodAST(['unknown'])]
|
|
1457
|
+
}
|
|
1432
1458
|
]);
|
|
1433
1459
|
}
|
|
1434
1460
|
buildArrayTypeFromSchema(schemaObj) {
|
|
@@ -1436,8 +1462,8 @@ export class TypeScriptCodeGeneratorService {
|
|
|
1436
1462
|
return this.buildZodAST([
|
|
1437
1463
|
{
|
|
1438
1464
|
type: 'array',
|
|
1439
|
-
args: [this.buildSchemaFromLogicalOperator(schemaObj.items)]
|
|
1440
|
-
}
|
|
1465
|
+
args: [this.buildSchemaFromLogicalOperator(schemaObj.items)]
|
|
1466
|
+
}
|
|
1441
1467
|
]);
|
|
1442
1468
|
}
|
|
1443
1469
|
return this.buildZodAST(['array']);
|
|
@@ -1457,7 +1483,7 @@ export class TypeScriptCodeGeneratorService {
|
|
|
1457
1483
|
if (this.isCircularReference(refName)) {
|
|
1458
1484
|
// Generate: z.lazy(() => RefSchema)
|
|
1459
1485
|
return ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('lazy')), undefined, [
|
|
1460
|
-
ts.factory.createArrowFunction(undefined, undefined, [], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createIdentifier(sanitizedRefName))
|
|
1486
|
+
ts.factory.createArrowFunction(undefined, undefined, [], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createIdentifier(sanitizedRefName))
|
|
1461
1487
|
]);
|
|
1462
1488
|
}
|
|
1463
1489
|
return ts.factory.createIdentifier(sanitizedRefName);
|
|
@@ -1475,9 +1501,7 @@ export class TypeScriptCodeGeneratorService {
|
|
|
1475
1501
|
}
|
|
1476
1502
|
// Case 2: Reference to a schema that's part of a circular dependency chain
|
|
1477
1503
|
// and we're currently building a schema that's also in that chain
|
|
1478
|
-
if (this.circularSchemas.has(refName) &&
|
|
1479
|
-
this.currentSchemaName !== null &&
|
|
1480
|
-
this.circularSchemas.has(this.currentSchemaName)) {
|
|
1504
|
+
if (this.circularSchemas.has(refName) && this.currentSchemaName !== null && this.circularSchemas.has(this.currentSchemaName)) {
|
|
1481
1505
|
return true;
|
|
1482
1506
|
}
|
|
1483
1507
|
return false;
|
|
@@ -1492,11 +1516,7 @@ export class TypeScriptCodeGeneratorService {
|
|
|
1492
1516
|
// Build dependency graph
|
|
1493
1517
|
const graph = new Map();
|
|
1494
1518
|
for (const [name, schema] of Object.entries(schemas)) {
|
|
1495
|
-
const dependencies =
|
|
1496
|
-
.query(schema, '$..["$ref"]')
|
|
1497
|
-
.filter((ref) => ref.startsWith('#/components/schemas/'))
|
|
1498
|
-
.map((ref) => ref.replace('#/components/schemas/', ''))
|
|
1499
|
-
.filter((dep) => dep in schemas);
|
|
1519
|
+
const dependencies = this.extractSchemaReferences(schema).filter((dep) => dep in schemas);
|
|
1500
1520
|
graph.set(name, dependencies);
|
|
1501
1521
|
}
|
|
1502
1522
|
// Tarjan's algorithm for finding SCCs
|
|
@@ -1574,10 +1594,7 @@ export class TypeScriptCodeGeneratorService {
|
|
|
1574
1594
|
}
|
|
1575
1595
|
visiting.add(name);
|
|
1576
1596
|
const schema = schemas[name];
|
|
1577
|
-
const dependencies =
|
|
1578
|
-
.query(schema, '$..["$ref"]')
|
|
1579
|
-
.filter((ref) => ref.startsWith('#/components/schemas/'))
|
|
1580
|
-
.map((ref) => ref.replace('#/components/schemas/', ''));
|
|
1597
|
+
const dependencies = this.extractSchemaReferences(schema);
|
|
1581
1598
|
for (const dep of dependencies) {
|
|
1582
1599
|
if (schemas[dep]) {
|
|
1583
1600
|
visit(dep);
|