Skip to content

Commit 510d990

Browse files
committed
fix some edge cases
1 parent 36ef007 commit 510d990

File tree

4 files changed

+154
-4
lines changed

4 files changed

+154
-4
lines changed

src/myzod/index.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,17 @@ export const MyZodSchemaVisitor = (schema: GraphQLSchema, config: ValidationSche
9292
},
9393
UnionTypeDefinition: (node: UnionTypeDefinitionNode) => {
9494
const unionName = tsVisitor.convertName(node.name.value);
95-
const unionElements = node.types?.map(t => `${t.name.value}Schema()`).join(', ');
95+
const unionElements = node.types?.map(t => `${tsVisitor.convertName(t.name.value)}Schema()`).join(', ');
96+
const unionElementsCount = node.types?.length ?? 0;
97+
98+
const union =
99+
unionElementsCount > 1 ? indent(`return myzod.union([${unionElements}])`) : indent(`return ${unionElements}`);
96100

97101
const result = new DeclarationBlock({})
98102
.export()
99103
.asKind('function')
100104
.withName(`${unionName}Schema()`)
101-
.withBlock(indent(`return myzod.union([${unionElements}])`));
105+
.withBlock(union);
102106

103107
return result.string;
104108
},
@@ -194,6 +198,11 @@ const generateNameNodeMyZodSchema = (
194198
return `${enumName}Schema`;
195199
}
196200

201+
if (typ?.astNode?.kind === 'UnionTypeDefinition') {
202+
const enumName = tsVisitor.convertName(typ.astNode.name.value);
203+
return `${enumName}Schema()`;
204+
}
205+
197206
return myzod4Scalar(config, tsVisitor, node.value);
198207
};
199208

src/zod/index.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,13 +103,17 @@ export const ZodSchemaVisitor = (schema: GraphQLSchema, config: ValidationSchema
103103
},
104104
UnionTypeDefinition: (node: UnionTypeDefinitionNode) => {
105105
const unionName = tsVisitor.convertName(node.name.value);
106-
const unionElements = node.types?.map(t => `${t.name.value}Schema()`).join(', ');
106+
const unionElements = node.types?.map(t => `${tsVisitor.convertName(t.name.value)}Schema()`).join(', ');
107+
const unionElementsCount = node.types?.length ?? 0;
108+
109+
const union =
110+
unionElementsCount > 1 ? indent(`return z.union([${unionElements}])`) : indent(`return ${unionElements}`);
107111

108112
const result = new DeclarationBlock({})
109113
.export()
110114
.asKind('function')
111115
.withName(`${unionName}Schema()`)
112-
.withBlock(indent(`return z.union([${unionElements}])`));
116+
.withBlock(union);
113117

114118
return result.string;
115119
},
@@ -205,6 +209,11 @@ const generateNameNodeZodSchema = (
205209
return `${enumName}Schema`;
206210
}
207211

212+
if (typ?.astNode?.kind === 'UnionTypeDefinition') {
213+
const enumName = tsVisitor.convertName(typ.astNode.name.value);
214+
return `${enumName}Schema()`;
215+
}
216+
208217
return zod4Scalar(config, tsVisitor, node.value);
209218
};
210219

tests/myzod.spec.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,72 @@ describe('myzod', () => {
570570
expect(result.content).toContain(wantContain);
571571
}
572572
});
573+
574+
it('generate union types with single element', async () => {
575+
const schema = buildSchema(/* GraphQL */ `
576+
type Square {
577+
size: Int
578+
}
579+
type Circle {
580+
radius: Int
581+
}
582+
union Shape = Circle | Square
583+
584+
type Geometry {
585+
shape: Shape
586+
}
587+
`);
588+
589+
const result = await plugin(
590+
schema,
591+
[],
592+
{
593+
schema: 'myzod',
594+
withObjectType: true,
595+
},
596+
{}
597+
);
598+
599+
const wantContains = [
600+
'export function GeometrySchema(): myzod.Type<Geometry> {',
601+
'return myzod.object({',
602+
"__typename: myzod.literal('Geometry').optional(),",
603+
'shape: ShapeSchema().optional().nullable()',
604+
'}',
605+
];
606+
for (const wantContain of wantContains) {
607+
expect(result.content).toContain(wantContain);
608+
}
609+
});
610+
611+
it('correctly reference generated union types', async () => {
612+
const schema = buildSchema(/* GraphQL */ `
613+
type Circle {
614+
radius: Int
615+
}
616+
union Shape = Circle
617+
`);
618+
619+
const result = await plugin(
620+
schema,
621+
[],
622+
{
623+
schema: 'myzod',
624+
withObjectType: true,
625+
},
626+
{}
627+
);
628+
629+
const wantContains = [
630+
// Shape Schema
631+
'export function ShapeSchema() {',
632+
'CircleSchema()',
633+
'}',
634+
];
635+
for (const wantContain of wantContains) {
636+
expect(result.content).toContain(wantContain);
637+
}
638+
});
573639
});
574640

575641
it('properly generates custom directive values', async () => {

tests/zod.spec.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,72 @@ describe('zod', () => {
668668
expect(result.content).toContain(wantContain);
669669
}
670670
});
671+
672+
it('generate union types with single element', async () => {
673+
const schema = buildSchema(/* GraphQL */ `
674+
type Square {
675+
size: Int
676+
}
677+
type Circle {
678+
radius: Int
679+
}
680+
union Shape = Circle | Square
681+
682+
type Geometry {
683+
shape: Shape
684+
}
685+
`);
686+
687+
const result = await plugin(
688+
schema,
689+
[],
690+
{
691+
schema: 'zod',
692+
withObjectType: true,
693+
},
694+
{}
695+
);
696+
697+
const wantContains = [
698+
'export function GeometrySchema(): z.ZodObject<Properties<Geometry>> {',
699+
'return z.object({',
700+
"__typename: z.literal('Geometry').optional(),",
701+
'shape: ShapeSchema().nullish()',
702+
'}',
703+
];
704+
for (const wantContain of wantContains) {
705+
expect(result.content).toContain(wantContain);
706+
}
707+
});
708+
709+
it('correctly reference generated union types', async () => {
710+
const schema = buildSchema(/* GraphQL */ `
711+
type Circle {
712+
radius: Int
713+
}
714+
union Shape = Circle
715+
`);
716+
717+
const result = await plugin(
718+
schema,
719+
[],
720+
{
721+
schema: 'zod',
722+
withObjectType: true,
723+
},
724+
{}
725+
);
726+
727+
const wantContains = [
728+
// Shape Schema
729+
'export function ShapeSchema() {',
730+
'CircleSchema()',
731+
'}',
732+
];
733+
for (const wantContain of wantContains) {
734+
expect(result.content).toContain(wantContain);
735+
}
736+
});
671737
});
672738

673739
it('properly generates custom directive values', async () => {

0 commit comments

Comments
 (0)