Skip to content

slight modifications for #237 #248

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Nov 23, 2022
Merged
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
21 changes: 20 additions & 1 deletion example/myzod/schemas.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import * as myzod from 'myzod'
import { AttributeInput, ButtonComponentType, ComponentInput, DropDownComponentInput, EventArgumentInput, EventInput, EventOptionType, HttpInput, HttpMethod, LayoutInput, PageInput, PageType, User } from '../types'
import { Admin, AttributeInput, ButtonComponentType, ComponentInput, DropDownComponentInput, EventArgumentInput, EventInput, EventOptionType, Guest, HttpInput, HttpMethod, LayoutInput, PageInput, PageType, User } from '../types'

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

export function AdminSchema(): myzod.Type<Admin> {
return myzod.object({
__typename: myzod.literal('Admin').optional(),
lastModifiedAt: definedNonNullAnySchema.optional().nullable()
})
}

export function AttributeInputSchema(): myzod.Type<AttributeInput> {
return myzod.object({
key: myzod.string().optional().nullable(),
Expand Down Expand Up @@ -45,6 +52,13 @@ export function EventInputSchema(): myzod.Type<EventInput> {

export const EventOptionTypeSchema = myzod.enum(EventOptionType);

export function GuestSchema(): myzod.Type<Guest> {
return myzod.object({
__typename: myzod.literal('Guest').optional(),
lastLoggedIn: definedNonNullAnySchema.optional().nullable()
})
}

export function HttpInputSchema(): myzod.Type<HttpInput> {
return myzod.object({
method: HttpMethodSchema.optional().nullable(),
Expand Down Expand Up @@ -84,8 +98,13 @@ export function UserSchema(): myzod.Type<User> {
createdAt: definedNonNullAnySchema.optional().nullable(),
email: myzod.string().optional().nullable(),
id: myzod.string().optional().nullable(),
kind: UserKindSchema().optional().nullable(),
name: myzod.string().optional().nullable(),
password: myzod.string().optional().nullable(),
updatedAt: definedNonNullAnySchema.optional().nullable()
})
}

export function UserKindSchema() {
return myzod.union([AdminSchema(), GuestSchema()])
}
11 changes: 11 additions & 0 deletions example/test.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,22 @@ enum PageType {
BASIC_AUTH
}

type Admin {
lastModifiedAt: Date
}

type Guest {
lastLoggedIn: Date
}

union UserKind = Admin | Guest

type User {
id: ID
name: String
email: String
password: String
kind: UserKind
createdAt: Date
updatedAt: Date
}
Expand Down
13 changes: 13 additions & 0 deletions example/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ export type Scalars = {
URL: any;
};

export type Admin = {
__typename?: 'Admin';
lastModifiedAt?: Maybe<Scalars['Date']>;
};

export type AttributeInput = {
key?: InputMaybe<Scalars['String']>;
val?: InputMaybe<Scalars['String']>;
Expand Down Expand Up @@ -52,6 +57,11 @@ export enum EventOptionType {
Retry = 'RETRY'
}

export type Guest = {
__typename?: 'Guest';
lastLoggedIn?: Maybe<Scalars['Date']>;
};

export type HttpInput = {
method?: InputMaybe<HttpMethod>;
url: Scalars['URL'];
Expand Down Expand Up @@ -92,7 +102,10 @@ export type User = {
createdAt?: Maybe<Scalars['Date']>;
email?: Maybe<Scalars['String']>;
id?: Maybe<Scalars['ID']>;
kind?: Maybe<UserKind>;
name?: Maybe<Scalars['String']>;
password?: Maybe<Scalars['String']>;
updatedAt?: Maybe<Scalars['Date']>;
};

export type UserKind = Admin | Guest;
27 changes: 26 additions & 1 deletion example/yup/schemas.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
import * as yup from 'yup'
import { AttributeInput, ButtonComponentType, ComponentInput, DropDownComponentInput, EventArgumentInput, EventInput, EventOptionType, HttpInput, HttpMethod, LayoutInput, PageInput, PageType, User } from '../types'
import { Admin, AttributeInput, ButtonComponentType, ComponentInput, DropDownComponentInput, EventArgumentInput, EventInput, EventOptionType, Guest, HttpInput, HttpMethod, LayoutInput, PageInput, PageType, User, UserKind } from '../types'

function union<T>(...schemas: ReadonlyArray<yup.SchemaOf<T>>): yup.BaseSchema<T> {
return yup.mixed().test({
test: (value) => schemas.some((schema) => schema.isValidSync(value))
})
}

export function AdminSchema(): yup.SchemaOf<Admin> {
return yup.object({
__typename: yup.mixed().oneOf(['Admin', undefined]),
lastModifiedAt: yup.mixed()
})
}

export function AttributeInputSchema(): yup.SchemaOf<AttributeInput> {
return yup.object({
Expand Down Expand Up @@ -43,6 +56,13 @@ export function EventInputSchema(): yup.SchemaOf<EventInput> {

export const EventOptionTypeSchema = yup.mixed().oneOf([EventOptionType.Reload, EventOptionType.Retry]);

export function GuestSchema(): yup.SchemaOf<Guest> {
return yup.object({
__typename: yup.mixed().oneOf(['Guest', undefined]),
lastLoggedIn: yup.mixed()
})
}

export function HttpInputSchema(): yup.SchemaOf<HttpInput> {
return yup.object({
method: HttpMethodSchema,
Expand Down Expand Up @@ -82,8 +102,13 @@ export function UserSchema(): yup.SchemaOf<User> {
createdAt: yup.mixed(),
email: yup.string(),
id: yup.string(),
kind: UserKindSchema(),
name: yup.string(),
password: yup.string(),
updatedAt: yup.mixed()
})
}

export function UserKindSchema(): yup.BaseSchema<UserKind> {
return union<UserKind>(AdminSchema(), GuestSchema())
}
21 changes: 20 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 { AttributeInput, ButtonComponentType, ComponentInput, DropDownComponentInput, EventArgumentInput, EventInput, EventOptionType, HttpInput, HttpMethod, LayoutInput, PageInput, PageType, User } from '../types'
import { Admin, AttributeInput, ButtonComponentType, ComponentInput, DropDownComponentInput, EventArgumentInput, EventInput, EventOptionType, Guest, HttpInput, HttpMethod, LayoutInput, PageInput, PageType, User } from '../types'

type Properties<T> = Required<{
[K in keyof T]: z.ZodType<T[K], any, T[K]>;
Expand All @@ -11,6 +11,13 @@ export const isDefinedNonNullAny = (v: any): v is definedNonNullAny => v !== und

export const definedNonNullAnySchema = z.any().refine((v) => isDefinedNonNullAny(v));

export function AdminSchema(): z.ZodObject<Properties<Admin>> {
return z.object<Properties<Admin>>({
__typename: z.literal('Admin').optional(),
lastModifiedAt: definedNonNullAnySchema.nullish()
})
}

export function AttributeInputSchema(): z.ZodObject<Properties<AttributeInput>> {
return z.object<Properties<AttributeInput>>({
key: z.string().nullish(),
Expand Down Expand Up @@ -53,6 +60,13 @@ export function EventInputSchema(): z.ZodObject<Properties<EventInput>> {

export const EventOptionTypeSchema = z.nativeEnum(EventOptionType);

export function GuestSchema(): z.ZodObject<Properties<Guest>> {
return z.object<Properties<Guest>>({
__typename: z.literal('Guest').optional(),
lastLoggedIn: definedNonNullAnySchema.nullish()
})
}

export function HttpInputSchema(): z.ZodObject<Properties<HttpInput>> {
return z.object<Properties<HttpInput>>({
method: HttpMethodSchema.nullish(),
Expand Down Expand Up @@ -92,8 +106,13 @@ export function UserSchema(): z.ZodObject<Properties<User>> {
createdAt: definedNonNullAnySchema.nullish(),
email: z.string().nullish(),
id: z.string().nullish(),
kind: UserKindSchema().nullish(),
name: z.string().nullish(),
password: z.string().nullish(),
updatedAt: definedNonNullAnySchema.nullish()
})
}

export function UserKindSchema() {
return z.union([AdminSchema(), GuestSchema()])
}
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
],
"scripts": {
"type-check": "tsc --noEmit",
"type-check:yup": "tsc --strict --noEmit example/yup/schemas.ts",
"type-check:zod": "tsc --strict --noEmit example/zod/schemas.ts",
"type-check:myzod": "tsc --strict --noEmit example/myzod/schemas.ts",
"test": "jest --no-watchman",
"build": "run-p build:*",
"build:main": "tsc -p tsconfig.main.json",
Expand Down
11 changes: 4 additions & 7 deletions src/myzod/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,20 +91,17 @@ export const MyZodSchemaVisitor = (schema: GraphQLSchema, config: ValidationSche
.withContent(`myzod.enum(${enumname})`).string;
},
UnionTypeDefinition: (node: UnionTypeDefinitionNode) => {
if (!node.types) return;

const unionName = tsVisitor.convertName(node.name.value);
const unionElements = node.types?.map(t => `${tsVisitor.convertName(t.name.value)}Schema()`).join(', ');
const unionElementsCount = node.types?.length ?? 0;

const union =
unionElementsCount > 1 ? indent(`return myzod.union([${unionElements}])`) : indent(`return ${unionElements}`);

const result = new DeclarationBlock({})
.export()
.asKind('function')
.withName(`${unionName}Schema()`)
.withBlock(union);

return result.string;
return new DeclarationBlock({}).export().asKind('function').withName(`${unionName}Schema()`).withBlock(union)
.string;
},
};
};
Expand Down
23 changes: 13 additions & 10 deletions src/yup/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export const YupSchemaVisitor = (schema: GraphQLSchema, config: ValidationSchema
return [importYup];
},
initialEmit: (): string =>
'\n' +
new DeclarationBlock({})
.asKind('function')
.withName('union<T>(...schemas: ReadonlyArray<yup.SchemaOf<T>>): yup.BaseSchema<T>')
Expand Down Expand Up @@ -101,22 +102,19 @@ export const YupSchemaVisitor = (schema: GraphQLSchema, config: ValidationSchema
.withContent(`yup.mixed().oneOf([${values}])`).string;
},
UnionTypeDefinition: (node: UnionTypeDefinitionNode) => {
if (!node.types) return;

const unionName = tsVisitor.convertName(node.name.value);
const unionElements = node.types?.map(t => `${tsVisitor.convertName(t.name.value)}Schema()`).join(', ');
const unionElementsCount = node.types?.length ?? 0;
importTypes.push(unionName);

const union =
unionElementsCount > 1
? indent(`return union<${unionName}>(${unionElements})`)
: indent(`return ${unionElements}`);
const unionElements = node.types?.map(t => `${tsVisitor.convertName(t.name.value)}Schema()`).join(', ');
const union = indent(`return union<${unionName}>(${unionElements})`);

const result = new DeclarationBlock({})
return new DeclarationBlock({})
.export()
.asKind('function')
.withName(`${unionName}Schema(): yup.BaseSchema<${unionName}>`)
.withBlock(union);

return result.string;
.withBlock(union).string;
},
// ScalarTypeDefinition: (node) => {
// const decl = new DeclarationBlock({})
Expand Down Expand Up @@ -209,6 +207,11 @@ const generateNameNodeYupSchema = (
return `${enumName}Schema`;
}

if (typ?.astNode?.kind === 'UnionTypeDefinition') {
const enumName = tsVisitor.convertName(typ.astNode.name.value);
return `${enumName}Schema()`;
}

const primitive = yup4Scalar(config, tsVisitor, node.value);
return primitive;
};
Expand Down
15 changes: 6 additions & 9 deletions src/zod/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,20 +102,17 @@ export const ZodSchemaVisitor = (schema: GraphQLSchema, config: ValidationSchema
.withContent(`z.nativeEnum(${enumname})`).string;
},
UnionTypeDefinition: (node: UnionTypeDefinitionNode) => {
if (!node.types) return;

const unionName = tsVisitor.convertName(node.name.value);
const unionElements = node.types?.map(t => `${tsVisitor.convertName(t.name.value)}Schema()`).join(', ');
const unionElementsCount = node.types?.length ?? 0;
const unionElements = node.types.map(t => `${tsVisitor.convertName(t.name.value)}Schema()`).join(', ');
const unionElementsCount = node.types.length ?? 0;

const union =
unionElementsCount > 1 ? indent(`return z.union([${unionElements}])`) : indent(`return ${unionElements}`);

const result = new DeclarationBlock({})
.export()
.asKind('function')
.withName(`${unionName}Schema()`)
.withBlock(union);

return result.string;
return new DeclarationBlock({}).export().asKind('function').withName(`${unionName}Schema()`).withBlock(union)
.string;
},
};
};
Expand Down
4 changes: 2 additions & 2 deletions tests/myzod.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,7 @@ describe('myzod', () => {
const wantContains = [
// Shape Schema
'export function ShapeSchema() {',
'myzod.union([CircleSchema(), SquareSchema()])',
'return myzod.union([CircleSchema(), SquareSchema()])',
'}',
];
for (const wantContain of wantContains) {
Expand Down Expand Up @@ -629,7 +629,7 @@ describe('myzod', () => {
const wantContains = [
// Shape Schema
'export function ShapeSchema() {',
'CircleSchema()',
'return CircleSchema()',
'}',
];
for (const wantContain of wantContains) {
Expand Down
4 changes: 2 additions & 2 deletions tests/yup.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ describe('yup', () => {
'export function GeometrySchema(): yup.SchemaOf<Geometry> {',
'return yup.object({',
"__typename: yup.mixed().oneOf(['Geometry', undefined]),",
'shape: yup.mixed()',
'shape: ShapeSchema()',
'})',
];
for (const wantContain of wantContains) {
Expand Down Expand Up @@ -542,7 +542,7 @@ describe('yup', () => {
const wantContains = [
// Shape Schema
'export function ShapeSchema(): yup.BaseSchema<Shape> {',
'CircleSchema()',
'return union<Shape>(CircleSchema())',
'}',
];
for (const wantContain of wantContains) {
Expand Down
4 changes: 2 additions & 2 deletions tests/zod.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -661,7 +661,7 @@ describe('zod', () => {
const wantContains = [
// Shape Schema
'export function ShapeSchema() {',
'z.union([CircleSchema(), SquareSchema()])',
'return z.union([CircleSchema(), SquareSchema()])',
'}',
];
for (const wantContain of wantContains) {
Expand Down Expand Up @@ -725,7 +725,7 @@ describe('zod', () => {
const wantContains = [
// Shape Schema
'export function ShapeSchema() {',
'CircleSchema()',
'return CircleSchema()',
'}',
];
for (const wantContain of wantContains) {
Expand Down