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,6 +1,6 @@
|
|
|
1
|
-
import {beforeEach, describe, expect, it} from 'vitest';
|
|
2
|
-
import {TypeScriptCodeGeneratorService} from '../../src/services/code-generator.service';
|
|
3
|
-
import type {OpenApiSpecType} from '../../src/types/openapi';
|
|
1
|
+
import { beforeEach, describe, expect, it } from 'vitest';
|
|
2
|
+
import { TypeScriptCodeGeneratorService } from '../../src/services/code-generator.service';
|
|
3
|
+
import type { OpenApiSpecType } from '../../src/types/openapi';
|
|
4
4
|
|
|
5
5
|
describe('TypeScriptCodeGeneratorService', () => {
|
|
6
6
|
let generator: TypeScriptCodeGeneratorService;
|
|
@@ -15,7 +15,7 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
15
15
|
openapi: '3.0.0',
|
|
16
16
|
info: {
|
|
17
17
|
title: 'Test API',
|
|
18
|
-
version: '1.0.0'
|
|
18
|
+
version: '1.0.0'
|
|
19
19
|
},
|
|
20
20
|
paths: {
|
|
21
21
|
'/users': {
|
|
@@ -26,18 +26,18 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
26
26
|
description: 'Success',
|
|
27
27
|
content: {
|
|
28
28
|
'application/json': {
|
|
29
|
-
schema: {type: 'string'}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
29
|
+
schema: { type: 'string' }
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
37
|
};
|
|
38
38
|
|
|
39
39
|
const generatorWithConvention = new TypeScriptCodeGeneratorService({
|
|
40
|
-
namingConvention: 'camelCase'
|
|
40
|
+
namingConvention: 'camelCase'
|
|
41
41
|
});
|
|
42
42
|
const code = generatorWithConvention.generate(spec);
|
|
43
43
|
expect(code).toContain('async getUserById');
|
|
@@ -49,7 +49,7 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
49
49
|
openapi: '3.0.0',
|
|
50
50
|
info: {
|
|
51
51
|
title: 'Test API',
|
|
52
|
-
version: '1.0.0'
|
|
52
|
+
version: '1.0.0'
|
|
53
53
|
},
|
|
54
54
|
paths: {
|
|
55
55
|
'/users': {
|
|
@@ -60,18 +60,18 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
60
60
|
description: 'Success',
|
|
61
61
|
content: {
|
|
62
62
|
'application/json': {
|
|
63
|
-
schema: {type: 'string'}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
63
|
+
schema: { type: 'string' }
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
71
|
};
|
|
72
72
|
|
|
73
73
|
const generatorWithConvention = new TypeScriptCodeGeneratorService({
|
|
74
|
-
namingConvention: 'PascalCase'
|
|
74
|
+
namingConvention: 'PascalCase'
|
|
75
75
|
});
|
|
76
76
|
const code = generatorWithConvention.generate(spec);
|
|
77
77
|
expect(code).toContain('async GetUserById');
|
|
@@ -83,7 +83,7 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
83
83
|
openapi: '3.0.0',
|
|
84
84
|
info: {
|
|
85
85
|
title: 'Test API',
|
|
86
|
-
version: '1.0.0'
|
|
86
|
+
version: '1.0.0'
|
|
87
87
|
},
|
|
88
88
|
paths: {
|
|
89
89
|
'/users': {
|
|
@@ -94,18 +94,18 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
94
94
|
description: 'Success',
|
|
95
95
|
content: {
|
|
96
96
|
'application/json': {
|
|
97
|
-
schema: {type: 'string'}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
97
|
+
schema: { type: 'string' }
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
105
|
};
|
|
106
106
|
|
|
107
107
|
const generatorWithConvention = new TypeScriptCodeGeneratorService({
|
|
108
|
-
namingConvention: 'snake_case'
|
|
108
|
+
namingConvention: 'snake_case'
|
|
109
109
|
});
|
|
110
110
|
const code = generatorWithConvention.generate(spec);
|
|
111
111
|
expect(code).toContain('async get_user_by_id');
|
|
@@ -117,7 +117,7 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
117
117
|
openapi: '3.0.0',
|
|
118
118
|
info: {
|
|
119
119
|
title: 'Test API',
|
|
120
|
-
version: '1.0.0'
|
|
120
|
+
version: '1.0.0'
|
|
121
121
|
},
|
|
122
122
|
paths: {
|
|
123
123
|
'/users/{id}': {
|
|
@@ -130,29 +130,22 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
130
130
|
description: 'Success',
|
|
131
131
|
content: {
|
|
132
132
|
'application/json': {
|
|
133
|
-
schema: {type: 'string'}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
}
|
|
133
|
+
schema: { type: 'string' }
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
141
|
};
|
|
142
142
|
|
|
143
|
-
const customTransformer = (details: {
|
|
144
|
-
operationId: string;
|
|
145
|
-
method: string;
|
|
146
|
-
path: string;
|
|
147
|
-
tags?: string[];
|
|
148
|
-
summary?: string;
|
|
149
|
-
description?: string;
|
|
150
|
-
}) => {
|
|
143
|
+
const customTransformer = (details: { operationId: string; method: string; path: string; tags?: string[]; summary?: string; description?: string }) => {
|
|
151
144
|
return `${details.method.toUpperCase()}_${details.tags?.[0] || 'default'}_${details.operationId}`;
|
|
152
145
|
};
|
|
153
146
|
|
|
154
147
|
const generatorWithTransformer = new TypeScriptCodeGeneratorService({
|
|
155
|
-
operationNameTransformer: customTransformer
|
|
148
|
+
operationNameTransformer: customTransformer
|
|
156
149
|
});
|
|
157
150
|
const code = generatorWithTransformer.generate(spec);
|
|
158
151
|
expect(code).toContain('async GET_users_getUserById');
|
|
@@ -163,7 +156,7 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
163
156
|
openapi: '3.0.0',
|
|
164
157
|
info: {
|
|
165
158
|
title: 'Test API',
|
|
166
|
-
version: '1.0.0'
|
|
159
|
+
version: '1.0.0'
|
|
167
160
|
},
|
|
168
161
|
paths: {
|
|
169
162
|
'/users': {
|
|
@@ -174,21 +167,21 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
174
167
|
description: 'Success',
|
|
175
168
|
content: {
|
|
176
169
|
'application/json': {
|
|
177
|
-
schema: {type: 'string'}
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
}
|
|
170
|
+
schema: { type: 'string' }
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
185
178
|
};
|
|
186
179
|
|
|
187
180
|
const customTransformer = () => 'customName';
|
|
188
181
|
|
|
189
182
|
const generatorWithBoth = new TypeScriptCodeGeneratorService({
|
|
190
183
|
namingConvention: 'PascalCase',
|
|
191
|
-
operationNameTransformer: customTransformer
|
|
184
|
+
operationNameTransformer: customTransformer
|
|
192
185
|
});
|
|
193
186
|
const code = generatorWithBoth.generate(spec);
|
|
194
187
|
expect(code).toContain('async customName');
|
|
@@ -203,9 +196,9 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
203
196
|
openapi: '3.0.0',
|
|
204
197
|
info: {
|
|
205
198
|
title: 'Test API',
|
|
206
|
-
version: '1.0.0'
|
|
199
|
+
version: '1.0.0'
|
|
207
200
|
},
|
|
208
|
-
paths: {}
|
|
201
|
+
paths: {}
|
|
209
202
|
};
|
|
210
203
|
|
|
211
204
|
const code = generator.generate(spec);
|
|
@@ -220,7 +213,7 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
220
213
|
openapi: '3.0.0',
|
|
221
214
|
info: {
|
|
222
215
|
title: 'Test API',
|
|
223
|
-
version: '1.0.0'
|
|
216
|
+
version: '1.0.0'
|
|
224
217
|
},
|
|
225
218
|
paths: {},
|
|
226
219
|
components: {
|
|
@@ -228,13 +221,13 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
228
221
|
User: {
|
|
229
222
|
type: 'object',
|
|
230
223
|
properties: {
|
|
231
|
-
id: {type: 'integer'},
|
|
232
|
-
name: {type: 'string'}
|
|
224
|
+
id: { type: 'integer' },
|
|
225
|
+
name: { type: 'string' }
|
|
233
226
|
},
|
|
234
|
-
required: ['id', 'name']
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
227
|
+
required: ['id', 'name']
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
238
231
|
};
|
|
239
232
|
|
|
240
233
|
const code = generator.generate(spec);
|
|
@@ -249,7 +242,7 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
249
242
|
openapi: '3.0.0',
|
|
250
243
|
info: {
|
|
251
244
|
title: 'Test API',
|
|
252
|
-
version: '1.0.0'
|
|
245
|
+
version: '1.0.0'
|
|
253
246
|
},
|
|
254
247
|
paths: {
|
|
255
248
|
'/users': {
|
|
@@ -262,15 +255,15 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
262
255
|
'application/json': {
|
|
263
256
|
schema: {
|
|
264
257
|
type: 'array',
|
|
265
|
-
items: {type: 'string'}
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
}
|
|
258
|
+
items: { type: 'string' }
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
274
267
|
};
|
|
275
268
|
|
|
276
269
|
const code = generator.generate(spec);
|
|
@@ -283,9 +276,9 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
283
276
|
openapi: '3.0.0',
|
|
284
277
|
info: {
|
|
285
278
|
title: 'Test API',
|
|
286
|
-
version: '1.0.0'
|
|
279
|
+
version: '1.0.0'
|
|
287
280
|
},
|
|
288
|
-
paths: {}
|
|
281
|
+
paths: {}
|
|
289
282
|
};
|
|
290
283
|
|
|
291
284
|
const code = generator.generate(spec);
|
|
@@ -298,10 +291,10 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
298
291
|
openapi: '3.0.0',
|
|
299
292
|
info: {
|
|
300
293
|
title: 'Test API',
|
|
301
|
-
version: '1.0.0'
|
|
294
|
+
version: '1.0.0'
|
|
302
295
|
},
|
|
303
|
-
servers: [{url: 'https://api.example.com'}],
|
|
304
|
-
paths: {}
|
|
296
|
+
servers: [{ url: 'https://api.example.com' }],
|
|
297
|
+
paths: {}
|
|
305
298
|
};
|
|
306
299
|
|
|
307
300
|
const code = generator.generate(spec);
|
|
@@ -314,7 +307,7 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
314
307
|
openapi: '3.0.0',
|
|
315
308
|
info: {
|
|
316
309
|
title: 'Test API',
|
|
317
|
-
version: '1.0.0'
|
|
310
|
+
version: '1.0.0'
|
|
318
311
|
},
|
|
319
312
|
paths: {},
|
|
320
313
|
components: {
|
|
@@ -322,21 +315,21 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
322
315
|
User: {
|
|
323
316
|
type: 'object',
|
|
324
317
|
properties: {
|
|
325
|
-
id: {type: 'integer'},
|
|
326
|
-
profile: {$ref: '#/components/schemas/Profile'}
|
|
318
|
+
id: { type: 'integer' },
|
|
319
|
+
profile: { $ref: '#/components/schemas/Profile' }
|
|
327
320
|
},
|
|
328
|
-
required: ['id']
|
|
321
|
+
required: ['id']
|
|
329
322
|
},
|
|
330
323
|
Profile: {
|
|
331
324
|
type: 'object',
|
|
332
325
|
properties: {
|
|
333
|
-
name: {type: 'string'},
|
|
334
|
-
email: {type: 'string', format: 'email'}
|
|
326
|
+
name: { type: 'string' },
|
|
327
|
+
email: { type: 'string', format: 'email' }
|
|
335
328
|
},
|
|
336
|
-
required: ['name', 'email']
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
}
|
|
329
|
+
required: ['name', 'email']
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
340
333
|
};
|
|
341
334
|
|
|
342
335
|
const code = generator.generate(spec);
|
|
@@ -353,17 +346,17 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
353
346
|
openapi: '3.0.0',
|
|
354
347
|
info: {
|
|
355
348
|
title: 'Test API',
|
|
356
|
-
version: '1.0.0'
|
|
349
|
+
version: '1.0.0'
|
|
357
350
|
},
|
|
358
351
|
paths: {},
|
|
359
352
|
components: {
|
|
360
353
|
schemas: {
|
|
361
354
|
Status: {
|
|
362
355
|
type: 'string',
|
|
363
|
-
enum: ['active', 'inactive', 'pending']
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
}
|
|
356
|
+
enum: ['active', 'inactive', 'pending']
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
367
360
|
};
|
|
368
361
|
|
|
369
362
|
const code = generator.generate(spec);
|
|
@@ -378,21 +371,21 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
378
371
|
openapi: '3.0.0',
|
|
379
372
|
info: {
|
|
380
373
|
title: 'Test API',
|
|
381
|
-
version: '1.0.0'
|
|
374
|
+
version: '1.0.0'
|
|
382
375
|
},
|
|
383
376
|
paths: {},
|
|
384
377
|
components: {
|
|
385
378
|
schemas: {
|
|
386
379
|
Status: {
|
|
387
380
|
type: 'integer',
|
|
388
|
-
enum: [-99, 0, 1, 2]
|
|
381
|
+
enum: [-99, 0, 1, 2]
|
|
389
382
|
},
|
|
390
383
|
ExecutionMode: {
|
|
391
384
|
type: 'integer',
|
|
392
|
-
enum: [1, 2]
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
}
|
|
385
|
+
enum: [1, 2]
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
396
389
|
};
|
|
397
390
|
|
|
398
391
|
const code = generator.generate(spec);
|
|
@@ -413,7 +406,7 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
413
406
|
openapi: '3.0.0',
|
|
414
407
|
info: {
|
|
415
408
|
title: 'Test API',
|
|
416
|
-
version: '1.0.0'
|
|
409
|
+
version: '1.0.0'
|
|
417
410
|
},
|
|
418
411
|
paths: {
|
|
419
412
|
'/test': {
|
|
@@ -424,14 +417,14 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
424
417
|
description: 'Success',
|
|
425
418
|
content: {
|
|
426
419
|
'application/json': {
|
|
427
|
-
schema: {type: 'string'}
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
}
|
|
420
|
+
schema: { type: 'string' }
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
435
428
|
};
|
|
436
429
|
|
|
437
430
|
const code = generator.generate(spec);
|
|
@@ -456,17 +449,17 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
456
449
|
openapi: '3.0.0',
|
|
457
450
|
info: {
|
|
458
451
|
title: 'Test API',
|
|
459
|
-
version: '1.0.0'
|
|
452
|
+
version: '1.0.0'
|
|
460
453
|
},
|
|
461
454
|
paths: {},
|
|
462
455
|
components: {
|
|
463
456
|
schemas: {
|
|
464
457
|
Tags: {
|
|
465
458
|
type: 'array',
|
|
466
|
-
items: {type: 'string'}
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
}
|
|
459
|
+
items: { type: 'string' }
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
470
463
|
};
|
|
471
464
|
|
|
472
465
|
const code = generator.generate(spec);
|
|
@@ -475,33 +468,141 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
475
468
|
});
|
|
476
469
|
});
|
|
477
470
|
|
|
471
|
+
describe('ResponseValidationError', () => {
|
|
472
|
+
it('should generate ResponseValidationError class', () => {
|
|
473
|
+
const spec: OpenApiSpecType = {
|
|
474
|
+
openapi: '3.0.0',
|
|
475
|
+
info: {
|
|
476
|
+
title: 'Test API',
|
|
477
|
+
version: '1.0.0'
|
|
478
|
+
},
|
|
479
|
+
paths: {}
|
|
480
|
+
};
|
|
481
|
+
|
|
482
|
+
const code = generator.generate(spec);
|
|
483
|
+
expect(code).toContain('class ResponseValidationError<T> extends Error');
|
|
484
|
+
expect(code).toContain('readonly response: Response');
|
|
485
|
+
expect(code).toContain('readonly error: z.ZodError<T>');
|
|
486
|
+
expect(code).toContain("this.name = 'ResponseValidationError' as const");
|
|
487
|
+
expect(code).toContain('get data(): T');
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
it('should use safeParse with ResponseValidationError for methods with response schemas', () => {
|
|
491
|
+
const spec: OpenApiSpecType = {
|
|
492
|
+
openapi: '3.0.0',
|
|
493
|
+
info: {
|
|
494
|
+
title: 'Test API',
|
|
495
|
+
version: '1.0.0'
|
|
496
|
+
},
|
|
497
|
+
paths: {
|
|
498
|
+
'/pets': {
|
|
499
|
+
post: {
|
|
500
|
+
operationId: 'createPet',
|
|
501
|
+
requestBody: {
|
|
502
|
+
content: {
|
|
503
|
+
'application/json': {
|
|
504
|
+
schema: { $ref: '#/components/schemas/Pet' }
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
},
|
|
508
|
+
responses: {
|
|
509
|
+
'200': {
|
|
510
|
+
description: 'Success',
|
|
511
|
+
content: {
|
|
512
|
+
'application/json': {
|
|
513
|
+
schema: { $ref: '#/components/schemas/Pet' }
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
},
|
|
521
|
+
components: {
|
|
522
|
+
schemas: {
|
|
523
|
+
Pet: {
|
|
524
|
+
type: 'object',
|
|
525
|
+
properties: {
|
|
526
|
+
id: { type: 'integer' },
|
|
527
|
+
name: { type: 'string' }
|
|
528
|
+
},
|
|
529
|
+
required: ['name']
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
};
|
|
534
|
+
|
|
535
|
+
const code = generator.generate(spec);
|
|
536
|
+
expect(code).toContain('Pet.safeParse(response)');
|
|
537
|
+
expect(code).toContain('parsedPet.success');
|
|
538
|
+
expect(code).toContain('new ResponseValidationError<Pet>');
|
|
539
|
+
expect(code).toContain('parsedPet.data');
|
|
540
|
+
expect(code).not.toContain('Pet.parse(');
|
|
541
|
+
});
|
|
542
|
+
|
|
543
|
+
it('should not use safeParse for methods without response schemas', () => {
|
|
544
|
+
const spec: OpenApiSpecType = {
|
|
545
|
+
openapi: '3.0.0',
|
|
546
|
+
info: {
|
|
547
|
+
title: 'Test API',
|
|
548
|
+
version: '1.0.0'
|
|
549
|
+
},
|
|
550
|
+
paths: {
|
|
551
|
+
'/pets/{id}': {
|
|
552
|
+
delete: {
|
|
553
|
+
operationId: 'deletePet',
|
|
554
|
+
parameters: [
|
|
555
|
+
{
|
|
556
|
+
name: 'id',
|
|
557
|
+
in: 'path',
|
|
558
|
+
required: true,
|
|
559
|
+
schema: { type: 'integer' }
|
|
560
|
+
}
|
|
561
|
+
],
|
|
562
|
+
responses: {
|
|
563
|
+
'204': {
|
|
564
|
+
description: 'Deleted'
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
};
|
|
571
|
+
|
|
572
|
+
const code = generator.generate(spec);
|
|
573
|
+
expect(code).toContain('async deletePet');
|
|
574
|
+
expect(code).toContain('return await this.makeRequest');
|
|
575
|
+
expect(code).not.toContain('safeParse');
|
|
576
|
+
});
|
|
577
|
+
});
|
|
578
|
+
|
|
478
579
|
describe('buildSchema', () => {
|
|
479
580
|
it('should build schema for string type', () => {
|
|
480
|
-
const schema = {type: 'string'};
|
|
581
|
+
const schema = { type: 'string' };
|
|
481
582
|
const result = generator.buildSchema(schema, true);
|
|
482
583
|
expect(result).toBeDefined();
|
|
483
584
|
});
|
|
484
585
|
|
|
485
586
|
it('should build schema for number type', () => {
|
|
486
|
-
const schema = {type: 'number'};
|
|
587
|
+
const schema = { type: 'number' };
|
|
487
588
|
const result = generator.buildSchema(schema, true);
|
|
488
589
|
expect(result).toBeDefined();
|
|
489
590
|
});
|
|
490
591
|
|
|
491
592
|
it('should build schema for boolean type', () => {
|
|
492
|
-
const schema = {type: 'boolean'};
|
|
593
|
+
const schema = { type: 'boolean' };
|
|
493
594
|
const result = generator.buildSchema(schema, true);
|
|
494
595
|
expect(result).toBeDefined();
|
|
495
596
|
});
|
|
496
597
|
|
|
497
598
|
it('should handle optional fields', () => {
|
|
498
|
-
const schema = {type: 'string'};
|
|
599
|
+
const schema = { type: 'string' };
|
|
499
600
|
const result = generator.buildSchema(schema, false);
|
|
500
601
|
expect(result).toBeDefined();
|
|
501
602
|
});
|
|
502
603
|
|
|
503
604
|
it('should handle string formats', () => {
|
|
504
|
-
const schema = {type: 'string', format: 'email'};
|
|
605
|
+
const schema = { type: 'string', format: 'email' };
|
|
505
606
|
const result = generator.buildSchema(schema, true);
|
|
506
607
|
expect(result).toBeDefined();
|
|
507
608
|
});
|
|
@@ -513,7 +614,7 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
513
614
|
openapi: '3.0.0',
|
|
514
615
|
info: {
|
|
515
616
|
title: 'Test API',
|
|
516
|
-
version: '1.0.0'
|
|
617
|
+
version: '1.0.0'
|
|
517
618
|
},
|
|
518
619
|
paths: {},
|
|
519
620
|
components: {
|
|
@@ -521,16 +622,16 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
521
622
|
TreeNode: {
|
|
522
623
|
type: 'object',
|
|
523
624
|
properties: {
|
|
524
|
-
value: {type: 'string'},
|
|
625
|
+
value: { type: 'string' },
|
|
525
626
|
children: {
|
|
526
627
|
type: 'array',
|
|
527
|
-
items: {$ref: '#/components/schemas/TreeNode'}
|
|
528
|
-
}
|
|
628
|
+
items: { $ref: '#/components/schemas/TreeNode' }
|
|
629
|
+
}
|
|
529
630
|
},
|
|
530
|
-
required: ['value']
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
}
|
|
631
|
+
required: ['value']
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
}
|
|
534
635
|
};
|
|
535
636
|
|
|
536
637
|
const code = generator.generate(spec);
|
|
@@ -542,7 +643,7 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
542
643
|
openapi: '3.0.0',
|
|
543
644
|
info: {
|
|
544
645
|
title: 'Test API',
|
|
545
|
-
version: '1.0.0'
|
|
646
|
+
version: '1.0.0'
|
|
546
647
|
},
|
|
547
648
|
paths: {},
|
|
548
649
|
components: {
|
|
@@ -550,21 +651,21 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
550
651
|
Person: {
|
|
551
652
|
type: 'object',
|
|
552
653
|
properties: {
|
|
553
|
-
name: {type: 'string'},
|
|
554
|
-
bestFriend: {$ref: '#/components/schemas/Friend'}
|
|
654
|
+
name: { type: 'string' },
|
|
655
|
+
bestFriend: { $ref: '#/components/schemas/Friend' }
|
|
555
656
|
},
|
|
556
|
-
required: ['name']
|
|
657
|
+
required: ['name']
|
|
557
658
|
},
|
|
558
659
|
Friend: {
|
|
559
660
|
type: 'object',
|
|
560
661
|
properties: {
|
|
561
|
-
nickname: {type: 'string'},
|
|
562
|
-
person: {$ref: '#/components/schemas/Person'}
|
|
662
|
+
nickname: { type: 'string' },
|
|
663
|
+
person: { $ref: '#/components/schemas/Person' }
|
|
563
664
|
},
|
|
564
|
-
required: ['nickname']
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
}
|
|
665
|
+
required: ['nickname']
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
}
|
|
568
669
|
};
|
|
569
670
|
|
|
570
671
|
const code = generator.generate(spec);
|
|
@@ -578,7 +679,7 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
578
679
|
openapi: '3.0.0',
|
|
579
680
|
info: {
|
|
580
681
|
title: 'Test API',
|
|
581
|
-
version: '1.0.0'
|
|
682
|
+
version: '1.0.0'
|
|
582
683
|
},
|
|
583
684
|
paths: {},
|
|
584
685
|
components: {
|
|
@@ -586,20 +687,20 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
586
687
|
User: {
|
|
587
688
|
type: 'object',
|
|
588
689
|
properties: {
|
|
589
|
-
id: {type: 'integer'},
|
|
590
|
-
profile: {$ref: '#/components/schemas/Profile'}
|
|
690
|
+
id: { type: 'integer' },
|
|
691
|
+
profile: { $ref: '#/components/schemas/Profile' }
|
|
591
692
|
},
|
|
592
|
-
required: ['id']
|
|
693
|
+
required: ['id']
|
|
593
694
|
},
|
|
594
695
|
Profile: {
|
|
595
696
|
type: 'object',
|
|
596
697
|
properties: {
|
|
597
|
-
name: {type: 'string'}
|
|
698
|
+
name: { type: 'string' }
|
|
598
699
|
},
|
|
599
|
-
required: ['name']
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
}
|
|
700
|
+
required: ['name']
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
}
|
|
603
704
|
};
|
|
604
705
|
|
|
605
706
|
const code = generator.generate(spec);
|
|
@@ -613,7 +714,7 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
613
714
|
openapi: '3.0.0',
|
|
614
715
|
info: {
|
|
615
716
|
title: 'Test API',
|
|
616
|
-
version: '1.0.0'
|
|
717
|
+
version: '1.0.0'
|
|
617
718
|
},
|
|
618
719
|
paths: {},
|
|
619
720
|
components: {
|
|
@@ -621,23 +722,23 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
621
722
|
Alpha: {
|
|
622
723
|
type: 'object',
|
|
623
724
|
properties: {
|
|
624
|
-
beta: {$ref: '#/components/schemas/Beta'}
|
|
625
|
-
}
|
|
725
|
+
beta: { $ref: '#/components/schemas/Beta' }
|
|
726
|
+
}
|
|
626
727
|
},
|
|
627
728
|
Beta: {
|
|
628
729
|
type: 'object',
|
|
629
730
|
properties: {
|
|
630
|
-
gamma: {$ref: '#/components/schemas/Gamma'}
|
|
631
|
-
}
|
|
731
|
+
gamma: { $ref: '#/components/schemas/Gamma' }
|
|
732
|
+
}
|
|
632
733
|
},
|
|
633
734
|
Gamma: {
|
|
634
735
|
type: 'object',
|
|
635
736
|
properties: {
|
|
636
|
-
alpha: {$ref: '#/components/schemas/Alpha'}
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
}
|
|
737
|
+
alpha: { $ref: '#/components/schemas/Alpha' }
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
}
|
|
641
742
|
};
|
|
642
743
|
|
|
643
744
|
const code = generator.generate(spec);
|
|
@@ -652,7 +753,7 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
652
753
|
openapi: '3.0.0',
|
|
653
754
|
info: {
|
|
654
755
|
title: 'Test API',
|
|
655
|
-
version: '1.0.0'
|
|
756
|
+
version: '1.0.0'
|
|
656
757
|
},
|
|
657
758
|
paths: {},
|
|
658
759
|
components: {
|
|
@@ -660,16 +761,16 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
660
761
|
Category: {
|
|
661
762
|
type: 'object',
|
|
662
763
|
properties: {
|
|
663
|
-
name: {type: 'string'},
|
|
764
|
+
name: { type: 'string' },
|
|
664
765
|
subcategories: {
|
|
665
766
|
type: 'array',
|
|
666
|
-
items: {$ref: '#/components/schemas/Category'}
|
|
667
|
-
}
|
|
767
|
+
items: { $ref: '#/components/schemas/Category' }
|
|
768
|
+
}
|
|
668
769
|
},
|
|
669
|
-
required: ['name']
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
|
-
}
|
|
770
|
+
required: ['name']
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
}
|
|
673
774
|
};
|
|
674
775
|
|
|
675
776
|
const code = generator.generate(spec);
|
|
@@ -681,7 +782,7 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
681
782
|
openapi: '3.0.0',
|
|
682
783
|
info: {
|
|
683
784
|
title: 'Test API',
|
|
684
|
-
version: '1.0.0'
|
|
785
|
+
version: '1.0.0'
|
|
685
786
|
},
|
|
686
787
|
paths: {},
|
|
687
788
|
components: {
|
|
@@ -690,12 +791,12 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
690
791
|
type: 'object',
|
|
691
792
|
properties: {
|
|
692
793
|
value: {
|
|
693
|
-
anyOf: [{type: 'string'}, {$ref: '#/components/schemas/Expression'}]
|
|
694
|
-
}
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
}
|
|
794
|
+
anyOf: [{ type: 'string' }, { $ref: '#/components/schemas/Expression' }]
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
}
|
|
699
800
|
};
|
|
700
801
|
|
|
701
802
|
const code = generator.generate(spec);
|
|
@@ -709,16 +810,16 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
709
810
|
openapi: '3.0.0',
|
|
710
811
|
info: {
|
|
711
812
|
title: 'Test API',
|
|
712
|
-
version: '1.0.0'
|
|
813
|
+
version: '1.0.0'
|
|
713
814
|
},
|
|
714
815
|
paths: {},
|
|
715
816
|
components: {
|
|
716
817
|
schemas: {
|
|
717
818
|
StringOrNumber: {
|
|
718
|
-
anyOf: [{type: 'string'}, {type: 'number'}]
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
}
|
|
819
|
+
anyOf: [{ type: 'string' }, { type: 'number' }]
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
}
|
|
722
823
|
};
|
|
723
824
|
|
|
724
825
|
const code = generator.generate(spec);
|
|
@@ -732,19 +833,19 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
732
833
|
openapi: '3.0.0',
|
|
733
834
|
info: {
|
|
734
835
|
title: 'Test API',
|
|
735
|
-
version: '1.0.0'
|
|
836
|
+
version: '1.0.0'
|
|
736
837
|
},
|
|
737
838
|
paths: {},
|
|
738
839
|
components: {
|
|
739
840
|
schemas: {
|
|
740
841
|
Variant: {
|
|
741
842
|
oneOf: [
|
|
742
|
-
{type: 'object', properties: {name: {type: 'string'}}},
|
|
743
|
-
{type: 'object', properties: {id: {type: 'number'}}}
|
|
744
|
-
]
|
|
745
|
-
}
|
|
746
|
-
}
|
|
747
|
-
}
|
|
843
|
+
{ type: 'object', properties: { name: { type: 'string' } } },
|
|
844
|
+
{ type: 'object', properties: { id: { type: 'number' } } }
|
|
845
|
+
]
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
}
|
|
748
849
|
};
|
|
749
850
|
|
|
750
851
|
const code = generator.generate(spec);
|
|
@@ -756,19 +857,19 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
756
857
|
openapi: '3.0.0',
|
|
757
858
|
info: {
|
|
758
859
|
title: 'Test API',
|
|
759
|
-
version: '1.0.0'
|
|
860
|
+
version: '1.0.0'
|
|
760
861
|
},
|
|
761
862
|
paths: {},
|
|
762
863
|
components: {
|
|
763
864
|
schemas: {
|
|
764
865
|
Combined: {
|
|
765
866
|
allOf: [
|
|
766
|
-
{type: 'object', properties: {id: {type: 'number'}}},
|
|
767
|
-
{type: 'object', properties: {name: {type: 'string'}}}
|
|
768
|
-
]
|
|
769
|
-
}
|
|
770
|
-
}
|
|
771
|
-
}
|
|
867
|
+
{ type: 'object', properties: { id: { type: 'number' } } },
|
|
868
|
+
{ type: 'object', properties: { name: { type: 'string' } } }
|
|
869
|
+
]
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
}
|
|
772
873
|
};
|
|
773
874
|
|
|
774
875
|
const code = generator.generate(spec);
|
|
@@ -780,16 +881,16 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
780
881
|
openapi: '3.0.0',
|
|
781
882
|
info: {
|
|
782
883
|
title: 'Test API',
|
|
783
|
-
version: '1.0.0'
|
|
884
|
+
version: '1.0.0'
|
|
784
885
|
},
|
|
785
886
|
paths: {},
|
|
786
887
|
components: {
|
|
787
888
|
schemas: {
|
|
788
889
|
EmptyObject: {
|
|
789
|
-
anyOf: [{type: 'object', properties: {}}]
|
|
790
|
-
}
|
|
791
|
-
}
|
|
792
|
-
}
|
|
890
|
+
anyOf: [{ type: 'object', properties: {} }]
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
}
|
|
793
894
|
};
|
|
794
895
|
|
|
795
896
|
const code = generator.generate(spec);
|
|
@@ -802,16 +903,16 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
802
903
|
openapi: '3.0.0',
|
|
803
904
|
info: {
|
|
804
905
|
title: 'Test API',
|
|
805
|
-
version: '1.0.0'
|
|
906
|
+
version: '1.0.0'
|
|
806
907
|
},
|
|
807
908
|
paths: {},
|
|
808
909
|
components: {
|
|
809
910
|
schemas: {
|
|
810
911
|
GenericArray: {
|
|
811
|
-
anyOf: [{type: 'array'}]
|
|
812
|
-
}
|
|
813
|
-
}
|
|
814
|
-
}
|
|
912
|
+
anyOf: [{ type: 'array' }]
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
}
|
|
815
916
|
};
|
|
816
917
|
|
|
817
918
|
const code = generator.generate(spec);
|
|
@@ -825,16 +926,16 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
825
926
|
openapi: '3.0.0',
|
|
826
927
|
info: {
|
|
827
928
|
title: 'Test API',
|
|
828
|
-
version: '1.0.0'
|
|
929
|
+
version: '1.0.0'
|
|
829
930
|
},
|
|
830
931
|
paths: {},
|
|
831
932
|
components: {
|
|
832
933
|
schemas: {
|
|
833
934
|
UnknownType: {
|
|
834
|
-
anyOf: [{type: 'unknown' as any}]
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
}
|
|
935
|
+
anyOf: [{ type: 'unknown' as any }]
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
}
|
|
838
939
|
};
|
|
839
940
|
|
|
840
941
|
const code = generator.generate(spec);
|
|
@@ -846,16 +947,16 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
846
947
|
openapi: '3.0.0',
|
|
847
948
|
info: {
|
|
848
949
|
title: 'Test API',
|
|
849
|
-
version: '1.0.0'
|
|
950
|
+
version: '1.0.0'
|
|
850
951
|
},
|
|
851
952
|
paths: {},
|
|
852
953
|
components: {
|
|
853
954
|
schemas: {
|
|
854
955
|
InvalidSchema: {
|
|
855
|
-
anyOf: [null as any]
|
|
856
|
-
}
|
|
857
|
-
}
|
|
858
|
-
}
|
|
956
|
+
anyOf: [null as any]
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
}
|
|
859
960
|
};
|
|
860
961
|
|
|
861
962
|
const code = generator.generate(spec);
|
|
@@ -868,16 +969,16 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
868
969
|
openapi: '3.0.0',
|
|
869
970
|
info: {
|
|
870
971
|
title: 'Test API',
|
|
871
|
-
version: '1.0.0'
|
|
972
|
+
version: '1.0.0'
|
|
872
973
|
},
|
|
873
974
|
paths: {},
|
|
874
975
|
components: {
|
|
875
976
|
schemas: {
|
|
876
977
|
IntOrString: {
|
|
877
|
-
anyOf: [{type: 'integer'}, {type: 'string'}]
|
|
878
|
-
}
|
|
879
|
-
}
|
|
880
|
-
}
|
|
978
|
+
anyOf: [{ type: 'integer' }, { type: 'string' }]
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
}
|
|
881
982
|
};
|
|
882
983
|
|
|
883
984
|
const code = generator.generate(spec);
|
|
@@ -890,16 +991,16 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
890
991
|
openapi: '3.0.0',
|
|
891
992
|
info: {
|
|
892
993
|
title: 'Test API',
|
|
893
|
-
version: '1.0.0'
|
|
994
|
+
version: '1.0.0'
|
|
894
995
|
},
|
|
895
996
|
paths: {},
|
|
896
997
|
components: {
|
|
897
998
|
schemas: {
|
|
898
999
|
BoolOrString: {
|
|
899
|
-
anyOf: [{type: 'boolean'}, {type: 'string'}]
|
|
900
|
-
}
|
|
901
|
-
}
|
|
902
|
-
}
|
|
1000
|
+
anyOf: [{ type: 'boolean' }, { type: 'string' }]
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
903
1004
|
};
|
|
904
1005
|
|
|
905
1006
|
const code = generator.generate(spec);
|
|
@@ -912,7 +1013,7 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
912
1013
|
openapi: '3.0.0',
|
|
913
1014
|
info: {
|
|
914
1015
|
title: 'Test API',
|
|
915
|
-
version: '1.0.0'
|
|
1016
|
+
version: '1.0.0'
|
|
916
1017
|
},
|
|
917
1018
|
paths: {},
|
|
918
1019
|
components: {
|
|
@@ -922,14 +1023,14 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
922
1023
|
{
|
|
923
1024
|
type: 'object',
|
|
924
1025
|
properties: {
|
|
925
|
-
name: {type: 'string'},
|
|
926
|
-
age: {type: 'number'}
|
|
927
|
-
}
|
|
928
|
-
}
|
|
929
|
-
]
|
|
930
|
-
}
|
|
931
|
-
}
|
|
932
|
-
}
|
|
1026
|
+
name: { type: 'string' },
|
|
1027
|
+
age: { type: 'number' }
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
]
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
933
1034
|
};
|
|
934
1035
|
|
|
935
1036
|
const code = generator.generate(spec);
|
|
@@ -943,7 +1044,7 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
943
1044
|
openapi: '3.0.0',
|
|
944
1045
|
info: {
|
|
945
1046
|
title: 'Test API',
|
|
946
|
-
version: '1.0.0'
|
|
1047
|
+
version: '1.0.0'
|
|
947
1048
|
},
|
|
948
1049
|
paths: {},
|
|
949
1050
|
components: {
|
|
@@ -952,12 +1053,12 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
952
1053
|
anyOf: [
|
|
953
1054
|
{
|
|
954
1055
|
type: 'array',
|
|
955
|
-
items: {type: 'string'}
|
|
956
|
-
}
|
|
957
|
-
]
|
|
958
|
-
}
|
|
959
|
-
}
|
|
960
|
-
}
|
|
1056
|
+
items: { type: 'string' }
|
|
1057
|
+
}
|
|
1058
|
+
]
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
961
1062
|
};
|
|
962
1063
|
|
|
963
1064
|
const code = generator.generate(spec);
|
|
@@ -971,16 +1072,16 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
971
1072
|
openapi: '3.0.0',
|
|
972
1073
|
info: {
|
|
973
1074
|
title: 'Test API',
|
|
974
|
-
version: '1.0.0'
|
|
1075
|
+
version: '1.0.0'
|
|
975
1076
|
},
|
|
976
1077
|
paths: {},
|
|
977
1078
|
components: {
|
|
978
1079
|
schemas: {
|
|
979
1080
|
InvalidSchema: {
|
|
980
|
-
anyOf: [{} as any]
|
|
981
|
-
}
|
|
982
|
-
}
|
|
983
|
-
}
|
|
1081
|
+
anyOf: [{} as any]
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
984
1085
|
};
|
|
985
1086
|
|
|
986
1087
|
const code = generator.generate(spec);
|
|
@@ -995,7 +1096,7 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
995
1096
|
openapi: '3.0.0',
|
|
996
1097
|
info: {
|
|
997
1098
|
title: 'Test API',
|
|
998
|
-
version: '1.0.0'
|
|
1099
|
+
version: '1.0.0'
|
|
999
1100
|
},
|
|
1000
1101
|
servers: [
|
|
1001
1102
|
{
|
|
@@ -1003,18 +1104,18 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
1003
1104
|
variables: {
|
|
1004
1105
|
environment: {
|
|
1005
1106
|
default: 'api',
|
|
1006
|
-
enum: ['api', 'api.staging', 'api.prod']
|
|
1107
|
+
enum: ['api', 'api.staging', 'api.prod']
|
|
1007
1108
|
},
|
|
1008
1109
|
port: {
|
|
1009
|
-
default: '443'
|
|
1110
|
+
default: '443'
|
|
1010
1111
|
},
|
|
1011
1112
|
version: {
|
|
1012
|
-
default: '1'
|
|
1013
|
-
}
|
|
1014
|
-
}
|
|
1015
|
-
}
|
|
1113
|
+
default: '1'
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1016
1117
|
],
|
|
1017
|
-
paths: {}
|
|
1118
|
+
paths: {}
|
|
1018
1119
|
};
|
|
1019
1120
|
|
|
1020
1121
|
const code = generator.generate(spec);
|
|
@@ -1031,7 +1132,7 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
1031
1132
|
openapi: '3.0.0',
|
|
1032
1133
|
info: {
|
|
1033
1134
|
title: 'Test API',
|
|
1034
|
-
version: '1.0.0'
|
|
1135
|
+
version: '1.0.0'
|
|
1035
1136
|
},
|
|
1036
1137
|
servers: [
|
|
1037
1138
|
{
|
|
@@ -1040,12 +1141,12 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
1040
1141
|
env: {
|
|
1041
1142
|
default: 'prod',
|
|
1042
1143
|
enum: ['dev', 'staging', 'prod'],
|
|
1043
|
-
description: 'Environment'
|
|
1044
|
-
}
|
|
1045
|
-
}
|
|
1046
|
-
}
|
|
1144
|
+
description: 'Environment'
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1047
1148
|
],
|
|
1048
|
-
paths: {}
|
|
1149
|
+
paths: {}
|
|
1049
1150
|
};
|
|
1050
1151
|
|
|
1051
1152
|
const code = generator.generate(spec);
|
|
@@ -1060,22 +1161,22 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
1060
1161
|
openapi: '3.0.0',
|
|
1061
1162
|
info: {
|
|
1062
1163
|
title: 'Test API',
|
|
1063
|
-
version: '1.0.0'
|
|
1164
|
+
version: '1.0.0'
|
|
1064
1165
|
},
|
|
1065
1166
|
servers: [
|
|
1066
1167
|
{
|
|
1067
|
-
url: 'https://api.example.com'
|
|
1168
|
+
url: 'https://api.example.com'
|
|
1068
1169
|
},
|
|
1069
1170
|
{
|
|
1070
1171
|
url: 'https://{env}.example.com',
|
|
1071
1172
|
variables: {
|
|
1072
1173
|
env: {
|
|
1073
|
-
default: 'staging'
|
|
1074
|
-
}
|
|
1075
|
-
}
|
|
1076
|
-
}
|
|
1174
|
+
default: 'staging'
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1077
1178
|
],
|
|
1078
|
-
paths: {}
|
|
1179
|
+
paths: {}
|
|
1079
1180
|
};
|
|
1080
1181
|
|
|
1081
1182
|
const code = generator.generate(spec);
|
|
@@ -1085,4 +1186,309 @@ describe('TypeScriptCodeGeneratorService', () => {
|
|
|
1085
1186
|
expect(code).toContain('https://{env}.example.com');
|
|
1086
1187
|
});
|
|
1087
1188
|
});
|
|
1189
|
+
|
|
1190
|
+
describe('explicit types', () => {
|
|
1191
|
+
it('should generate explicit interface for object schema', () => {
|
|
1192
|
+
const spec: OpenApiSpecType = {
|
|
1193
|
+
openapi: '3.0.0',
|
|
1194
|
+
info: {
|
|
1195
|
+
title: 'Test API',
|
|
1196
|
+
version: '1.0.0'
|
|
1197
|
+
},
|
|
1198
|
+
paths: {},
|
|
1199
|
+
components: {
|
|
1200
|
+
schemas: {
|
|
1201
|
+
Order: {
|
|
1202
|
+
type: 'object',
|
|
1203
|
+
properties: {
|
|
1204
|
+
id: { type: 'integer' },
|
|
1205
|
+
name: { type: 'string' }
|
|
1206
|
+
},
|
|
1207
|
+
required: ['id', 'name']
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
};
|
|
1212
|
+
|
|
1213
|
+
const code = generator.generate(spec);
|
|
1214
|
+
|
|
1215
|
+
// Should generate explicit interface
|
|
1216
|
+
expect(code).toContain('export interface Order');
|
|
1217
|
+
expect(code).toContain('id: number');
|
|
1218
|
+
expect(code).toContain('name: string');
|
|
1219
|
+
|
|
1220
|
+
// Should add type annotation to schema
|
|
1221
|
+
expect(code).toContain('export const Order: z.ZodType<Order>');
|
|
1222
|
+
|
|
1223
|
+
// Should NOT generate z.infer type export
|
|
1224
|
+
expect(code).not.toContain('z.infer<typeof Order>');
|
|
1225
|
+
});
|
|
1226
|
+
|
|
1227
|
+
it('should generate type alias for enum schema', () => {
|
|
1228
|
+
const spec: OpenApiSpecType = {
|
|
1229
|
+
openapi: '3.0.0',
|
|
1230
|
+
info: {
|
|
1231
|
+
title: 'Test API',
|
|
1232
|
+
version: '1.0.0'
|
|
1233
|
+
},
|
|
1234
|
+
paths: {},
|
|
1235
|
+
components: {
|
|
1236
|
+
schemas: {
|
|
1237
|
+
Status: {
|
|
1238
|
+
type: 'string',
|
|
1239
|
+
enum: ['active', 'inactive', 'pending']
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
};
|
|
1244
|
+
|
|
1245
|
+
const code = generator.generate(spec);
|
|
1246
|
+
|
|
1247
|
+
// Should generate type alias (not interface) for enum
|
|
1248
|
+
expect(code).toContain('export type Status');
|
|
1249
|
+
expect(code).toContain("'active'");
|
|
1250
|
+
expect(code).toContain("'inactive'");
|
|
1251
|
+
expect(code).toContain("'pending'");
|
|
1252
|
+
|
|
1253
|
+
// Should add type annotation to schema
|
|
1254
|
+
expect(code).toContain('export const Status: z.ZodType<Status>');
|
|
1255
|
+
});
|
|
1256
|
+
|
|
1257
|
+
it('should generate type alias for array schema', () => {
|
|
1258
|
+
const spec: OpenApiSpecType = {
|
|
1259
|
+
openapi: '3.0.0',
|
|
1260
|
+
info: {
|
|
1261
|
+
title: 'Test API',
|
|
1262
|
+
version: '1.0.0'
|
|
1263
|
+
},
|
|
1264
|
+
paths: {},
|
|
1265
|
+
components: {
|
|
1266
|
+
schemas: {
|
|
1267
|
+
Tags: {
|
|
1268
|
+
type: 'array',
|
|
1269
|
+
items: { type: 'string' }
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
};
|
|
1274
|
+
|
|
1275
|
+
const code = generator.generate(spec);
|
|
1276
|
+
|
|
1277
|
+
// Should generate type alias for array
|
|
1278
|
+
expect(code).toContain('export type Tags = string[]');
|
|
1279
|
+
|
|
1280
|
+
// Should add type annotation to schema
|
|
1281
|
+
expect(code).toContain('export const Tags: z.ZodType<Tags>');
|
|
1282
|
+
});
|
|
1283
|
+
|
|
1284
|
+
it('should handle nested objects with references', () => {
|
|
1285
|
+
const spec: OpenApiSpecType = {
|
|
1286
|
+
openapi: '3.0.0',
|
|
1287
|
+
info: {
|
|
1288
|
+
title: 'Test API',
|
|
1289
|
+
version: '1.0.0'
|
|
1290
|
+
},
|
|
1291
|
+
paths: {},
|
|
1292
|
+
components: {
|
|
1293
|
+
schemas: {
|
|
1294
|
+
User: {
|
|
1295
|
+
type: 'object',
|
|
1296
|
+
properties: {
|
|
1297
|
+
id: { type: 'integer' },
|
|
1298
|
+
profile: { $ref: '#/components/schemas/Profile' }
|
|
1299
|
+
},
|
|
1300
|
+
required: ['id']
|
|
1301
|
+
},
|
|
1302
|
+
Profile: {
|
|
1303
|
+
type: 'object',
|
|
1304
|
+
properties: {
|
|
1305
|
+
name: { type: 'string' }
|
|
1306
|
+
},
|
|
1307
|
+
required: ['name']
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
};
|
|
1312
|
+
|
|
1313
|
+
const code = generator.generate(spec);
|
|
1314
|
+
|
|
1315
|
+
// Should generate interfaces for both
|
|
1316
|
+
expect(code).toContain('export interface User');
|
|
1317
|
+
expect(code).toContain('export interface Profile');
|
|
1318
|
+
|
|
1319
|
+
// User should reference Profile type
|
|
1320
|
+
expect(code).toContain('profile?: Profile');
|
|
1321
|
+
|
|
1322
|
+
// Both should have type annotations
|
|
1323
|
+
expect(code).toContain('export const User: z.ZodType<User>');
|
|
1324
|
+
expect(code).toContain('export const Profile: z.ZodType<Profile>');
|
|
1325
|
+
});
|
|
1326
|
+
|
|
1327
|
+
it('should handle union types (anyOf)', () => {
|
|
1328
|
+
const spec: OpenApiSpecType = {
|
|
1329
|
+
openapi: '3.0.0',
|
|
1330
|
+
info: {
|
|
1331
|
+
title: 'Test API',
|
|
1332
|
+
version: '1.0.0'
|
|
1333
|
+
},
|
|
1334
|
+
paths: {},
|
|
1335
|
+
components: {
|
|
1336
|
+
schemas: {
|
|
1337
|
+
StringOrNumber: {
|
|
1338
|
+
anyOf: [{ type: 'string' }, { type: 'number' }]
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
};
|
|
1343
|
+
|
|
1344
|
+
const code = generator.generate(spec);
|
|
1345
|
+
|
|
1346
|
+
// Should generate type alias for union
|
|
1347
|
+
expect(code).toContain('export type StringOrNumber = string | number');
|
|
1348
|
+
|
|
1349
|
+
// Should add type annotation to schema
|
|
1350
|
+
expect(code).toContain('export const StringOrNumber: z.ZodType<StringOrNumber>');
|
|
1351
|
+
});
|
|
1352
|
+
|
|
1353
|
+
it('should handle intersection types (allOf)', () => {
|
|
1354
|
+
const spec: OpenApiSpecType = {
|
|
1355
|
+
openapi: '3.0.0',
|
|
1356
|
+
info: {
|
|
1357
|
+
title: 'Test API',
|
|
1358
|
+
version: '1.0.0'
|
|
1359
|
+
},
|
|
1360
|
+
paths: {},
|
|
1361
|
+
components: {
|
|
1362
|
+
schemas: {
|
|
1363
|
+
Base: {
|
|
1364
|
+
type: 'object',
|
|
1365
|
+
properties: {
|
|
1366
|
+
id: { type: 'integer' }
|
|
1367
|
+
},
|
|
1368
|
+
required: ['id']
|
|
1369
|
+
},
|
|
1370
|
+
Extended: {
|
|
1371
|
+
allOf: [
|
|
1372
|
+
{ $ref: '#/components/schemas/Base' },
|
|
1373
|
+
{
|
|
1374
|
+
type: 'object',
|
|
1375
|
+
properties: {
|
|
1376
|
+
name: { type: 'string' }
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
]
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
};
|
|
1384
|
+
|
|
1385
|
+
const code = generator.generate(spec);
|
|
1386
|
+
|
|
1387
|
+
// Should generate interface for Base
|
|
1388
|
+
expect(code).toContain('export interface Base');
|
|
1389
|
+
|
|
1390
|
+
// Should generate type alias for Extended (intersection)
|
|
1391
|
+
expect(code).toContain('export type Extended = Base &');
|
|
1392
|
+
|
|
1393
|
+
// Should add type annotations to schemas
|
|
1394
|
+
expect(code).toContain('export const Base: z.ZodType<Base>');
|
|
1395
|
+
expect(code).toContain('export const Extended: z.ZodType<Extended>');
|
|
1396
|
+
});
|
|
1397
|
+
|
|
1398
|
+
it('should handle optional properties', () => {
|
|
1399
|
+
const spec: OpenApiSpecType = {
|
|
1400
|
+
openapi: '3.0.0',
|
|
1401
|
+
info: {
|
|
1402
|
+
title: 'Test API',
|
|
1403
|
+
version: '1.0.0'
|
|
1404
|
+
},
|
|
1405
|
+
paths: {},
|
|
1406
|
+
components: {
|
|
1407
|
+
schemas: {
|
|
1408
|
+
User: {
|
|
1409
|
+
type: 'object',
|
|
1410
|
+
properties: {
|
|
1411
|
+
id: { type: 'integer' },
|
|
1412
|
+
email: { type: 'string' }
|
|
1413
|
+
},
|
|
1414
|
+
required: ['id']
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
};
|
|
1419
|
+
|
|
1420
|
+
const code = generator.generate(spec);
|
|
1421
|
+
|
|
1422
|
+
// id should be required (no ?)
|
|
1423
|
+
expect(code).toContain('id: number');
|
|
1424
|
+
// email should be optional (with ?)
|
|
1425
|
+
expect(code).toContain('email?: string');
|
|
1426
|
+
});
|
|
1427
|
+
|
|
1428
|
+
it('should handle circular dependencies', () => {
|
|
1429
|
+
const spec: OpenApiSpecType = {
|
|
1430
|
+
openapi: '3.0.0',
|
|
1431
|
+
info: {
|
|
1432
|
+
title: 'Test API',
|
|
1433
|
+
version: '1.0.0'
|
|
1434
|
+
},
|
|
1435
|
+
paths: {},
|
|
1436
|
+
components: {
|
|
1437
|
+
schemas: {
|
|
1438
|
+
Node: {
|
|
1439
|
+
type: 'object',
|
|
1440
|
+
properties: {
|
|
1441
|
+
id: { type: 'integer' },
|
|
1442
|
+
children: {
|
|
1443
|
+
type: 'array',
|
|
1444
|
+
items: { $ref: '#/components/schemas/Node' }
|
|
1445
|
+
}
|
|
1446
|
+
},
|
|
1447
|
+
required: ['id']
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
};
|
|
1452
|
+
|
|
1453
|
+
const code = generator.generate(spec);
|
|
1454
|
+
|
|
1455
|
+
// Should generate interface with self-reference
|
|
1456
|
+
expect(code).toContain('export interface Node');
|
|
1457
|
+
expect(code).toContain('children?: Node[]');
|
|
1458
|
+
|
|
1459
|
+
// Should add type annotation to schema
|
|
1460
|
+
expect(code).toContain('export const Node: z.ZodType<Node>');
|
|
1461
|
+
|
|
1462
|
+
// Zod schema should use z.lazy for circular reference
|
|
1463
|
+
expect(code).toContain('z.lazy');
|
|
1464
|
+
});
|
|
1465
|
+
|
|
1466
|
+
it('should handle numeric enum types', () => {
|
|
1467
|
+
const spec: OpenApiSpecType = {
|
|
1468
|
+
openapi: '3.0.0',
|
|
1469
|
+
info: {
|
|
1470
|
+
title: 'Test API',
|
|
1471
|
+
version: '1.0.0'
|
|
1472
|
+
},
|
|
1473
|
+
paths: {},
|
|
1474
|
+
components: {
|
|
1475
|
+
schemas: {
|
|
1476
|
+
Priority: {
|
|
1477
|
+
type: 'integer',
|
|
1478
|
+
enum: [0, 1, 2]
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1482
|
+
};
|
|
1483
|
+
|
|
1484
|
+
const code = generator.generate(spec);
|
|
1485
|
+
|
|
1486
|
+
// Should generate type alias for numeric enum
|
|
1487
|
+
expect(code).toContain('export type Priority');
|
|
1488
|
+
expect(code).toMatch(/0\s*\|\s*1\s*\|\s*2/);
|
|
1489
|
+
|
|
1490
|
+
// Should add type annotation to schema
|
|
1491
|
+
expect(code).toContain('export const Priority: z.ZodType<Priority>');
|
|
1492
|
+
});
|
|
1493
|
+
});
|
|
1088
1494
|
});
|