Skip to content

Commit 8535755

Browse files
authored
Merge pull request #529 from bramvanderholst/feature/default-input-values
2 parents 9fd0487 + 5723a0e commit 8535755

File tree

6 files changed

+166
-23
lines changed

6 files changed

+166
-23
lines changed

src/myzod/index.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
GraphQLSchema,
66
InputObjectTypeDefinitionNode,
77
InputValueDefinitionNode,
8+
Kind,
89
NameNode,
910
ObjectTypeDefinitionNode,
1011
TypeNode,
@@ -234,7 +235,19 @@ const generateFieldTypeMyZodSchema = (
234235
if (isListType(parentType)) {
235236
return `${gen}.nullable()`;
236237
}
237-
const appliedDirectivesGen = applyDirectives(config, field, gen);
238+
let appliedDirectivesGen = applyDirectives(config, field, gen);
239+
240+
if (field.kind === Kind.INPUT_VALUE_DEFINITION) {
241+
const { defaultValue } = field;
242+
243+
if (defaultValue?.kind === Kind.INT || defaultValue?.kind === Kind.FLOAT || defaultValue?.kind === Kind.BOOLEAN) {
244+
appliedDirectivesGen = `${appliedDirectivesGen}.default(${defaultValue.value})`;
245+
}
246+
if ((defaultValue?.kind === Kind.STRING) || (defaultValue?.kind === Kind.ENUM)) {
247+
appliedDirectivesGen = `${appliedDirectivesGen}.default("${defaultValue.value}")`;
248+
}
249+
}
250+
238251
if (isNonNullType(parentType)) {
239252
if (visitor.shouldEmitAsNotAllowEmptyString(type.name.value)) {
240253
return `${gen}.min(1)`;

src/yup/index.ts

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
GraphQLSchema,
66
InputObjectTypeDefinitionNode,
77
InputValueDefinitionNode,
8+
Kind,
89
NameNode,
910
ObjectTypeDefinitionNode,
1011
TypeNode,
@@ -68,12 +69,7 @@ export class YupSchemaVisitor extends BaseSchemaVisitor {
6869
const appendArguments = argumentBlocks ? '\n' + argumentBlocks : '';
6970

7071
// Building schema for fields.
71-
const shape = node.fields
72-
?.map(field => {
73-
const fieldSchema = generateFieldYupSchema(this.config, visitor, field, 2);
74-
return isNonNullType(field.type) ? fieldSchema : `${fieldSchema}.optional()`;
75-
})
76-
.join(',\n');
72+
const shape = shapeFields(node.fields, this.config, visitor)
7773

7874
switch (this.config.validationSchemaExportType) {
7975
case 'const':
@@ -203,12 +199,7 @@ export class YupSchemaVisitor extends BaseSchemaVisitor {
203199
visitor: Visitor,
204200
name: string
205201
) {
206-
const shape = fields
207-
?.map(field => {
208-
const fieldSchema = generateFieldYupSchema(this.config, visitor, field, 2);
209-
return isNonNullType(field.type) ? fieldSchema : `${fieldSchema}.optional()`;
210-
})
211-
.join(',\n');
202+
const shape = shapeFields(fields, this.config, visitor)
212203

213204
switch (this.config.validationSchemaExportType) {
214205
case 'const':
@@ -229,6 +220,30 @@ export class YupSchemaVisitor extends BaseSchemaVisitor {
229220
}
230221
}
231222

223+
const shapeFields = (fields: readonly (FieldDefinitionNode | InputValueDefinitionNode)[] | undefined, config: ValidationSchemaPluginConfig, visitor: Visitor) => {
224+
return fields?.map(field => {
225+
let fieldSchema = generateFieldYupSchema(config, visitor, field, 2);
226+
227+
if (field.kind === Kind.INPUT_VALUE_DEFINITION) {
228+
const { defaultValue } = field;
229+
230+
if (defaultValue?.kind === Kind.INT || defaultValue?.kind === Kind.FLOAT || defaultValue?.kind === Kind.BOOLEAN) {
231+
fieldSchema = `${fieldSchema}.default(${defaultValue.value})`;
232+
}
233+
if ((defaultValue?.kind === Kind.STRING) || (defaultValue?.kind === Kind.ENUM)) {
234+
fieldSchema = `${fieldSchema}.default("${defaultValue.value}")`;
235+
}
236+
}
237+
238+
if(isNonNullType(field.type)) {
239+
return fieldSchema
240+
}
241+
242+
return `${fieldSchema}.optional()`;
243+
})
244+
.join(',\n');
245+
}
246+
232247
const generateFieldYupSchema = (
233248
config: ValidationSchemaPluginConfig,
234249
visitor: Visitor,

src/zod/index.ts

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
GraphQLSchema,
66
InputObjectTypeDefinitionNode,
77
InputValueDefinitionNode,
8+
Kind,
89
NameNode,
910
ObjectTypeDefinitionNode,
1011
TypeNode,
@@ -129,16 +130,16 @@ export class ZodSchemaVisitor extends BaseSchemaVisitor {
129130
this.enumDeclarations.push(
130131
this.config.enumsAsTypes
131132
? new DeclarationBlock({})
132-
.export()
133-
.asKind('const')
134-
.withName(`${enumname}Schema`)
135-
.withContent(`z.enum([${node.values?.map(enumOption => `'${enumOption.name.value}'`).join(', ')}])`)
136-
.string
133+
.export()
134+
.asKind('const')
135+
.withName(`${enumname}Schema`)
136+
.withContent(`z.enum([${node.values?.map(enumOption => `'${enumOption.name.value}'`).join(', ')}])`)
137+
.string
137138
: new DeclarationBlock({})
138-
.export()
139-
.asKind('const')
140-
.withName(`${enumname}Schema`)
141-
.withContent(`z.nativeEnum(${enumname})`).string
139+
.export()
140+
.asKind('const')
141+
.withName(`${enumname}Schema`)
142+
.withContent(`z.nativeEnum(${enumname})`).string
142143
);
143144
},
144145
};
@@ -247,7 +248,19 @@ const generateFieldTypeZodSchema = (
247248
if (isListType(parentType)) {
248249
return `${gen}.nullable()`;
249250
}
250-
const appliedDirectivesGen = applyDirectives(config, field, gen);
251+
let appliedDirectivesGen = applyDirectives(config, field, gen);
252+
253+
if (field.kind === Kind.INPUT_VALUE_DEFINITION) {
254+
const { defaultValue } = field;
255+
256+
if (defaultValue?.kind === Kind.INT || defaultValue?.kind === Kind.FLOAT || defaultValue?.kind === Kind.BOOLEAN) {
257+
appliedDirectivesGen = `${appliedDirectivesGen}.default(${defaultValue.value})`;
258+
}
259+
if ((defaultValue?.kind === Kind.STRING) || (defaultValue?.kind === Kind.ENUM)) {
260+
appliedDirectivesGen = `${appliedDirectivesGen}.default("${defaultValue.value}")`;
261+
}
262+
}
263+
251264
if (isNonNullType(parentType)) {
252265
if (visitor.shouldEmitAsNotAllowEmptyString(type.name.value)) {
253266
return `${appliedDirectivesGen}.min(1)`;

tests/myzod.spec.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -991,4 +991,38 @@ describe('myzod', () => {
991991
}`;
992992
expect(result.content).toContain(wantContain);
993993
});
994+
995+
it('with default input values', async () => {
996+
const schema = buildSchema(/* GraphQL */ `
997+
enum PageType {
998+
PUBLIC
999+
BASIC_AUTH
1000+
}
1001+
input PageInput {
1002+
pageType: PageType! = PUBLIC
1003+
greeting: String = "Hello"
1004+
score: Int = 100
1005+
ratio: Float = 0.5
1006+
isMember: Boolean = true
1007+
}
1008+
`);
1009+
const result = await plugin(
1010+
schema,
1011+
[],
1012+
{
1013+
schema: 'myzod',
1014+
importFrom: './types',
1015+
},
1016+
{}
1017+
);
1018+
1019+
expect(result.content).toContain('export const PageTypeSchema = myzod.enum(PageType)');
1020+
expect(result.content).toContain('export function PageInputSchema(): myzod.Type<PageInput>');
1021+
1022+
expect(result.content).toContain('pageType: PageTypeSchema.default("PUBLIC")');
1023+
expect(result.content).toContain('greeting: myzod.string().default("Hello").optional().nullable()');
1024+
expect(result.content).toContain('score: myzod.number().default(100).optional().nullable()');
1025+
expect(result.content).toContain('ratio: myzod.number().default(0.5).optional().nullable()');
1026+
expect(result.content).toContain('isMember: myzod.boolean().default(true).optional().nullable()');
1027+
});
9941028
});

tests/yup.spec.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -905,4 +905,38 @@ describe('yup', () => {
905905
}`;
906906
expect(result.content).toContain(wantContain);
907907
});
908+
909+
it('with default input values', async () => {
910+
const schema = buildSchema(/* GraphQL */ `
911+
enum PageType {
912+
PUBLIC
913+
BASIC_AUTH
914+
}
915+
input PageInput {
916+
pageType: PageType! = PUBLIC
917+
greeting: String = "Hello"
918+
score: Int = 100
919+
ratio: Float = 0.5
920+
isMember: Boolean = true
921+
}
922+
`);
923+
const result = await plugin(
924+
schema,
925+
[],
926+
{
927+
schema: 'yup',
928+
importFrom: './types',
929+
},
930+
{}
931+
);
932+
933+
expect(result.content).toContain('export const PageTypeSchema = yup.string<PageType>().oneOf([PageType.Public, PageType.BasicAuth]).defined()');
934+
expect(result.content).toContain('export function PageInputSchema(): yup.ObjectSchema<PageInput>');
935+
936+
expect(result.content).toContain('pageType: PageTypeSchema.nonNullable().default("PUBLIC")');
937+
expect(result.content).toContain('greeting: yup.string().defined().nullable().default("Hello").optional()');
938+
expect(result.content).toContain('score: yup.number().defined().nullable().default(100).optional()');
939+
expect(result.content).toContain('ratio: yup.number().defined().nullable().default(0.5).optional()');
940+
expect(result.content).toContain('isMember: yup.boolean().defined().nullable().default(true).optional()');
941+
});
908942
});

tests/zod.spec.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,40 @@ describe('zod', () => {
403403
expect(result.content).toContain('export function SayISchema(): z.ZodObject<Properties<SayI>> {');
404404
});
405405

406+
it('with default input values', async () => {
407+
const schema = buildSchema(/* GraphQL */ `
408+
enum PageType {
409+
PUBLIC
410+
BASIC_AUTH
411+
}
412+
input PageInput {
413+
pageType: PageType! = PUBLIC
414+
greeting: String = "Hello"
415+
score: Int = 100
416+
ratio: Float = 0.5
417+
isMember: Boolean = true
418+
}
419+
`);
420+
const result = await plugin(
421+
schema,
422+
[],
423+
{
424+
schema: 'zod',
425+
importFrom: './types',
426+
},
427+
{}
428+
);
429+
430+
expect(result.content).toContain('export const PageTypeSchema = z.nativeEnum(PageType)');
431+
expect(result.content).toContain('export function PageInputSchema(): z.ZodObject<Properties<PageInput>>');
432+
433+
expect(result.content).toContain('pageType: PageTypeSchema.default("PUBLIC")');
434+
expect(result.content).toContain('greeting: z.string().default("Hello").nullish()');
435+
expect(result.content).toContain('score: z.number().default(100).nullish()');
436+
expect(result.content).toContain('ratio: z.number().default(0.5).nullish()');
437+
expect(result.content).toContain('isMember: z.boolean().default(true).nullish()');
438+
});
439+
406440
describe('issues #19', () => {
407441
it('string field', async () => {
408442
const schema = buildSchema(/* GraphQL */ `

0 commit comments

Comments
 (0)