@softonus/graphql-codegen-zod
v1.1.0
Published
GraphQL Code Generator plugin that generates Zod v4 validation schemas with full type inference. Modern replacement for typescript-validation-schema
Maintainers
Readme
@softonus/graphql-codegen-zod
Generate Zod v4 validation schemas from your GraphQL Input types automatically
What is this?
@softonus/graphql-codegen-zod is a GraphQL Code Generator plugin that automatically generates Zod v4 validation schemas from your GraphQL Input types.
It's the modern replacement for typescript-validation-schema which has compatibility issues with Zod v4.
Why do I need this?
- Generate validation schemas directly from your GraphQL schema
- No manual synchronization between GraphQL types and Zod schemas
- Full type inference with Zod v4
- Works perfectly with React Hook Form + Zod Resolver
Installation
# npm
npm install @softonus/graphql-codegen-zod
# yarn
yarn add @softonus/graphql-codegen-zod
# pnpm
pnpm add @softonus/graphql-codegen-zod
# bun
bun add @softonus/graphql-codegen-zodQuick Start
# codegen.ts
import { CodegenConfig } from '@graphql-codegen/cli'
import { readdirSync } from 'fs'
const scalars = {
ID: 'string', String: 'string', Int: 'number', Boolean: 'boolean',
Float: 'number', JSON: '{ [key: string]: any }', Upload: 'File',
DateTime: 'string', Email: 'string', PhoneNumber: 'string'
}
const scalarSchemas = {
ID: 'z.string().min(1)', String: 'z.string().min(1)', Int: 'z.number().int()',
Boolean: 'z.boolean()', Float: 'z.number()', JSON: 'z.record(z.string(), z.any())',
Upload: 'z.instanceof(File)', DateTime: 'z.string()', Email: 'z.string().email()',
PhoneNumber: 'z.string().min(8)'
}
const modules = readdirSync('gql', { withFileTypes: true })
.filter(d => d.isDirectory())
.map(d => d.name)
const config: CodegenConfig = {
schema: 'http://localhost:4000/graphql',
documents: 'gql/**/*.gql',
generates: modules.reduce((acc, module) => ({
...acc,
[`gql/${module}/graphql.ts`]: {
schema: 'http://localhost:4000/graphql',
documents: `gql/${module}/**/*.gql`,
plugins: ['typescript', 'typescript-operations', 'typed-document-node'],
config: { scalars, useTypeImports: true }
},
[`gql/${module}/zod.ts`]: {
schema: 'http://localhost:4000/graphql',
documents: `gql/${module}/**/*.gql`,
plugins: ['@softonus/graphql-codegen-zod'],
config: { scalarSchemas }
}
}), {})
}
export default configWhat it generates
Given a GraphQL schema with Input types:
input CreateUserInput {
"""The user's full name"""
name: String!
"""Valid email address"""
email: String!
age: Int
status: UserStatus!
}
enum UserStatus {
ACTIVE
INACTIVE
SUSPENDED
}It generates gql/auth/zod.ts (grouped by module):
/* eslint-disable */
/**
* @softonus/graphql-codegen-zod
* Generated by graphql-codegen
*/
import { z } from 'zod'
// ============ AUTH INPUTS ============
export function CreateUserInputSchema() {
return z.object({
name: z.string().min(1).describe("The user's full name"),
email: z.string().email().describe("Valid email address"),
age: z.number().int().optional(),
status: z.enum(["ACTIVE", "INACTIVE", "SUSPENDED"])
})
}Usage with React Hook Form
import { useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import { CreateUserInputSchema } from '@/gql/auth/zod'
function CreateUserForm() {
const { register, handleSubmit } = useForm({
resolver: zodResolver(CreateUserInputSchema())
})
// Form is automatically validated against GraphQL schema types! ✓
}Comparison
| Feature | typescript-validation-schema | @softonus/graphql-codegen-zod |
|---------|------------------------------|---------------------|
| Zod v4 support | ❌ Partial | ✅ Full |
| Type inference | ⚠️ Limited | ✅ Full |
| Per-module output | ❌ No | ✅ Yes |
| Custom scalars | ⚠️ Manual | ✅ Automatic |
| Schema grouping | ❌ Flat | ✅ By module |
| Enum support | ❌ No | ✅ Yes |
| Field descriptions | ❌ No | ✅ Yes (.describe()) |
| Discriminated unions | ❌ No | ✅ Yes |
| Field refinements | ❌ No | ✅ Yes |
Configuration Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| importFrom | string | '@/gql/graphql' | Import types from path |
| groupByModule | boolean | true | Group schemas by folder |
| scalarSchemas | Record<string, string> | See below | Custom scalar mappings |
| module | string | undefined | Only generate schemas for this specific module |
| fieldRefinements | Record<string, Record<string, string>> | {} | Field-level refinement chains |
| generateObjectTypes | boolean | false | Also generate output/object type schemas |
Default Scalar Schemas
{
ID: 'z.string().min(1)',
String: 'z.string()',
Int: 'z.number().int()',
Boolean: 'z.boolean()',
Float: 'z.number()',
DateTime: 'z.string()',
Email: 'z.string().email()',
PhoneNumber: 'z.string().min(8)',
JSON: 'z.record(z.string(), z.any())',
Upload: 'z.instanceof(File)'
}FAQ
Q: Can I use this with Zod v3?
A: This plugin is designed for Zod v4. For Zod v3, use typescript-validation-schema.
Q: How is the module grouping determined?
A: Based on Input type naming convention. For example: CreateUserInput → auth module, CreatePostInput → posts module.
Q: How do I customize scalar mappings?
A: Pass scalarSchemas in the config:
config:
scalarSchemas:
DateTime: 'z.string().datetime()'Q: Can I generate schemas for all Input types or just specific ones? A: All Input types in your GraphQL schema are automatically converted to Zod schemas.
Q: Does it extract default values from the schema?
A: Yes. Fields with = default in the schema get .default(value) on the Zod schema.
Q: How do I add custom validation to specific fields?
A: Use fieldRefinements in your config:
config:
fieldRefinements:
SignInInput:
email: '.refine(v => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v), { message: "Invalid email" })'Q: Does it support GraphQL enums?
A: Yes! Enum types are automatically converted to z.enum([...]) with their values.
Q: Can I generate schemas for output types (not just inputs)?
A: Yes! Set generateObjectTypes: true in your config to also generate schemas for output/object types and unions (as z.discriminatedUnion). Field descriptions are automatically carried over as .describe().
Example Output Structure
gql/
├── auth/
│ ├── graphql.ts # GraphQL types
│ └── zod.ts # SignInInputSchema, SignUpInputSchema, etc.
├── posts/
│ ├── graphql.ts
│ └── zod.ts # CreatePostInputSchema, etc.
└── memorial/
├── graphql.ts
└── zod.ts # CreateMemorialInputSchema, etc.License
MIT © Ebo
