@davars/graphql-codegen-zod
v0.4.1
Published
GraphQL Code Generator plugin that generates Zod v4 validation schemas with transform support
Downloads
53
Readme
@davars/graphql-codegen-zod
GraphQL Code Generator plugin that generates Zod v4 validation schemas from GraphQL types, with support for custom transforms.
Derived from graphql-codegen-typescript-validation-schema by Code-Hex (MIT licensed). Stripped to Zod v4 only, with added transform support for custom type constructors.
Installation
pnpm add -D @davars/graphql-codegen-zodUsage
# codegen.yml
generates:
path/to/schemas.ts:
plugins:
- @davars/graphql-codegen-zod
config:
schema: zodv4
withObjectType: true
importFrom: ./graphql-operations
scalarSchemas:
UUID: z.string().uuid()
DateTime: z.coerce.date()Transforms
Transforms let you convert plain parsed objects into custom class instances using Zod's .transform().
1. Define a transform function alongside your model
// models/DateRange.ts
export class DateRange {
constructor(readonly start: Date, readonly end: Date) {}
}
export function transformDateRange(raw: { start?: Date | null; end?: Date | null }): DateRange | null {
if (raw.start == null || raw.end == null) return null
return new DateRange(raw.start, raw.end)
}2. Create a transforms config
// transforms.config.ts
import type { TransformConfig } from '@davars/graphql-codegen-zod/config'
import { transformDateRange } from './models/DateRange'
const config: TransformConfig = {
DateRange: transformDateRange,
}
export default config3. Reference in codegen.yml
config:
transforms: ./path/to/transforms.config.tsThe generated schema will include:
import { transformDateRange } from './models/DateRange'
export function DateRangeSchema() {
return z.object({
__typename: z.literal('DateRange').optional(),
start: z.coerce.date().nullish(),
end: z.coerce.date().nullish(),
}).transform(transformDateRange)
}Client wrapper generation
You can also generate namespace-scoped query/mutation wrappers by setting config.client on an output target.
This mode:
- generates wrapper exports for named
queryandmutationoperations in matching documents - parses whole-operation payloads with operation-level schemas
- emits TanStack adapters (
queryOptions,mutationOptions) - uses a DI runtime (
configureGraphqlClientRuntime) so no transport/error import paths are required
Example
generates:
frontend/src/lib/api/client/statements.ts:
plugins:
- @davars/graphql-codegen-zod
config:
schema: zodv4
importFrom: ../graphql-operations
withObjectType: true
client:
namespace: statements
includeGlobs:
- statements/graphql/**/*.graphqlClient config
interface ClientNamespaceConfig {
namespace: string
includeGlobs: string[]
}Each generated client module exports a DI contract:
type ExecuteOperation = (
operation: string,
variables: Record<string, unknown> | undefined,
context?: { signal?: AbortSignal },
) => Promise<unknown>
type GraphqlClientRuntime = {
executeOperation: ExecuteOperation
ApiError: {
new (result: { __typename: string; message?: string; field?: string; entity?: string }): Error
isErrorResult(result: { __typename: string }): boolean
}
}
configureGraphqlClientRuntime(runtime: GraphqlClientRuntime): voidApp bootstrap example:
import { configureGraphqlClientRuntime } from '@/lib/api/client/statements'
import { executeOperation } from '@/lib/api/runtime/executeOperation'
import { ApiError } from '@/lib/api/errors'
configureGraphqlClientRuntime({ executeOperation, ApiError })Notes:
importFromis required in client mode (used for operation result type imports).validationSchemaExportType: 'const'is not supported in client mode.- Subscriptions are not supported in client mode.
- All operations must be named in client mode.
License
MIT
