@use-pico/graphql-codegen-zod
v4.0.65
Published
Simple Zod generator for graphql schemas.
Maintainers
Readme
@use-pico/graphql-codegen-zod
A powerful GraphQL Code Generator plugin that automatically generates Zod schemas from your GraphQL schema and operations. This plugin provides type-safe validation for GraphQL data with full TypeScript integration.
Features
🎯 Complete GraphQL Type Support
- Object Types - Convert GraphQL objects to Zod object schemas
- Input Types - Generate validation schemas for GraphQL input types
- Enums - Convert GraphQL enums to Zod enum schemas with proper values
- Unions - Handle GraphQL union types with Zod union schemas
- Interfaces - Support for GraphQL interface types
- Scalars - Built-in support for common scalars (String, Int, Float, Boolean, ID, Date, DateTime, JSON)
- Custom Scalars - Configurable mapping for custom scalar types
🔄 Fragment Support
- Fragment Definitions - Generate Zod schemas from GraphQL fragments
- Fragment Spreads - Handle fragment spreads within operations
- Fragment Dependencies - Automatic dependency validation and error detection
- Inline Fragments - Support for inline fragment definitions
📝 Operation Support
- Query Variables - Generate validation schemas for operation variables
- Mutation Variables - Validate mutation input parameters
- Subscription Variables - Support for subscription variable validation
🛡️ Advanced Features
- Circular Reference Detection - Prevents infinite loops with smart circular reference handling
- Recursive Type Handling - Uses getter functions for recursive types to avoid circular dependencies
- Nullish Field Support - Proper handling of nullable and optional fields
- Description Preservation - Maintains GraphQL field descriptions in generated schemas
- Error Handling - Comprehensive error handling with meaningful error messages
- Type Deduplication - Prevents duplicate field definitions in generated schemas
🔧 TypeScript Integration
- Full TypeScript Support - Generated schemas include proper TypeScript types
- Type Inference - Use
z.infer<typeof SchemaName>for type extraction - Namespace Exports - Organized exports with TypeScript namespaces
Installation
npm install @use-pico/graphql-codegen-zod
# or
yarn add @use-pico/graphql-codegen-zod
# or
bun add @use-pico/graphql-codegen-zodConfiguration
Add the plugin to your codegen.yml or codegen.ts configuration:
# codegen.yml
schema: schema.graphql
documents: 'src/**/*.graphql'
generates:
src/generated/zod.ts:
plugins:
- '@use-pico/graphql-codegen-zod'
config:
scalars:
CustomScalar: 'z.custom()'
DateTime: 'z.date()'Or with TypeScript configuration:
// codegen.ts
import { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
schema: 'schema.graphql',
documents: ['src/**/*.graphql'],
generates: {
'src/generated/zod.ts': {
plugins: ['@use-pico/graphql-codegen-zod'],
config: {
scalars: {
CustomScalar: 'z.custom()',
DateTime: 'z.date()',
},
},
},
},
};
export default config;Configuration Options
scalars
Map custom GraphQL scalar types to Zod schema definitions.
interface Config {
scalars?: Record<string, string>;
imports?: string[];
}Example:
config:
scalars:
DateTime: 'z.date()'
JSON: 'z.any()'
CustomScalar: 'z.string().transform(val => customTransform(val))'imports
Add custom import statements to the generated file. This is useful when using custom scalar validators from external libraries.
Example:
config:
scalars:
AWSDateTime: 'zInstant'
imports:
- 'import { zInstant } from "temporal-zod";'With this configuration, the generated file will include:
/* eslint-disable no-use-before-define */
import { z } from "zod";
import { zInstant } from "temporal-zod";
// ... your generated schemas using zInstantGenerated Output
The plugin generates TypeScript files with Zod schemas and type definitions:
import { z } from "zod";
// Object Type Schema
export const UserSchema = z.object({
id: z.string(),
name: z.string().nullish(),
email: z.string(),
});
export type UserSchema = typeof UserSchema;
export namespace UserSchema {
export type Type = z.infer<UserSchema>;
}
// Fragment Schema
export const UserFragmentSchema = z.object({
id: z.string(),
name: z.string().nullish(),
profile: z.object({
avatar: z.string().nullish(),
bio: z.string().nullish(),
}),
});
export type UserFragmentSchema = typeof UserFragmentSchema;
export namespace UserFragmentSchema {
export type Type = z.infer<UserFragmentSchema>;
}
// Operation Variables Schema
export const GetUserVariablesSchema = z.object({
id: z.string(),
includeProfile: z.boolean().nullish(),
});
export type GetUserVariablesSchema = typeof GetUserVariablesSchema;
export namespace GetUserVariablesSchema {
export type Type = z.infer<GetUserVariablesSchema>;
}
// Enum Schema
export const UserRoleSchema = z.enum(["ADMIN", "USER", "MODERATOR"]);
export type UserRoleSchema = typeof UserRoleSchema;
export namespace UserRoleSchema {
export type Type = z.infer<UserRoleSchema>;
}Usage Examples
Basic Schema Validation
import { UserSchema } from './generated/zod';
// Validate user data
const userData = {
id: "123",
name: "John Doe",
email: "[email protected]"
};
const validatedUser = UserSchema.parse(userData);
// TypeScript knows this is UserSchema.TypeFragment Validation
import { UserFragmentSchema } from './generated/zod';
// Validate data that matches a fragment
const userWithProfile = {
id: "123",
name: "John Doe",
profile: {
avatar: "https://example.com/avatar.jpg",
bio: "Software developer"
}
};
const validatedUserFragment = UserFragmentSchema.parse(userWithProfile);Operation Variables Validation
import { GetUserVariablesSchema } from './generated/zod';
// Validate GraphQL operation variables
const variables = {
id: "123",
includeProfile: true
};
const validatedVariables = GetUserVariablesSchema.parse(variables);Custom Scalar Handling
// With custom scalar configuration
const config = {
scalars: {
DateTime: 'z.date()',
JSON: 'z.any()',
CustomScalar: 'z.string().transform(val => customTransform(val))'
}
};
// Generated schema will use your custom definitions
export const EventSchema = z.object({
id: z.string(),
createdAt: z.date(), // Custom DateTime scalar
metadata: z.any(), // Custom JSON scalar
});Advanced Features
Recursive Type Handling
The plugin automatically detects recursive types and uses getter functions to prevent circular dependencies:
// For recursive types like nested comments
export const CommentSchema = z.object({
id: z.string(),
content: z.string(),
get replies() {
return z.array(CommentSchema).nullish();
}
});Fragment Dependency Validation
The plugin validates fragment dependencies and provides helpful error messages:
// If a fragment references an undefined fragment, you'll get:
/** Fragment dependency warnings: */
/** Fragment 'UserWithProfile' depends on undefined fragment 'ProfileFragment' */Error Handling
Comprehensive error handling with meaningful messages:
// For processing errors:
/** Error processing type User: Field 'invalidField' not found on type User */
/** Circular reference detected for type: RecursiveType */TypeScript Integration
The generated schemas provide full TypeScript support:
import { UserSchema } from './generated/zod';
// Extract types
type User = UserSchema.Type;
// Use in function signatures
function processUser(user: User) {
// TypeScript knows the exact shape of user
}
// Validate and get typed result
const user: User = UserSchema.parse(rawData);Best Practices
- Use Fragment Schemas for reusable data shapes
- Validate Variables before sending GraphQL operations
- Handle Nullish Fields appropriately in your application logic
- Custom Scalars should be properly typed and validated
- Error Handling - Always handle validation errors in production
Contributing
This plugin is part of the use-pico ecosystem. Contributions are welcome!
License
MIT License - see the LICENSE file for details.
