diff --git a/README.md b/README.md index c37f4889..665a4d52 100644 --- a/README.md +++ b/README.md @@ -188,6 +188,12 @@ It is currently added for the purpose of using simple objects. See also [#20](ht This option currently **does not support fragment** generation. If you are interested, send me PR would be greatly appreciated! +### `validationSchemaExportType` + +type: `ValidationSchemaExportType` default: `'function'` + +Specify validation schema export type. + ### `directives` type: `DirectiveConfig` diff --git a/codegen.yml b/codegen.yml index b8b02819..b35f9fd3 100644 --- a/codegen.yml +++ b/codegen.yml @@ -13,7 +13,6 @@ generates: schema: yup importFrom: ../types withObjectType: true - validationSchemaExportType: const directives: required: msg: required @@ -50,7 +49,6 @@ generates: schema: zod importFrom: ../types withObjectType: true - validationSchemaExportType: const directives: # Write directives like # @@ -74,7 +72,6 @@ generates: schema: myzod importFrom: ../types withObjectType: true - validationSchemaExportType: const directives: constraint: minLength: min diff --git a/example/myzod/schemas.ts b/example/myzod/schemas.ts index c8526499..316c00d2 100644 --- a/example/myzod/schemas.ts +++ b/example/myzod/schemas.ts @@ -1,86 +1,110 @@ import * as myzod from 'myzod' -import { PageType, HttpMethod, HttpInput, EventOptionType, EventArgumentInput, EventInput, ComponentInput, DropDownComponentInput, LayoutInput, ButtonComponentType, AttributeInput, PageInput, Guest, Admin, 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 const PageTypeSchema = myzod.enum(PageType); - -export const HttpMethodSchema = myzod.enum(HttpMethod); +export const ButtonComponentTypeSchema = myzod.enum(ButtonComponentType); export const EventOptionTypeSchema = myzod.enum(EventOptionType); -export const ButtonComponentTypeSchema = myzod.enum(ButtonComponentType); - -export const HttpInputSchema: myzod.Type = myzod.object({ - method: HttpMethodSchema.optional().nullable(), - url: definedNonNullAnySchema -}); +export const HttpMethodSchema = myzod.enum(HttpMethod); -export const EventArgumentInputSchema: myzod.Type = myzod.object({ - name: myzod.string().min(5), - value: myzod.string().pattern(/^foo/) -}); +export const PageTypeSchema = myzod.enum(PageType); -export const EventInputSchema: myzod.Type = myzod.object({ - arguments: myzod.array(myzod.lazy(() => EventArgumentInputSchema)), - options: myzod.array(EventOptionTypeSchema).optional().nullable() -}); +export function AdminSchema(): myzod.Type { + return myzod.object({ + __typename: myzod.literal('Admin').optional(), + lastModifiedAt: definedNonNullAnySchema.optional().nullable() + }) +} -export const ComponentInputSchema: myzod.Type = myzod.object({ - child: myzod.lazy(() => ComponentInputSchema.optional().nullable()), - childrens: myzod.array(myzod.lazy(() => ComponentInputSchema.nullable())).optional().nullable(), - event: myzod.lazy(() => EventInputSchema.optional().nullable()), +export function AttributeInputSchema(): myzod.Type { + return myzod.object({ + key: myzod.string().optional().nullable(), + val: myzod.string().optional().nullable() + }) +} + +export function ComponentInputSchema(): myzod.Type { + return myzod.object({ + child: myzod.lazy(() => ComponentInputSchema().optional().nullable()), + childrens: myzod.array(myzod.lazy(() => ComponentInputSchema().nullable())).optional().nullable(), + event: myzod.lazy(() => EventInputSchema().optional().nullable()), name: myzod.string(), type: ButtonComponentTypeSchema -}); - -export const DropDownComponentInputSchema: myzod.Type = myzod.object({ - dropdownComponent: myzod.lazy(() => ComponentInputSchema.optional().nullable()), - getEvent: myzod.lazy(() => EventInputSchema) -}); + }) +} + +export function DropDownComponentInputSchema(): myzod.Type { + return myzod.object({ + dropdownComponent: myzod.lazy(() => ComponentInputSchema().optional().nullable()), + getEvent: myzod.lazy(() => EventInputSchema()) + }) +} + +export function EventArgumentInputSchema(): myzod.Type { + return myzod.object({ + name: myzod.string().min(5), + value: myzod.string().pattern(/^foo/) + }) +} -export const LayoutInputSchema: myzod.Type = myzod.object({ - dropdown: myzod.lazy(() => DropDownComponentInputSchema.optional().nullable()) -}); +export function EventInputSchema(): myzod.Type { + return myzod.object({ + arguments: myzod.array(myzod.lazy(() => EventArgumentInputSchema())), + options: myzod.array(EventOptionTypeSchema).optional().nullable() + }) +} -export const AttributeInputSchema: myzod.Type = myzod.object({ - key: myzod.string().optional().nullable(), - val: myzod.string().optional().nullable() -}); +export function GuestSchema(): myzod.Type { + return myzod.object({ + __typename: myzod.literal('Guest').optional(), + lastLoggedIn: definedNonNullAnySchema.optional().nullable() + }) +} -export const PageInputSchema: myzod.Type = myzod.object({ - attributes: myzod.array(myzod.lazy(() => AttributeInputSchema)).optional().nullable(), +export function HttpInputSchema(): myzod.Type { + return myzod.object({ + method: HttpMethodSchema.optional().nullable(), + url: definedNonNullAnySchema + }) +} + +export function LayoutInputSchema(): myzod.Type { + return myzod.object({ + dropdown: myzod.lazy(() => DropDownComponentInputSchema().optional().nullable()) + }) +} + +export function PageInputSchema(): myzod.Type { + return myzod.object({ + attributes: myzod.array(myzod.lazy(() => AttributeInputSchema())).optional().nullable(), date: definedNonNullAnySchema.optional().nullable(), height: myzod.number(), id: myzod.string(), - layout: myzod.lazy(() => LayoutInputSchema), + layout: myzod.lazy(() => LayoutInputSchema()), pageType: PageTypeSchema, postIDs: myzod.array(myzod.string()).optional().nullable(), show: myzod.boolean(), tags: myzod.array(myzod.string().nullable()).optional().nullable(), title: myzod.string(), width: myzod.number() -}); + }) +} -export const GuestSchema: myzod.Type = myzod.object({ - __typename: myzod.literal('Guest').optional(), - lastLoggedIn: definedNonNullAnySchema.optional().nullable() -}); - -export const AdminSchema: myzod.Type = myzod.object({ - __typename: myzod.literal('Admin').optional(), - lastModifiedAt: definedNonNullAnySchema.optional().nullable() -}); - -export const UserKindSchema = myzod.union([AdminSchema, GuestSchema]); - -export const UserSchema: myzod.Type = myzod.object({ +export function UserSchema(): myzod.Type { + return myzod.object({ __typename: myzod.literal('User').optional(), createdAt: definedNonNullAnySchema.optional().nullable(), email: myzod.string().optional().nullable(), id: myzod.string().optional().nullable(), - kind: UserKindSchema.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()]) +} diff --git a/example/yup/schemas.ts b/example/yup/schemas.ts index 2a38d5d6..9d6671d6 100644 --- a/example/yup/schemas.ts +++ b/example/yup/schemas.ts @@ -1,13 +1,13 @@ import * as yup from 'yup' -import { PageType, HttpMethod, HttpInput, EventOptionType, EventArgumentInput, EventInput, ComponentInput, DropDownComponentInput, LayoutInput, ButtonComponentType, AttributeInput, PageInput, Guest, Admin, UserKind, User } from '../types' +import { Admin, AttributeInput, ButtonComponentType, ComponentInput, DropDownComponentInput, EventArgumentInput, EventInput, EventOptionType, Guest, HttpInput, HttpMethod, LayoutInput, PageInput, PageType, User, UserKind } from '../types' -export const PageTypeSchema = yup.string().oneOf([PageType.BasicAuth, PageType.Lp, PageType.Restricted, PageType.Service]).defined(); - -export const HttpMethodSchema = yup.string().oneOf([HttpMethod.Get, HttpMethod.Post]).defined(); +export const ButtonComponentTypeSchema = yup.string().oneOf([ButtonComponentType.Button, ButtonComponentType.Submit]).defined(); export const EventOptionTypeSchema = yup.string().oneOf([EventOptionType.Reload, EventOptionType.Retry]).defined(); -export const ButtonComponentTypeSchema = yup.string().oneOf([ButtonComponentType.Button, ButtonComponentType.Submit]).defined(); +export const HttpMethodSchema = yup.string().oneOf([HttpMethod.Get, HttpMethod.Post]).defined(); + +export const PageTypeSchema = yup.string().oneOf([PageType.BasicAuth, PageType.Lp, PageType.Restricted, PageType.Service]).defined(); function union(...schemas: ReadonlyArray>): yup.MixedSchema { return yup.mixed().test({ @@ -15,76 +15,100 @@ function union(...schemas: ReadonlyArray>): yup.Mixe }).defined() } -export const HttpInputSchema: yup.ObjectSchema = yup.object({ - method: HttpMethodSchema.nullable().optional(), - url: yup.mixed().nonNullable() -}); +export function AdminSchema(): yup.ObjectSchema { + return yup.object({ + __typename: yup.string<'Admin'>().optional(), + lastModifiedAt: yup.mixed().nullable().optional() + }) +} + +export function AttributeInputSchema(): yup.ObjectSchema { + return yup.object({ + key: yup.string().defined().nullable().optional(), + val: yup.string().defined().nullable().optional() + }) +} + +export function ComponentInputSchema(): yup.ObjectSchema { + return yup.object({ + child: yup.lazy(() => ComponentInputSchema()).optional(), + childrens: yup.array(yup.lazy(() => ComponentInputSchema())).defined().nullable().optional(), + event: yup.lazy(() => EventInputSchema()).optional(), + name: yup.string().defined().nonNullable(), + type: ButtonComponentTypeSchema.nonNullable() + }) +} -export const EventArgumentInputSchema: yup.ObjectSchema = yup.object({ +export function DropDownComponentInputSchema(): yup.ObjectSchema { + return yup.object({ + dropdownComponent: yup.lazy(() => ComponentInputSchema()).optional(), + getEvent: yup.lazy(() => EventInputSchema().nonNullable()) + }) +} + +export function EventArgumentInputSchema(): yup.ObjectSchema { + return yup.object({ name: yup.string().defined().nonNullable().min(5), value: yup.string().defined().nonNullable().matches(/^foo/) -}); + }) +} -export const EventInputSchema: yup.ObjectSchema = yup.object({ - arguments: yup.array(yup.lazy(() => EventArgumentInputSchema.nonNullable())).defined(), +export function EventInputSchema(): yup.ObjectSchema { + return yup.object({ + arguments: yup.array(yup.lazy(() => EventArgumentInputSchema().nonNullable())).defined(), options: yup.array(EventOptionTypeSchema.nonNullable()).defined().nullable().optional() -}); - -export const ComponentInputSchema: yup.ObjectSchema = yup.object({ - child: yup.lazy(() => ComponentInputSchema).optional(), - childrens: yup.array(yup.lazy(() => ComponentInputSchema)).defined().nullable().optional(), - event: yup.lazy(() => EventInputSchema).optional(), - name: yup.string().defined().nonNullable(), - type: ButtonComponentTypeSchema.nonNullable() -}); + }) +} -export const DropDownComponentInputSchema: yup.ObjectSchema = yup.object({ - dropdownComponent: yup.lazy(() => ComponentInputSchema).optional(), - getEvent: yup.lazy(() => EventInputSchema.nonNullable()) -}); +export function GuestSchema(): yup.ObjectSchema { + return yup.object({ + __typename: yup.string<'Guest'>().optional(), + lastLoggedIn: yup.mixed().nullable().optional() + }) +} -export const LayoutInputSchema: yup.ObjectSchema = yup.object({ - dropdown: yup.lazy(() => DropDownComponentInputSchema).optional() -}); +export function HttpInputSchema(): yup.ObjectSchema { + return yup.object({ + method: HttpMethodSchema.nullable().optional(), + url: yup.mixed().nonNullable() + }) +} -export const AttributeInputSchema: yup.ObjectSchema = yup.object({ - key: yup.string().defined().nullable().optional(), - val: yup.string().defined().nullable().optional() -}); +export function LayoutInputSchema(): yup.ObjectSchema { + return yup.object({ + dropdown: yup.lazy(() => DropDownComponentInputSchema()).optional() + }) +} -export const PageInputSchema: yup.ObjectSchema = yup.object({ - attributes: yup.array(yup.lazy(() => AttributeInputSchema.nonNullable())).defined().nullable().optional(), +export function PageInputSchema(): yup.ObjectSchema { + return yup.object({ + attributes: yup.array(yup.lazy(() => AttributeInputSchema().nonNullable())).defined().nullable().optional(), date: yup.mixed().nullable().optional(), height: yup.number().defined().nonNullable(), id: yup.string().defined().nonNullable(), - layout: yup.lazy(() => LayoutInputSchema.nonNullable()), + layout: yup.lazy(() => LayoutInputSchema().nonNullable()), pageType: PageTypeSchema.nonNullable(), postIDs: yup.array(yup.string().defined().nonNullable()).defined().nullable().optional(), show: yup.boolean().defined().nonNullable(), tags: yup.array(yup.string().defined().nullable()).defined().nullable().optional(), title: yup.string().defined().nonNullable(), width: yup.number().defined().nonNullable() -}); - -export const GuestSchema: yup.ObjectSchema = yup.object({ - __typename: yup.string<'Guest'>().optional(), - lastLoggedIn: yup.mixed().nullable().optional() -}); - -export const AdminSchema: yup.ObjectSchema = yup.object({ - __typename: yup.string<'Admin'>().optional(), - lastModifiedAt: yup.mixed().nullable().optional() -}); - -export const UserKindSchema: yup.MixedSchema = union(AdminSchema, GuestSchema); + }) +} -export const UserSchema: yup.ObjectSchema = yup.object({ +export function UserSchema(): yup.ObjectSchema { + return yup.object({ __typename: yup.string<'User'>().optional(), createdAt: yup.mixed().nullable().optional(), email: yup.string().defined().nullable().optional(), id: yup.string().defined().nullable().optional(), - kind: UserKindSchema.nullable().optional(), + kind: UserKindSchema().nullable().optional(), name: yup.string().defined().nullable().optional(), password: yup.string().defined().nullable().optional(), updatedAt: yup.mixed().nullable().optional() -}); + }) +} + +export function UserKindSchema(): yup.MixedSchema { + return union(AdminSchema(), GuestSchema()) +} diff --git a/example/zod/schemas.ts b/example/zod/schemas.ts index 4f23a70c..3f03fb08 100644 --- a/example/zod/schemas.ts +++ b/example/zod/schemas.ts @@ -1,5 +1,5 @@ import { z } from 'zod' -import { PageType, HttpMethod, HttpInput, EventOptionType, EventArgumentInput, EventInput, ComponentInput, DropDownComponentInput, LayoutInput, ButtonComponentType, AttributeInput, PageInput, Guest, Admin, User } from '../types' +import { Admin, AttributeInput, ButtonComponentType, ComponentInput, DropDownComponentInput, EventArgumentInput, EventInput, EventOptionType, Guest, HttpInput, HttpMethod, LayoutInput, PageInput, PageType, User } from '../types' type Properties = Required<{ [K in keyof T]: z.ZodType; @@ -11,84 +11,108 @@ export const isDefinedNonNullAny = (v: any): v is definedNonNullAny => v !== und export const definedNonNullAnySchema = z.any().refine((v) => isDefinedNonNullAny(v)); -export const PageTypeSchema = z.nativeEnum(PageType); - -export const HttpMethodSchema = z.nativeEnum(HttpMethod); +export const ButtonComponentTypeSchema = z.nativeEnum(ButtonComponentType); export const EventOptionTypeSchema = z.nativeEnum(EventOptionType); -export const ButtonComponentTypeSchema = z.nativeEnum(ButtonComponentType); - -export const HttpInputSchema: z.ZodObject> = z.object({ - method: HttpMethodSchema.nullish(), - url: definedNonNullAnySchema -}); +export const HttpMethodSchema = z.nativeEnum(HttpMethod); -export const EventArgumentInputSchema: z.ZodObject> = z.object({ - name: z.string().min(5), - value: z.string().regex(/^foo/, "message") -}); +export const PageTypeSchema = z.nativeEnum(PageType); -export const EventInputSchema: z.ZodObject> = z.object({ - arguments: z.array(z.lazy(() => EventArgumentInputSchema)), - options: z.array(EventOptionTypeSchema).nullish() -}); +export function AdminSchema(): z.ZodObject> { + return z.object({ + __typename: z.literal('Admin').optional(), + lastModifiedAt: definedNonNullAnySchema.nullish() + }) +} -export const ComponentInputSchema: z.ZodObject> = z.object({ - child: z.lazy(() => ComponentInputSchema.nullish()), - childrens: z.array(z.lazy(() => ComponentInputSchema.nullable())).nullish(), - event: z.lazy(() => EventInputSchema.nullish()), +export function AttributeInputSchema(): z.ZodObject> { + return z.object({ + key: z.string().nullish(), + val: z.string().nullish() + }) +} + +export function ComponentInputSchema(): z.ZodObject> { + return z.object({ + child: z.lazy(() => ComponentInputSchema().nullish()), + childrens: z.array(z.lazy(() => ComponentInputSchema().nullable())).nullish(), + event: z.lazy(() => EventInputSchema().nullish()), name: z.string(), type: ButtonComponentTypeSchema -}); - -export const DropDownComponentInputSchema: z.ZodObject> = z.object({ - dropdownComponent: z.lazy(() => ComponentInputSchema.nullish()), - getEvent: z.lazy(() => EventInputSchema) -}); + }) +} + +export function DropDownComponentInputSchema(): z.ZodObject> { + return z.object({ + dropdownComponent: z.lazy(() => ComponentInputSchema().nullish()), + getEvent: z.lazy(() => EventInputSchema()) + }) +} + +export function EventArgumentInputSchema(): z.ZodObject> { + return z.object({ + name: z.string().min(5), + value: z.string().regex(/^foo/, "message") + }) +} -export const LayoutInputSchema: z.ZodObject> = z.object({ - dropdown: z.lazy(() => DropDownComponentInputSchema.nullish()) -}); +export function EventInputSchema(): z.ZodObject> { + return z.object({ + arguments: z.array(z.lazy(() => EventArgumentInputSchema())), + options: z.array(EventOptionTypeSchema).nullish() + }) +} -export const AttributeInputSchema: z.ZodObject> = z.object({ - key: z.string().nullish(), - val: z.string().nullish() -}); +export function GuestSchema(): z.ZodObject> { + return z.object({ + __typename: z.literal('Guest').optional(), + lastLoggedIn: definedNonNullAnySchema.nullish() + }) +} -export const PageInputSchema: z.ZodObject> = z.object({ - attributes: z.array(z.lazy(() => AttributeInputSchema)).nullish(), +export function HttpInputSchema(): z.ZodObject> { + return z.object({ + method: HttpMethodSchema.nullish(), + url: definedNonNullAnySchema + }) +} + +export function LayoutInputSchema(): z.ZodObject> { + return z.object({ + dropdown: z.lazy(() => DropDownComponentInputSchema().nullish()) + }) +} + +export function PageInputSchema(): z.ZodObject> { + return z.object({ + attributes: z.array(z.lazy(() => AttributeInputSchema())).nullish(), date: definedNonNullAnySchema.nullish(), height: z.number(), id: z.string(), - layout: z.lazy(() => LayoutInputSchema), + layout: z.lazy(() => LayoutInputSchema()), pageType: PageTypeSchema, postIDs: z.array(z.string()).nullish(), show: z.boolean(), tags: z.array(z.string().nullable()).nullish(), title: z.string(), width: z.number() -}); + }) +} -export const GuestSchema: z.ZodObject> = z.object({ - __typename: z.literal('Guest').optional(), - lastLoggedIn: definedNonNullAnySchema.nullish() -}); - -export const AdminSchema: z.ZodObject> = z.object({ - __typename: z.literal('Admin').optional(), - lastModifiedAt: definedNonNullAnySchema.nullish() -}); - -export const UserKindSchema = z.union([AdminSchema, GuestSchema]); - -export const UserSchema: z.ZodObject> = z.object({ +export function UserSchema(): z.ZodObject> { + return z.object({ __typename: z.literal('User').optional(), createdAt: definedNonNullAnySchema.nullish(), email: z.string().nullish(), id: z.string().nullish(), - kind: UserKindSchema.nullish(), + kind: UserKindSchema().nullish(), name: z.string().nullish(), password: z.string().nullish(), updatedAt: definedNonNullAnySchema.nullish() -}); + }) +} + +export function UserKindSchema() { + return z.union([AdminSchema(), GuestSchema()]) +} diff --git a/src/config.ts b/src/config.ts index 3fd32e7c..ecaecd96 100644 --- a/src/config.ts +++ b/src/config.ts @@ -194,6 +194,22 @@ export interface ValidationSchemaPluginConfig extends TypeScriptPluginConfig { * ``` */ withObjectType?: boolean; + /** + * @description Specify validation schema export type. + * @default function + * + * @exampleMarkdown + * ```yml + * generates: + * path/to/file.ts: + * plugins: + * - typescript + * - graphql-codegen-validation-schema + * config: + * validationSchemaExportType: const + * ``` + */ + validationSchemaExportType?: ValidationSchemaExportType; /** * @description Generates validation schema with more API based on directive schema. * @exampleMarkdown @@ -235,20 +251,4 @@ export interface ValidationSchemaPluginConfig extends TypeScriptPluginConfig { * ``` */ directives?: DirectiveConfig; - /** - * @description Specify validation schema export type - * @default function - * - * @exampleMarkdown - * ```yml - * generates: - * path/to/file.ts: - * plugins: - * - typescript - * - graphql-codegen-validation-schema - * config: - * validationSchemaExportType: const - * ``` - */ - validationSchemaExportType?: ValidationSchemaExportType; }