Skip to content

Commit ea8ebf3

Browse files
authored
Merge pull request #352 from Code-Hex/fix/285
fixed Union of enums: zod enum has no native call signature issue
2 parents f3140fd + 7a95924 commit ea8ebf3

File tree

7 files changed

+142
-5
lines changed

7 files changed

+142
-5
lines changed

example/yup/schemas.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as yup from 'yup'
22
import { Admin, AttributeInput, ButtonComponentType, ComponentInput, DropDownComponentInput, EventArgumentInput, EventInput, EventOptionType, Guest, HttpInput, HttpMethod, LayoutInput, PageInput, PageType, User, UserKind } from '../types'
33

4-
function union<T extends {}>(...schemas: ReadonlyArray<yup.ObjectSchema<T>>): yup.MixedSchema<T> {
4+
function union<T extends {}>(...schemas: ReadonlyArray<yup.Schema<T>>): yup.MixedSchema<T> {
55
return yup.mixed<T>().test({
66
test: (value) => schemas.some((schema) => schema.isValidSync(value))
77
}).defined()

src/myzod/index.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,16 @@ export const MyZodSchemaVisitor = (schema: GraphQLSchema, config: ValidationSche
102102
if (!node.types || !config.withObjectType) return;
103103

104104
const unionName = tsVisitor.convertName(node.name.value);
105-
const unionElements = node.types?.map(t => `${tsVisitor.convertName(t.name.value)}Schema()`).join(', ');
105+
const unionElements = node.types
106+
?.map(t => {
107+
const element = tsVisitor.convertName(t.name.value);
108+
const typ = schema.getType(t.name.value);
109+
if (typ?.astNode?.kind === 'EnumTypeDefinition') {
110+
return `${element}Schema`;
111+
}
112+
return `${element}Schema()`;
113+
})
114+
.join(', ');
106115
const unionElementsCount = node.types?.length ?? 0;
107116

108117
const union =

src/yup/index.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export const YupSchemaVisitor = (schema: GraphQLSchema, config: ValidationSchema
3636
'\n' +
3737
new DeclarationBlock({})
3838
.asKind('function')
39-
.withName('union<T extends {}>(...schemas: ReadonlyArray<yup.ObjectSchema<T>>): yup.MixedSchema<T>')
39+
.withName('union<T extends {}>(...schemas: ReadonlyArray<yup.Schema<T>>): yup.MixedSchema<T>')
4040
.withBlock(
4141
[
4242
indent('return yup.mixed<T>().test({'),
@@ -129,7 +129,16 @@ export const YupSchemaVisitor = (schema: GraphQLSchema, config: ValidationSchema
129129
const unionName = tsVisitor.convertName(node.name.value);
130130
importTypes.push(unionName);
131131

132-
const unionElements = node.types?.map(t => `${tsVisitor.convertName(t.name.value)}Schema()`).join(', ');
132+
const unionElements = node.types
133+
?.map(t => {
134+
const element = tsVisitor.convertName(t.name.value);
135+
const typ = schema.getType(t.name.value);
136+
if (typ?.astNode?.kind === 'EnumTypeDefinition') {
137+
return `${element}Schema`;
138+
}
139+
return `${element}Schema()`;
140+
})
141+
.join(', ');
133142
const union = indent(`return union<${unionName}>(${unionElements})`);
134143

135144
return new DeclarationBlock({})

src/zod/index.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,16 @@ export const ZodSchemaVisitor = (schema: GraphQLSchema, config: ValidationSchema
117117
if (!node.types || !config.withObjectType) return;
118118

119119
const unionName = tsVisitor.convertName(node.name.value);
120-
const unionElements = node.types.map(t => `${tsVisitor.convertName(t.name.value)}Schema()`).join(', ');
120+
const unionElements = node.types
121+
.map(t => {
122+
const element = tsVisitor.convertName(t.name.value);
123+
const typ = schema.getType(t.name.value);
124+
if (typ?.astNode?.kind === 'EnumTypeDefinition') {
125+
return `${element}Schema`;
126+
}
127+
return `${element}Schema()`;
128+
})
129+
.join(', ');
121130
const unionElementsCount = node.types.length ?? 0;
122131

123132
const union =

tests/myzod.spec.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,41 @@ describe('myzod', () => {
636636
expect(result.content).toContain(wantContain);
637637
}
638638
});
639+
640+
it('generate enum union types', async () => {
641+
const schema = buildSchema(/* GraphQL */ `
642+
enum PageType {
643+
PUBLIC
644+
BASIC_AUTH
645+
}
646+
647+
enum MethodType {
648+
GET
649+
POST
650+
}
651+
652+
union AnyType = PageType | MethodType
653+
`);
654+
655+
const result = await plugin(
656+
schema,
657+
[],
658+
{
659+
schema: 'myzod',
660+
withObjectType: true,
661+
},
662+
{}
663+
);
664+
665+
const wantContains = [
666+
'export function AnyTypeSchema() {',
667+
'return myzod.union([PageTypeSchema, MethodTypeSchema])',
668+
'}',
669+
];
670+
for (const wantContain of wantContains) {
671+
expect(result.content).toContain(wantContain);
672+
}
673+
});
639674
});
640675

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

tests/yup.spec.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,41 @@ describe('yup', () => {
551551
expect(result.content).toContain(wantContain);
552552
}
553553
});
554+
555+
it('generate enum union types', async () => {
556+
const schema = buildSchema(/* GraphQL */ `
557+
enum PageType {
558+
PUBLIC
559+
BASIC_AUTH
560+
}
561+
562+
enum MethodType {
563+
GET
564+
POST
565+
}
566+
567+
union AnyType = PageType | MethodType
568+
`);
569+
570+
const result = await plugin(
571+
schema,
572+
[],
573+
{
574+
schema: 'yup',
575+
withObjectType: true,
576+
},
577+
{}
578+
);
579+
580+
const wantContains = [
581+
'export function AnyTypeSchema(): yup.MixedSchema<AnyType> {',
582+
'union<AnyType>(PageTypeSchema, MethodTypeSchema)',
583+
'}',
584+
];
585+
for (const wantContain of wantContains) {
586+
expect(result.content).toContain(wantContain);
587+
}
588+
});
554589
});
555590

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

tests/zod.spec.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@ describe('zod', () => {
320320
expect(result.prepend).toContain("import { SayI } from './types'");
321321
expect(result.content).toContain('export function SayISchema(): z.ZodObject<Properties<SayI>> {');
322322
});
323+
323324
describe('issues #19', () => {
324325
it('string field', async () => {
325326
const schema = buildSchema(/* GraphQL */ `
@@ -351,6 +352,7 @@ describe('zod', () => {
351352
expect(result.content).toContain(wantContain);
352353
}
353354
});
355+
354356
it('not null field', async () => {
355357
const schema = buildSchema(/* GraphQL */ `
356358
input UserCreateInput {
@@ -381,6 +383,7 @@ describe('zod', () => {
381383
expect(result.content).toContain(wantContain);
382384
}
383385
});
386+
384387
it('list field', async () => {
385388
const schema = buildSchema(/* GraphQL */ `
386389
input UserCreateInput {
@@ -412,6 +415,7 @@ describe('zod', () => {
412415
}
413416
});
414417
});
418+
415419
describe('PR #112', () => {
416420
it('with notAllowEmptyString', async () => {
417421
const schema = buildSchema(/* GraphQL */ `
@@ -476,6 +480,7 @@ describe('zod', () => {
476480
}
477481
});
478482
});
483+
479484
describe('with withObjectType', () => {
480485
const schema = buildSchema(/* GraphQL */ `
481486
input ScalarsInput {
@@ -732,6 +737,41 @@ describe('zod', () => {
732737
expect(result.content).toContain(wantContain);
733738
}
734739
});
740+
741+
it('generate enum union types', async () => {
742+
const schema = buildSchema(/* GraphQL */ `
743+
enum PageType {
744+
PUBLIC
745+
BASIC_AUTH
746+
}
747+
748+
enum MethodType {
749+
GET
750+
POST
751+
}
752+
753+
union AnyType = PageType | MethodType
754+
`);
755+
756+
const result = await plugin(
757+
schema,
758+
[],
759+
{
760+
schema: 'zod',
761+
withObjectType: true,
762+
},
763+
{}
764+
);
765+
766+
const wantContains = [
767+
'export function AnyTypeSchema() {',
768+
'return z.union([PageTypeSchema, MethodTypeSchema])',
769+
'}',
770+
];
771+
for (const wantContain of wantContains) {
772+
expect(result.content).toContain(wantContain);
773+
}
774+
});
735775
});
736776

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

0 commit comments

Comments
 (0)