Skip to content

Commit e7007b3

Browse files
committed
fixed generation for field of the object type
1 parent fcccc86 commit e7007b3

File tree

6 files changed

+269
-88
lines changed

6 files changed

+269
-88
lines changed

src/myzod/index.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,12 +165,17 @@ const generateNameNodeMyZodSchema = (
165165
): string => {
166166
const typ = schema.getType(node.value);
167167

168-
if (typ && typ.astNode?.kind === 'InputObjectTypeDefinition') {
168+
if (typ?.astNode?.kind === 'InputObjectTypeDefinition') {
169169
const enumName = tsVisitor.convertName(typ.astNode.name.value);
170170
return `${enumName}Schema()`;
171171
}
172172

173-
if (typ && typ.astNode?.kind === 'EnumTypeDefinition') {
173+
if (typ?.astNode?.kind === 'ObjectTypeDefinition') {
174+
const enumName = tsVisitor.convertName(typ.astNode.name.value);
175+
return `${enumName}Schema()`;
176+
}
177+
178+
if (typ?.astNode?.kind === 'EnumTypeDefinition') {
174179
const enumName = tsVisitor.convertName(typ.astNode.name.value);
175180
return `${enumName}Schema`;
176181
}

src/yup/index.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,12 @@ const generateFieldTypeYupSchema = (
145145
return maybeLazy(type.type, nonNullGen);
146146
}
147147
if (isNamedType(type)) {
148-
return generateNameNodeYupSchema(config, tsVisitor, schema, type.name);
148+
const gen = generateNameNodeYupSchema(config, tsVisitor, schema, type.name);
149+
const typ = schema.getType(type.name.value);
150+
if (typ?.astNode?.kind === 'ObjectTypeDefinition') {
151+
return `${gen}.optional()`;
152+
}
153+
return gen;
149154
}
150155
console.warn('unhandled type:', type);
151156
return '';
@@ -159,12 +164,17 @@ const generateNameNodeYupSchema = (
159164
): string => {
160165
const typ = schema.getType(node.value);
161166

162-
if (typ && typ.astNode?.kind === 'InputObjectTypeDefinition') {
167+
if (typ?.astNode?.kind === 'InputObjectTypeDefinition') {
168+
const enumName = tsVisitor.convertName(typ.astNode.name.value);
169+
return `${enumName}Schema()`;
170+
}
171+
172+
if (typ?.astNode?.kind === 'ObjectTypeDefinition') {
163173
const enumName = tsVisitor.convertName(typ.astNode.name.value);
164174
return `${enumName}Schema()`;
165175
}
166176

167-
if (typ && typ.astNode?.kind === 'EnumTypeDefinition') {
177+
if (typ?.astNode?.kind === 'EnumTypeDefinition') {
168178
const enumName = tsVisitor.convertName(typ.astNode.name.value);
169179
return `${enumName}Schema`;
170180
}

src/zod/index.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,12 +176,17 @@ const generateNameNodeZodSchema = (
176176
): string => {
177177
const typ = schema.getType(node.value);
178178

179-
if (typ && typ.astNode?.kind === 'InputObjectTypeDefinition') {
179+
if (typ?.astNode?.kind === 'InputObjectTypeDefinition') {
180180
const enumName = tsVisitor.convertName(typ.astNode.name.value);
181181
return `${enumName}Schema()`;
182182
}
183183

184-
if (typ && typ.astNode?.kind === 'EnumTypeDefinition') {
184+
if (typ?.astNode?.kind === 'ObjectTypeDefinition') {
185+
const enumName = tsVisitor.convertName(typ.astNode.name.value);
186+
return `${enumName}Schema()`;
187+
}
188+
189+
if (typ?.astNode?.kind === 'EnumTypeDefinition') {
185190
const enumName = tsVisitor.convertName(typ.astNode.name.value);
186191
return `${enumName}Schema`;
187192
}
@@ -209,6 +214,6 @@ const zod4Scalar = (config: ValidationSchemaPluginConfig, tsVisitor: TsVisitor,
209214
case 'boolean':
210215
return `z.boolean()`;
211216
}
212-
console.warn('unhandled name:', scalarName);
217+
console.warn('unhandled scalar name:', scalarName);
213218
return anySchema;
214219
};

tests/myzod.spec.ts

Lines changed: 77 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -412,40 +412,13 @@ describe('myzod', () => {
412412
});
413413

414414
describe('with withObjectType', () => {
415-
const schema = buildSchema(/* GraphQL */ `
416-
input ScalarsInput {
417-
date: Date!
418-
email: Email
419-
}
420-
scalar Date
421-
scalar Email
422-
input UserCreateInput {
423-
name: String!
424-
email: Email!
425-
}
426-
type User {
427-
id: ID!
428-
name: String
429-
age: Int
430-
email: Email
431-
isMember: Boolean
432-
createdAt: Date!
433-
}
434-
435-
type Mutation {
436-
_empty: String
437-
}
438-
439-
type Query {
440-
_empty: String
441-
}
442-
443-
type Subscription {
444-
_empty: String
445-
}
446-
`);
447-
448415
it('not generate if withObjectType false', async () => {
416+
const schema = buildSchema(/* GraphQL */ `
417+
type User {
418+
id: ID!
419+
name: String
420+
}
421+
`);
449422
const result = await plugin(
450423
schema,
451424
[],
@@ -457,7 +430,77 @@ describe('myzod', () => {
457430
expect(result.content).not.toContain('export function UserSchema(): myzod.Type<User> {');
458431
});
459432

433+
it('generate object type contains object type', async () => {
434+
const schema = buildSchema(/* GraphQL */ `
435+
type Book {
436+
author: Author
437+
title: String
438+
}
439+
440+
type Author {
441+
books: [Book]
442+
name: String
443+
}
444+
`);
445+
const result = await plugin(
446+
schema,
447+
[],
448+
{
449+
schema: 'myzod',
450+
withObjectType: true,
451+
},
452+
{}
453+
);
454+
const wantContains = [
455+
'export function AuthorSchema(): myzod.Type<Author> {',
456+
"__typename: myzod.literal('Author').optional(),",
457+
'books: myzod.array(BookSchema().nullable()).optional().nullable(),',
458+
'name: myzod.string().optional().nullable()',
459+
460+
'export function BookSchema(): myzod.Type<Book> {',
461+
"__typename: myzod.literal('Book').optional(),",
462+
'author: AuthorSchema().optional().nullable(),',
463+
'title: myzod.string().optional().nullable()',
464+
];
465+
for (const wantContain of wantContains) {
466+
expect(result.content).toContain(wantContain);
467+
}
468+
469+
for (const wantNotContain of ['Query', 'Mutation', 'Subscription']) {
470+
expect(result.content).not.toContain(wantNotContain);
471+
}
472+
});
473+
460474
it('generate both input & type', async () => {
475+
const schema = buildSchema(/* GraphQL */ `
476+
scalar Date
477+
scalar Email
478+
input UserCreateInput {
479+
name: String!
480+
date: Date!
481+
email: Email!
482+
}
483+
type User {
484+
id: ID!
485+
name: String
486+
age: Int
487+
email: Email
488+
isMember: Boolean
489+
createdAt: Date!
490+
}
491+
492+
type Mutation {
493+
_empty: String
494+
}
495+
496+
type Query {
497+
_empty: String
498+
}
499+
500+
type Subscription {
501+
_empty: String
502+
}
503+
`);
461504
const result = await plugin(
462505
schema,
463506
[],
@@ -472,14 +515,10 @@ describe('myzod', () => {
472515
{}
473516
);
474517
const wantContains = [
475-
// ScalarsInput
476-
'export const definedNonNullAnySchema = myzod.object({});',
477-
'export function ScalarsInputSchema(): myzod.Type<ScalarsInput> {',
478-
'date: myzod.date(),',
479-
'email: myzod.string().email().optional().nullable(),',
480518
// User Create Input
481519
'export function UserCreateInputSchema(): myzod.Type<UserCreateInput> {',
482520
'name: myzod.string(),',
521+
'date: myzod.date(),',
483522
'email: myzod.string().email()',
484523
// User
485524
'export function UserSchema(): myzod.Type<User> {',

tests/yup.spec.ts

Lines changed: 87 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -314,52 +314,106 @@ describe('yup', () => {
314314
expect(result.content).toContain('export function SayISchema(): yup.SchemaOf<SayI> {');
315315
});
316316
describe('with withObjectType', () => {
317-
const schema = buildSchema(/* GraphQL */ `
318-
input ScalarsInput {
319-
date: Date!
320-
email: Email
321-
}
322-
scalar Date
323-
scalar Email
324-
input UserCreateInput {
325-
name: String!
326-
email: Email!
327-
}
328-
type User {
329-
id: ID!
330-
name: String
331-
age: Int
332-
email: Email
333-
isMember: Boolean
334-
createdAt: Date!
335-
}
336-
337-
type Mutation {
338-
_empty: String
339-
}
317+
it('not generate if withObjectType false', async () => {
318+
const schema = buildSchema(/* GraphQL */ `
319+
type User {
320+
id: ID!
321+
name: String
322+
}
323+
`);
324+
const result = await plugin(
325+
schema,
326+
[],
327+
{
328+
schema: 'yup',
329+
},
330+
{}
331+
);
332+
expect(result.content).not.toContain('export function UserSchema(): yup.SchemaOf<User> {');
333+
});
340334

341-
type Query {
342-
_empty: String
343-
}
335+
it('generate object type contains object type', async () => {
336+
const schema = buildSchema(/* GraphQL */ `
337+
type Book {
338+
author: Author
339+
title: String
340+
}
344341
345-
type Subscription {
346-
_empty: String
347-
}
348-
`);
342+
type Book2 {
343+
author: Author!
344+
title: String!
345+
}
349346
350-
it('not generate if withObjectType false', async () => {
347+
type Author {
348+
books: [Book]
349+
name: String
350+
}
351+
`);
351352
const result = await plugin(
352353
schema,
353354
[],
354355
{
355356
schema: 'yup',
357+
withObjectType: true,
356358
},
357359
{}
358360
);
359-
expect(result.content).not.toContain('export function UserSchema(): yup.SchemaOf<User> {');
361+
const wantContains = [
362+
'export function AuthorSchema(): yup.SchemaOf<Author> {',
363+
"__typename: yup.mixed().oneOf(['Author', undefined]),",
364+
'books: yup.array().of(BookSchema().optional()).optional(),',
365+
'name: yup.string()',
366+
367+
'export function BookSchema(): yup.SchemaOf<Book> {',
368+
"__typename: yup.mixed().oneOf(['Book', undefined]),",
369+
'author: AuthorSchema().optional(),',
370+
'title: yup.string()',
371+
372+
'export function Book2Schema(): yup.SchemaOf<Book2> {',
373+
"__typename: yup.mixed().oneOf(['Book2', undefined]),",
374+
'author: AuthorSchema().optional().defined(),',
375+
'title: yup.string().defined()',
376+
];
377+
for (const wantContain of wantContains) {
378+
expect(result.content).toContain(wantContain);
379+
}
380+
381+
for (const wantNotContain of ['Query', 'Mutation', 'Subscription']) {
382+
expect(result.content).not.toContain(wantNotContain);
383+
}
360384
});
361385

362386
it('generate both input & type if withObjectType true', async () => {
387+
const schema = buildSchema(/* GraphQL */ `
388+
scalar Date
389+
scalar Email
390+
input UserCreateInput {
391+
name: String!
392+
date: Date!
393+
email: Email!
394+
}
395+
type User {
396+
id: ID!
397+
name: String
398+
age: Int
399+
email: Email
400+
isMember: Boolean
401+
createdAt: Date!
402+
}
403+
404+
type Mutation {
405+
_empty: String
406+
}
407+
408+
type Query {
409+
_empty: String
410+
}
411+
412+
type Subscription {
413+
_empty: String
414+
}
415+
`);
416+
363417
const result = await plugin(
364418
schema,
365419
[],
@@ -374,14 +428,10 @@ describe('yup', () => {
374428
{}
375429
);
376430
const wantContains = [
377-
// ScalarsInput
378-
'export function ScalarsInputSchema(): yup.SchemaOf<ScalarsInput> {',
379-
'return yup.object({',
380-
'date: yup.date().defined(),',
381-
'email: yup.string().email()',
382431
// User Create Input
383432
'export function UserCreateInputSchema(): yup.SchemaOf<UserCreateInput> {',
384433
'name: yup.string().defined(),',
434+
'date: yup.date().defined(),',
385435
'email: yup.string().email().defined()',
386436
// User
387437
'export function UserSchema(): yup.SchemaOf<User> {',

0 commit comments

Comments
 (0)