Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion example/myzod/schemas.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as myzod from 'myzod'
import { Admin, AttributeInput, ButtonComponentType, ComponentInput, DropDownComponentInput, EventArgumentInput, EventInput, EventOptionType, Guest, HttpInput, HttpMethod, LayoutInput, PageInput, PageType, User } from '../types'
import { Admin, AttributeInput, ButtonComponentType, ComponentInput, DropDownComponentInput, EventArgumentInput, EventInput, EventOptionType, Guest, HttpInput, HttpMethod, InnerType, LayoutInput, OuterType, PageInput, PageType, User } from '../types'

export const definedNonNullAnySchema = myzod.object({});

Expand Down Expand Up @@ -68,12 +68,26 @@ export function HttpInputSchema(): myzod.Type<HttpInput> {

export const HttpMethodSchema = myzod.enum(HttpMethod);

export function InnerTypeSchema(): myzod.Type<InnerType> {
return myzod.object({
__typename: myzod.literal('InnerType').optional(),
testScalar: definedNonNullAnySchema
})
}

export function LayoutInputSchema(): myzod.Type<LayoutInput> {
return myzod.object({
dropdown: myzod.lazy(() => DropDownComponentInputSchema().optional().nullable())
})
}

export function OuterTypeSchema(): myzod.Type<OuterType> {
return myzod.object({
__typename: myzod.literal('OuterType').optional(),
inner: InnerTypeSchema().optional().nullable()
})
}

export function PageInputSchema(): myzod.Type<PageInput> {
return myzod.object({
attributes: myzod.array(myzod.lazy(() => AttributeInputSchema())).optional().nullable(),
Expand Down
10 changes: 10 additions & 0 deletions example/test.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ type Guest {

union UserKind = Admin | Guest

type InnerType {
testScalar: MyScalar!
}

type OuterType {
inner: InnerType
}

scalar MyScalar

type User {
id: ID
name: String
Expand Down
11 changes: 11 additions & 0 deletions example/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export type Scalars = {
Int: { input: number; output: number; }
Float: { input: number; output: number; }
Date: { input: any; output: any; }
MyScalar: { input: any; output: any; }
URL: { input: any; output: any; }
};

Expand Down Expand Up @@ -74,10 +75,20 @@ export enum HttpMethod {
Post = 'POST'
}

export type InnerType = {
__typename?: 'InnerType';
testScalar: Scalars['MyScalar']['output'];
};

export type LayoutInput = {
dropdown?: InputMaybe<DropDownComponentInput>;
};

export type OuterType = {
__typename?: 'OuterType';
inner?: Maybe<InnerType>;
};

export type PageInput = {
attributes?: InputMaybe<Array<AttributeInput>>;
date?: InputMaybe<Scalars['Date']['input']>;
Expand Down
28 changes: 21 additions & 7 deletions example/yup/schemas.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import * as yup from 'yup'
import { Admin, AttributeInput, ButtonComponentType, ComponentInput, DropDownComponentInput, EventArgumentInput, EventInput, EventOptionType, Guest, HttpInput, HttpMethod, LayoutInput, PageInput, PageType, User, UserKind } from '../types'
import { Admin, AttributeInput, ButtonComponentType, ComponentInput, DropDownComponentInput, EventArgumentInput, EventInput, EventOptionType, Guest, HttpInput, HttpMethod, InnerType, LayoutInput, OuterType, PageInput, PageType, User, UserKind } from '../types'

function union<T extends {}>(...schemas: ReadonlyArray<yup.Schema<T>>): yup.MixedSchema<T> {
return yup.mixed<T>().test({
test: (value) => schemas.some((schema) => schema.isValidSync(value))
}).defined()
}

export function AdminSchema(): yup.ObjectSchema<Admin> {
export function AdminSchema(): yup.Schema {
return yup.object({
__typename: yup.string<'Admin'>().optional(),
lastModifiedAt: yup.mixed().nullable().optional()
})
}) satisfies yup.ObjectSchema<Admin>
}

export function AttributeInputSchema(): yup.ObjectSchema<AttributeInput> {
Expand Down Expand Up @@ -56,11 +56,11 @@ export function EventInputSchema(): yup.ObjectSchema<EventInput> {

export const EventOptionTypeSchema = yup.string<EventOptionType>().oneOf([EventOptionType.Reload, EventOptionType.Retry]).defined();

export function GuestSchema(): yup.ObjectSchema<Guest> {
export function GuestSchema(): yup.Schema {
return yup.object({
__typename: yup.string<'Guest'>().optional(),
lastLoggedIn: yup.mixed().nullable().optional()
})
}) satisfies yup.ObjectSchema<Guest>
}

export function HttpInputSchema(): yup.ObjectSchema<HttpInput> {
Expand All @@ -72,12 +72,26 @@ export function HttpInputSchema(): yup.ObjectSchema<HttpInput> {

export const HttpMethodSchema = yup.string<HttpMethod>().oneOf([HttpMethod.Get, HttpMethod.Post]).defined();

export function InnerTypeSchema(): yup.Schema {
return yup.object({
__typename: yup.string<'InnerType'>().optional(),
testScalar: yup.mixed().nonNullable()
}) satisfies yup.ObjectSchema<InnerType>
}

export function LayoutInputSchema(): yup.ObjectSchema<LayoutInput> {
return yup.object({
dropdown: yup.lazy(() => DropDownComponentInputSchema()).optional()
})
}

export function OuterTypeSchema(): yup.Schema {
return yup.object({
__typename: yup.string<'OuterType'>().optional(),
inner: InnerTypeSchema().nullable().optional()
}) satisfies yup.ObjectSchema<OuterType>
}

export function PageInputSchema(): yup.ObjectSchema<PageInput> {
return yup.object({
attributes: yup.array(yup.lazy(() => AttributeInputSchema().nonNullable())).defined().nullable().optional(),
Expand All @@ -96,7 +110,7 @@ export function PageInputSchema(): yup.ObjectSchema<PageInput> {

export const PageTypeSchema = yup.string<PageType>().oneOf([PageType.BasicAuth, PageType.Lp, PageType.Restricted, PageType.Service]).defined();

export function UserSchema(): yup.ObjectSchema<User> {
export function UserSchema(): yup.Schema {
return yup.object({
__typename: yup.string<'User'>().optional(),
createdAt: yup.mixed().nullable().optional(),
Expand All @@ -106,7 +120,7 @@ export function UserSchema(): yup.ObjectSchema<User> {
name: yup.string().defined().nullable().optional(),
password: yup.string().defined().nullable().optional(),
updatedAt: yup.mixed().nullable().optional()
})
}) satisfies yup.ObjectSchema<User>
}

export function UserKindSchema(): yup.MixedSchema<UserKind> {
Expand Down
16 changes: 15 additions & 1 deletion example/zod/schemas.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { z } from 'zod'
import { Admin, AttributeInput, ButtonComponentType, ComponentInput, DropDownComponentInput, EventArgumentInput, EventInput, EventOptionType, Guest, HttpInput, HttpMethod, LayoutInput, PageInput, PageType, User } from '../types'
import { Admin, AttributeInput, ButtonComponentType, ComponentInput, DropDownComponentInput, EventArgumentInput, EventInput, EventOptionType, Guest, HttpInput, HttpMethod, InnerType, LayoutInput, OuterType, PageInput, PageType, User } from '../types'

type Properties<T> = Required<{
[K in keyof T]: z.ZodType<T[K], any, T[K]>;
Expand Down Expand Up @@ -76,12 +76,26 @@ export function HttpInputSchema(): z.ZodObject<Properties<HttpInput>> {

export const HttpMethodSchema = z.nativeEnum(HttpMethod);

export function InnerTypeSchema(): z.ZodObject<Properties<InnerType>> {
return z.object<Properties<InnerType>>({
__typename: z.literal('InnerType').optional(),
testScalar: definedNonNullAnySchema
})
}

export function LayoutInputSchema(): z.ZodObject<Properties<LayoutInput>> {
return z.object<Properties<LayoutInput>>({
dropdown: z.lazy(() => DropDownComponentInputSchema().nullish())
})
}

export function OuterTypeSchema(): z.ZodObject<Properties<OuterType>> {
return z.object<Properties<OuterType>>({
__typename: z.literal('OuterType').optional(),
inner: InnerTypeSchema().nullish()
})
}

export function PageInputSchema(): z.ZodObject<Properties<PageInput>> {
return z.object<Properties<PageInput>>({
attributes: z.array(z.lazy(() => AttributeInputSchema())).nullish(),
Expand Down
4 changes: 2 additions & 2 deletions src/yup/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,13 @@ export const YupSchemaVisitor = (schema: GraphQLSchema, config: ValidationSchema
return new DeclarationBlock({})
.export()
.asKind('function')
.withName(`${name}Schema(): yup.ObjectSchema<${name}>`)
.withName(`${name}Schema(): yup.Schema`)
.withBlock(
[
indent(`return yup.object({`),
indent(`__typename: yup.string<'${node.name.value}'>().optional(),`, 2),
shape,
indent('})'),
indent(`}) satisfies yup.ObjectSchema<${name}>`),
].join('\n')
).string;
}),
Expand Down
16 changes: 10 additions & 6 deletions tests/yup.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -408,20 +408,23 @@ describe('yup', () => {
{}
);
const wantContains = [
'export function AuthorSchema(): yup.ObjectSchema<Author> {',
'export function AuthorSchema(): yup.Schema {',
"__typename: yup.string<'Author'>().optional(),",
'books: yup.array(BookSchema().nullable()).defined().nullable().optional(),',
'name: yup.string().defined().nullable().optional()',
'}) satisfies yup.ObjectSchema<Author>',

'export function BookSchema(): yup.ObjectSchema<Book> {',
'export function BookSchema(): yup.Schema {',
"__typename: yup.string<'Book'>().optional(),",
'author: AuthorSchema().nullable().optional(),',
'title: yup.string().defined().nonNullable()',
'}) satisfies yup.ObjectSchema<Book>',

'export function Book2Schema(): yup.ObjectSchema<Book2> {',
'export function Book2Schema(): yup.Schema {',
"__typename: yup.string<'Book2'>().optional(),",
'author: AuthorSchema().nonNullable(),',
'title: yup.string().defined().nullable().optional()',
'}) satisfies yup.ObjectSchema<Book2>',
];
for (const wantContain of wantContains) {
expect(result.content).toContain(wantContain);
Expand Down Expand Up @@ -497,14 +500,15 @@ describe('yup', () => {
'updateInputId: yup.number().defined().nonNullable(),',
'updateName: yup.string().defined().nonNullable()',
// User
'export function UserSchema(): yup.ObjectSchema<User> {',
'export function UserSchema(): yup.Schema {',
"__typename: yup.string<'User'>().optional(),",
'id: yup.string().defined().nonNullable(),',
'name: yup.string().defined().nullable().optional(),',
'age: yup.number().defined().nullable().optional(),',
'isMember: yup.boolean().defined().nullable().optional(),',
'email: yup.string().email().defined().nullable().optional(),',
'createdAt: yup.date().defined().nonNullable()',
'}) satisfies yup.ObjectSchema<User>',
];
for (const wantContain of wantContains) {
expect(result.content).toContain(wantContain);
Expand Down Expand Up @@ -573,11 +577,11 @@ describe('yup', () => {
);

const wantContains = [
'export function GeometrySchema(): yup.ObjectSchema<Geometry> {',
'export function GeometrySchema(): yup.Schema {',
'return yup.object({',
"__typename: yup.string<'Geometry'>().optional(),",
'shape: ShapeSchema().nullable().optional()',
'})',
'}) satisfies yup.ObjectSchema<Geometry>',
];
for (const wantContain of wantContains) {
expect(result.content).toContain(wantContain);
Expand Down