zod-codegen 1.2.1 → 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,8 @@
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
+
1
6
  ## <small>1.2.1 (2025-11-19)</small>
2
7
 
3
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)
@@ -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,36 +524,34 @@ export class TypeScriptCodeGeneratorService {
516
524
  }
517
525
  const responseSchema = response.content['application/json'].schema;
518
526
  const typeName = this.getSchemaTypeName(responseSchema, schemas);
519
- const inferredType = this.wrapTypeWithZInfer(typeName, schemas);
520
- return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [inferredType]);
521
- }
522
- wrapTypeWithZInfer(typeName, schemas) {
523
- // Primitive types and Record types don't need z.infer
524
- const primitiveTypes = ['string', 'number', 'boolean', 'unknown'];
525
- if (primitiveTypes.includes(typeName) || typeName.startsWith('Record<')) {
526
- return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(typeName), undefined);
527
- }
528
527
  // Handle array types like "Pet[]"
529
528
  if (typeName.endsWith('[]')) {
530
529
  const itemTypeName = typeName.slice(0, -2);
531
530
  const sanitizedItemTypeName = this.typeBuilder.sanitizeIdentifier(itemTypeName);
532
- // Check if the item type is a custom schema
531
+ // Check if the item type is a custom schema (we have a type alias for it)
533
532
  if (schemas[sanitizedItemTypeName]) {
534
- // Return z.infer<typeof ItemType>[]
535
- const zInferType = ts.factory.createTypeReferenceNode(ts.factory.createQualifiedName(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('infer')), [ts.factory.createTypeQueryNode(ts.factory.createIdentifier(sanitizedItemTypeName), undefined)]);
536
- return ts.factory.createArrayTypeNode(zInferType);
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
537
  }
538
- // If it's a primitive array, return as-is
539
- return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(typeName), undefined);
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
+ ]);
540
542
  }
541
- // Handle custom schema types
542
543
  const sanitizedTypeName = this.typeBuilder.sanitizeIdentifier(typeName);
544
+ // Check if it's a custom schema type (we have a type alias for it)
543
545
  if (schemas[sanitizedTypeName]) {
544
- // Return z.infer<typeof TypeName>
545
- return ts.factory.createTypeReferenceNode(ts.factory.createQualifiedName(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('infer')), [ts.factory.createTypeQueryNode(ts.factory.createIdentifier(sanitizedTypeName), undefined)]);
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
+ ]);
546
550
  }
547
- // Fallback: return as-is if we can't determine
548
- return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(typeName), undefined);
551
+ // For primitive types and Record types, use the type name directly
552
+ return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
553
+ ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(typeName), undefined),
554
+ ]);
549
555
  }
550
556
  buildServerConfiguration(openapi) {
551
557
  const servers = openapi.servers;
package/package.json CHANGED
@@ -110,5 +110,5 @@
110
110
  "release": "semantic-release",
111
111
  "release:dry": "semantic-release --dry-run"
112
112
  },
113
- "version": "1.2.1"
113
+ "version": "1.2.2"
114
114
  }
@@ -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>,
@@ -1264,48 +1281,41 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
1264
1281
 
1265
1282
  const responseSchema = response.content['application/json'].schema;
1266
1283
  const typeName = this.getSchemaTypeName(responseSchema, schemas);
1267
- const inferredType = this.wrapTypeWithZInfer(typeName, schemas);
1268
-
1269
- return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [inferredType]);
1270
- }
1271
-
1272
- private wrapTypeWithZInfer(typeName: string, schemas: Record<string, ts.VariableStatement>): ts.TypeNode {
1273
- // Primitive types and Record types don't need z.infer
1274
- const primitiveTypes = ['string', 'number', 'boolean', 'unknown'];
1275
- if (primitiveTypes.includes(typeName) || typeName.startsWith('Record<')) {
1276
- return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(typeName), undefined);
1277
- }
1278
1284
 
1279
1285
  // Handle array types like "Pet[]"
1280
1286
  if (typeName.endsWith('[]')) {
1281
1287
  const itemTypeName = typeName.slice(0, -2);
1282
1288
  const sanitizedItemTypeName = this.typeBuilder.sanitizeIdentifier(itemTypeName);
1283
1289
 
1284
- // Check if the item type is a custom schema
1290
+ // Check if the item type is a custom schema (we have a type alias for it)
1285
1291
  if (schemas[sanitizedItemTypeName]) {
1286
- // Return z.infer<typeof ItemType>[]
1287
- const zInferType = ts.factory.createTypeReferenceNode(
1288
- ts.factory.createQualifiedName(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('infer')),
1289
- [ts.factory.createTypeQueryNode(ts.factory.createIdentifier(sanitizedItemTypeName), undefined)],
1290
- );
1291
- return ts.factory.createArrayTypeNode(zInferType);
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
+ ]);
1292
1298
  }
1293
- // If it's a primitive array, return as-is
1294
- return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(typeName), undefined);
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
+ ]);
1295
1303
  }
1296
1304
 
1297
- // Handle custom schema types
1298
1305
  const sanitizedTypeName = this.typeBuilder.sanitizeIdentifier(typeName);
1306
+
1307
+ // Check if it's a custom schema type (we have a type alias for it)
1299
1308
  if (schemas[sanitizedTypeName]) {
1300
- // Return z.infer<typeof TypeName>
1301
- return ts.factory.createTypeReferenceNode(
1302
- ts.factory.createQualifiedName(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('infer')),
1303
- [ts.factory.createTypeQueryNode(ts.factory.createIdentifier(sanitizedTypeName), undefined)],
1304
- );
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
+ ]);
1305
1313
  }
1306
1314
 
1307
- // Fallback: return as-is if we can't determine
1308
- return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(typeName), undefined);
1315
+ // For primitive types and Record types, use the type name directly
1316
+ return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
1317
+ ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(typeName), undefined),
1318
+ ]);
1309
1319
  }
1310
1320
 
1311
1321
  private buildServerConfiguration(openapi: OpenApiSpecType): ts.Statement[] {