zod-codegen 1.2.0 → 1.2.2
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/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
## <small>1.2.2 (2025-11-19)</small>
|
|
2
|
+
|
|
3
|
+
- Merge pull request #35 from julienandreu/fix/generate-typescript-type-aliases ([b8d9250](https://github.com/julienandreu/zod-codegen/commit/b8d9250)), closes [#35](https://github.com/julienandreu/zod-codegen/issues/35)
|
|
4
|
+
- fix: generate TypeScript type aliases alongside Zod schemas ([7032a69](https://github.com/julienandreu/zod-codegen/commit/7032a69))
|
|
5
|
+
|
|
6
|
+
## <small>1.2.1 (2025-11-19)</small>
|
|
7
|
+
|
|
8
|
+
- Merge pull request #33 from julienandreu/fix/add-z-infer-to-response-types ([a14d81c](https://github.com/julienandreu/zod-codegen/commit/a14d81c)), closes [#33](https://github.com/julienandreu/zod-codegen/issues/33)
|
|
9
|
+
- fix: add z.infer to response types in generated methods ([c45ac77](https://github.com/julienandreu/zod-codegen/commit/c45ac77))
|
|
10
|
+
|
|
1
11
|
## 1.2.0 (2025-11-19)
|
|
2
12
|
|
|
3
13
|
- Merge pull request #31 from julienandreu/dependabot/npm_and_yarn/dev-dependencies-1dd8918b9f ([97ebb65](https://github.com/julienandreu/zod-codegen/commit/97ebb65)), closes [#31](https://github.com/julienandreu/zod-codegen/issues/31)
|
|
@@ -40,6 +40,7 @@ export class TypeScriptCodeGeneratorService {
|
|
|
40
40
|
buildAST(openapi) {
|
|
41
41
|
const imports = this.importBuilder.buildImports();
|
|
42
42
|
const schemas = this.buildSchemas(openapi);
|
|
43
|
+
const schemaTypeAliases = this.buildSchemaTypeAliases(schemas);
|
|
43
44
|
const serverConfig = this.buildServerConfiguration(openapi);
|
|
44
45
|
const clientClass = this.buildClientClass(openapi, schemas);
|
|
45
46
|
return [
|
|
@@ -47,6 +48,7 @@ export class TypeScriptCodeGeneratorService {
|
|
|
47
48
|
...imports,
|
|
48
49
|
this.createComment('Components schemas'),
|
|
49
50
|
...Object.values(schemas),
|
|
51
|
+
...schemaTypeAliases,
|
|
50
52
|
...serverConfig,
|
|
51
53
|
this.createComment('Client class'),
|
|
52
54
|
clientClass,
|
|
@@ -68,6 +70,12 @@ export class TypeScriptCodeGeneratorService {
|
|
|
68
70
|
};
|
|
69
71
|
}, {});
|
|
70
72
|
}
|
|
73
|
+
buildSchemaTypeAliases(schemas) {
|
|
74
|
+
return Object.keys(schemas).map((name) => {
|
|
75
|
+
const sanitizedName = this.typeBuilder.sanitizeIdentifier(name);
|
|
76
|
+
return ts.factory.createTypeAliasDeclaration([ts.factory.createToken(ts.SyntaxKind.ExportKeyword)], ts.factory.createIdentifier(sanitizedName), undefined, ts.factory.createTypeReferenceNode(ts.factory.createQualifiedName(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('infer')), [ts.factory.createTypeQueryNode(ts.factory.createIdentifier(sanitizedName), undefined)]));
|
|
77
|
+
});
|
|
78
|
+
}
|
|
71
79
|
buildClientClass(openapi, schemas) {
|
|
72
80
|
const clientName = this.generateClientName(openapi.info.title);
|
|
73
81
|
const methods = this.buildClientMethods(openapi, schemas);
|
|
@@ -516,6 +524,31 @@ export class TypeScriptCodeGeneratorService {
|
|
|
516
524
|
}
|
|
517
525
|
const responseSchema = response.content['application/json'].schema;
|
|
518
526
|
const typeName = this.getSchemaTypeName(responseSchema, schemas);
|
|
527
|
+
// Handle array types like "Pet[]"
|
|
528
|
+
if (typeName.endsWith('[]')) {
|
|
529
|
+
const itemTypeName = typeName.slice(0, -2);
|
|
530
|
+
const sanitizedItemTypeName = this.typeBuilder.sanitizeIdentifier(itemTypeName);
|
|
531
|
+
// Check if the item type is a custom schema (we have a type alias for it)
|
|
532
|
+
if (schemas[sanitizedItemTypeName]) {
|
|
533
|
+
// Use the type alias directly (it already uses z.infer)
|
|
534
|
+
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
|
|
535
|
+
ts.factory.createArrayTypeNode(ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(sanitizedItemTypeName), undefined)),
|
|
536
|
+
]);
|
|
537
|
+
}
|
|
538
|
+
// If it's a primitive array, use the type name as-is
|
|
539
|
+
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
|
|
540
|
+
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(typeName), undefined),
|
|
541
|
+
]);
|
|
542
|
+
}
|
|
543
|
+
const sanitizedTypeName = this.typeBuilder.sanitizeIdentifier(typeName);
|
|
544
|
+
// Check if it's a custom schema type (we have a type alias for it)
|
|
545
|
+
if (schemas[sanitizedTypeName]) {
|
|
546
|
+
// Use the type name directly (we have a type alias that already uses z.infer)
|
|
547
|
+
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
|
|
548
|
+
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(sanitizedTypeName), undefined),
|
|
549
|
+
]);
|
|
550
|
+
}
|
|
551
|
+
// For primitive types and Record types, use the type name directly
|
|
519
552
|
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
|
|
520
553
|
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(typeName), undefined),
|
|
521
554
|
]);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
|
2
|
-
// Built with zod-codegen@1.
|
|
3
|
-
// Latest edit:
|
|
2
|
+
// Built with zod-codegen@1.1.2
|
|
3
|
+
// Latest edit: Wed, 19 Nov 2025 16:26:25 GMT
|
|
4
4
|
// Source file: ./samples/swagger-petstore.yaml
|
|
5
5
|
/* eslint-disable */
|
|
6
6
|
// @ts-nocheck
|
|
@@ -144,73 +144,209 @@ export class SwaggerPetstoreOpenAPI30 {
|
|
|
144
144
|
if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
145
145
|
return await response.json();
|
|
146
146
|
}
|
|
147
|
-
|
|
147
|
+
/**
|
|
148
|
+
* Add a new pet to the store
|
|
149
|
+
* @param body Create a new pet in the store
|
|
150
|
+
* @returns {z.infer<typeof Pet>}
|
|
151
|
+
*/
|
|
152
|
+
async addPet(body: Pet): Promise<z.infer<typeof Pet>> {
|
|
148
153
|
return Pet.parse(
|
|
149
154
|
await this.#makeRequest('POST', '/pet', {data: body, contentType: 'application/x-www-form-urlencoded'}),
|
|
150
155
|
);
|
|
151
156
|
}
|
|
152
|
-
|
|
157
|
+
/**
|
|
158
|
+
* Update an existing pet
|
|
159
|
+
*
|
|
160
|
+
* Update an existing pet by Id
|
|
161
|
+
* @param body Update an existent pet in the store
|
|
162
|
+
* @returns {z.infer<typeof Pet>}
|
|
163
|
+
*/
|
|
164
|
+
async updatePet(body: Pet): Promise<z.infer<typeof Pet>> {
|
|
153
165
|
return Pet.parse(
|
|
154
166
|
await this.#makeRequest('PUT', '/pet', {data: body, contentType: 'application/x-www-form-urlencoded'}),
|
|
155
167
|
);
|
|
156
168
|
}
|
|
157
|
-
|
|
169
|
+
/**
|
|
170
|
+
* Finds Pets by status
|
|
171
|
+
*
|
|
172
|
+
* Multiple status values can be provided with comma separated strings
|
|
173
|
+
*
|
|
174
|
+
* @param status Status values that need to be considered for filter
|
|
175
|
+
* @returns {z.infer<typeof Pet>[]}
|
|
176
|
+
*/
|
|
177
|
+
async findPetsByStatus(status?: string): Promise<z.infer<typeof Pet>[]> {
|
|
158
178
|
return await this.#makeRequest('GET', '/pet/findByStatus', {params: {status: status}});
|
|
159
179
|
}
|
|
160
|
-
|
|
180
|
+
/**
|
|
181
|
+
* Finds Pets by tags
|
|
182
|
+
*
|
|
183
|
+
* Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.
|
|
184
|
+
*
|
|
185
|
+
* @param tags Tags to filter by
|
|
186
|
+
* @returns {z.infer<typeof Pet>[]}
|
|
187
|
+
*/
|
|
188
|
+
async findPetsByTags(tags?: string[]): Promise<z.infer<typeof Pet>[]> {
|
|
161
189
|
return await this.#makeRequest('GET', '/pet/findByTags', {params: {tags: tags}});
|
|
162
190
|
}
|
|
163
|
-
|
|
191
|
+
/**
|
|
192
|
+
* Find pet by ID
|
|
193
|
+
*
|
|
194
|
+
* Returns a single pet
|
|
195
|
+
*
|
|
196
|
+
* @param petId ID of pet to return
|
|
197
|
+
* @returns {z.infer<typeof Pet>}
|
|
198
|
+
*/
|
|
199
|
+
async getPetById(petId: number): Promise<z.infer<typeof Pet>> {
|
|
164
200
|
return Pet.parse(await this.#makeRequest('GET', `/pet/${petId}`, {}));
|
|
165
201
|
}
|
|
202
|
+
/**
|
|
203
|
+
* Updates a pet in the store with form data
|
|
204
|
+
*
|
|
205
|
+
* @param petId ID of pet that needs to be updated
|
|
206
|
+
* @param name Name of pet that needs to be updated
|
|
207
|
+
* @param status Status of pet that needs to be updated
|
|
208
|
+
* @returns {void}
|
|
209
|
+
*/
|
|
166
210
|
async updatePetWithForm(petId: number, name?: string, status?: string): Promise<void> {
|
|
167
211
|
return await this.#makeRequest('POST', `/pet/${petId}`, {params: {name: name, status: status}});
|
|
168
212
|
}
|
|
213
|
+
/**
|
|
214
|
+
* Deletes a pet
|
|
215
|
+
*
|
|
216
|
+
* delete a pet
|
|
217
|
+
*
|
|
218
|
+
* @param api_key
|
|
219
|
+
* @param petId Pet id to delete
|
|
220
|
+
* @returns {void}
|
|
221
|
+
*/
|
|
169
222
|
async deletePet(petId: number): Promise<void> {
|
|
170
223
|
return await this.#makeRequest('DELETE', `/pet/${petId}`, {});
|
|
171
224
|
}
|
|
172
|
-
|
|
225
|
+
/**
|
|
226
|
+
* uploads an image
|
|
227
|
+
*
|
|
228
|
+
* @param petId ID of pet to update
|
|
229
|
+
* @param additionalMetadata Additional Metadata
|
|
230
|
+
* @param body
|
|
231
|
+
* @returns {z.infer<typeof ApiResponse>}
|
|
232
|
+
*/
|
|
233
|
+
async uploadFile(petId: number, additionalMetadata?: string): Promise<z.infer<typeof ApiResponse>> {
|
|
173
234
|
return ApiResponse.parse(
|
|
174
235
|
await this.#makeRequest('POST', `/pet/${petId}/uploadImage`, {params: {additionalMetadata: additionalMetadata}}),
|
|
175
236
|
);
|
|
176
237
|
}
|
|
238
|
+
/**
|
|
239
|
+
* Returns pet inventories by status
|
|
240
|
+
*
|
|
241
|
+
* Returns a map of status codes to quantities
|
|
242
|
+
* @returns {Record<string, unknown>}
|
|
243
|
+
*/
|
|
177
244
|
async getInventory(): Promise<Record<string, unknown>> {
|
|
178
245
|
return await this.#makeRequest('GET', '/store/inventory', {});
|
|
179
246
|
}
|
|
180
|
-
|
|
247
|
+
/**
|
|
248
|
+
* Place an order for a pet
|
|
249
|
+
*
|
|
250
|
+
* Place a new order in the store
|
|
251
|
+
* @param body
|
|
252
|
+
* @returns {z.infer<typeof Order>}
|
|
253
|
+
*/
|
|
254
|
+
async placeOrder(body?: Order): Promise<z.infer<typeof Order>> {
|
|
181
255
|
return Order.parse(
|
|
182
256
|
await this.#makeRequest('POST', '/store/order', {data: body, contentType: 'application/x-www-form-urlencoded'}),
|
|
183
257
|
);
|
|
184
258
|
}
|
|
185
|
-
|
|
259
|
+
/**
|
|
260
|
+
* Find purchase order by ID
|
|
261
|
+
*
|
|
262
|
+
* For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions.
|
|
263
|
+
*
|
|
264
|
+
* @param orderId ID of order that needs to be fetched
|
|
265
|
+
* @returns {z.infer<typeof Order>}
|
|
266
|
+
*/
|
|
267
|
+
async getOrderById(orderId: number): Promise<z.infer<typeof Order>> {
|
|
186
268
|
return Order.parse(await this.#makeRequest('GET', `/store/order/${orderId}`, {}));
|
|
187
269
|
}
|
|
270
|
+
/**
|
|
271
|
+
* Delete purchase order by ID
|
|
272
|
+
*
|
|
273
|
+
* For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
|
|
274
|
+
*
|
|
275
|
+
* @param orderId ID of the order that needs to be deleted
|
|
276
|
+
* @returns {void}
|
|
277
|
+
*/
|
|
188
278
|
async deleteOrder(orderId: number): Promise<void> {
|
|
189
279
|
return await this.#makeRequest('DELETE', `/store/order/${orderId}`, {});
|
|
190
280
|
}
|
|
191
|
-
|
|
281
|
+
/**
|
|
282
|
+
* Create user
|
|
283
|
+
*
|
|
284
|
+
* This can only be done by the logged in user.
|
|
285
|
+
* @param body Created user object
|
|
286
|
+
* @returns {z.infer<typeof User>}
|
|
287
|
+
*/
|
|
288
|
+
async createUser(body?: User): Promise<z.infer<typeof User>> {
|
|
192
289
|
return User.parse(
|
|
193
290
|
await this.#makeRequest('POST', '/user', {data: body, contentType: 'application/x-www-form-urlencoded'}),
|
|
194
291
|
);
|
|
195
292
|
}
|
|
196
|
-
|
|
293
|
+
/**
|
|
294
|
+
* Creates list of users with given input array
|
|
295
|
+
* @param body
|
|
296
|
+
* @returns {z.infer<typeof User>}
|
|
297
|
+
*/
|
|
298
|
+
async createUsersWithListInput(body?: User[]): Promise<z.infer<typeof User>> {
|
|
197
299
|
return User.parse(await this.#makeRequest('POST', '/user/createWithList', {data: body}));
|
|
198
300
|
}
|
|
301
|
+
/**
|
|
302
|
+
* Logs user into the system
|
|
303
|
+
*
|
|
304
|
+
* @param username The user name for login
|
|
305
|
+
* @param password The password for login in clear text
|
|
306
|
+
* @returns {string}
|
|
307
|
+
*/
|
|
199
308
|
async loginUser(username?: string, password?: string): Promise<string> {
|
|
200
309
|
return await this.#makeRequest('GET', '/user/login', {params: {username: username, password: password}});
|
|
201
310
|
}
|
|
311
|
+
/**
|
|
312
|
+
* Logs out current logged in user session
|
|
313
|
+
* @returns {void}
|
|
314
|
+
*/
|
|
202
315
|
async logoutUser(): Promise<void> {
|
|
203
316
|
return await this.#makeRequest('GET', '/user/logout', {});
|
|
204
317
|
}
|
|
205
|
-
|
|
318
|
+
/**
|
|
319
|
+
* Get user by user name
|
|
320
|
+
*
|
|
321
|
+
* @param username The name that needs to be fetched. Use user1 for testing.
|
|
322
|
+
* @returns {z.infer<typeof User>}
|
|
323
|
+
*/
|
|
324
|
+
async getUserByName(username: string): Promise<z.infer<typeof User>> {
|
|
206
325
|
return User.parse(await this.#makeRequest('GET', `/user/${username}`, {}));
|
|
207
326
|
}
|
|
327
|
+
/**
|
|
328
|
+
* Update user
|
|
329
|
+
*
|
|
330
|
+
* This can only be done by the logged in user.
|
|
331
|
+
*
|
|
332
|
+
* @param username name that need to be deleted
|
|
333
|
+
* @param body Update an existent user in the store
|
|
334
|
+
* @returns {void}
|
|
335
|
+
*/
|
|
208
336
|
async updateUser(username: string, body?: User): Promise<void> {
|
|
209
337
|
return await this.#makeRequest('PUT', `/user/${username}`, {
|
|
210
338
|
data: body,
|
|
211
339
|
contentType: 'application/x-www-form-urlencoded',
|
|
212
340
|
});
|
|
213
341
|
}
|
|
342
|
+
/**
|
|
343
|
+
* Delete user
|
|
344
|
+
*
|
|
345
|
+
* This can only be done by the logged in user.
|
|
346
|
+
*
|
|
347
|
+
* @param username The name that needs to be deleted
|
|
348
|
+
* @returns {void}
|
|
349
|
+
*/
|
|
214
350
|
async deleteUser(username: string): Promise<void> {
|
|
215
351
|
return await this.#makeRequest('DELETE', `/user/${username}`, {});
|
|
216
352
|
}
|
package/package.json
CHANGED
|
@@ -53,6 +53,7 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
53
53
|
private buildAST(openapi: OpenApiSpecType): ts.Statement[] {
|
|
54
54
|
const imports = this.importBuilder.buildImports();
|
|
55
55
|
const schemas = this.buildSchemas(openapi);
|
|
56
|
+
const schemaTypeAliases = this.buildSchemaTypeAliases(schemas);
|
|
56
57
|
const serverConfig = this.buildServerConfiguration(openapi);
|
|
57
58
|
const clientClass = this.buildClientClass(openapi, schemas);
|
|
58
59
|
|
|
@@ -61,6 +62,7 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
61
62
|
...imports,
|
|
62
63
|
this.createComment('Components schemas'),
|
|
63
64
|
...Object.values(schemas),
|
|
65
|
+
...schemaTypeAliases,
|
|
64
66
|
...serverConfig,
|
|
65
67
|
this.createComment('Client class'),
|
|
66
68
|
clientClass,
|
|
@@ -97,6 +99,21 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
97
99
|
}, {});
|
|
98
100
|
}
|
|
99
101
|
|
|
102
|
+
private buildSchemaTypeAliases(schemas: Record<string, ts.VariableStatement>): ts.TypeAliasDeclaration[] {
|
|
103
|
+
return Object.keys(schemas).map((name) => {
|
|
104
|
+
const sanitizedName = this.typeBuilder.sanitizeIdentifier(name);
|
|
105
|
+
return ts.factory.createTypeAliasDeclaration(
|
|
106
|
+
[ts.factory.createToken(ts.SyntaxKind.ExportKeyword)],
|
|
107
|
+
ts.factory.createIdentifier(sanitizedName),
|
|
108
|
+
undefined,
|
|
109
|
+
ts.factory.createTypeReferenceNode(
|
|
110
|
+
ts.factory.createQualifiedName(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('infer')),
|
|
111
|
+
[ts.factory.createTypeQueryNode(ts.factory.createIdentifier(sanitizedName), undefined)],
|
|
112
|
+
),
|
|
113
|
+
);
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
100
117
|
private buildClientClass(
|
|
101
118
|
openapi: OpenApiSpecType,
|
|
102
119
|
schemas: Record<string, ts.VariableStatement>,
|
|
@@ -1265,6 +1282,37 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1265
1282
|
const responseSchema = response.content['application/json'].schema;
|
|
1266
1283
|
const typeName = this.getSchemaTypeName(responseSchema, schemas);
|
|
1267
1284
|
|
|
1285
|
+
// Handle array types like "Pet[]"
|
|
1286
|
+
if (typeName.endsWith('[]')) {
|
|
1287
|
+
const itemTypeName = typeName.slice(0, -2);
|
|
1288
|
+
const sanitizedItemTypeName = this.typeBuilder.sanitizeIdentifier(itemTypeName);
|
|
1289
|
+
|
|
1290
|
+
// Check if the item type is a custom schema (we have a type alias for it)
|
|
1291
|
+
if (schemas[sanitizedItemTypeName]) {
|
|
1292
|
+
// Use the type alias directly (it already uses z.infer)
|
|
1293
|
+
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
|
|
1294
|
+
ts.factory.createArrayTypeNode(
|
|
1295
|
+
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(sanitizedItemTypeName), undefined),
|
|
1296
|
+
),
|
|
1297
|
+
]);
|
|
1298
|
+
}
|
|
1299
|
+
// If it's a primitive array, use the type name as-is
|
|
1300
|
+
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
|
|
1301
|
+
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(typeName), undefined),
|
|
1302
|
+
]);
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
const sanitizedTypeName = this.typeBuilder.sanitizeIdentifier(typeName);
|
|
1306
|
+
|
|
1307
|
+
// Check if it's a custom schema type (we have a type alias for it)
|
|
1308
|
+
if (schemas[sanitizedTypeName]) {
|
|
1309
|
+
// Use the type name directly (we have a type alias that already uses z.infer)
|
|
1310
|
+
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
|
|
1311
|
+
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(sanitizedTypeName), undefined),
|
|
1312
|
+
]);
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
// For primitive types and Record types, use the type name directly
|
|
1268
1316
|
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
|
|
1269
1317
|
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(typeName), undefined),
|
|
1270
1318
|
]);
|