A Prisma generator that automatically generates Zod schemas from your Prisma models.
Note
This package is ESM only.
Install it with your preferred package manager:
npm i -D @cvsa/prisma-zod
yarn add -D @cvsa/prisma-zod
pnpm i -D @cvsa/prisma-zod
bun i -D @cvsa/prisma-zod
deno add -D npm:@cvsa/prisma-zodAssume your project structure looks like this:
awesome-project/
├── prisma/
│ ├── migrations/
│ └── schema.prisma
├── prisma.config.ts
└── package.json
Add the generator to your schema.prisma:
generator zod {
provider = "prisma-zod"
output = "./zod"
}Then run prisma generate and import the schemas:
import { LogSchema } from "root/prisma/zod";If you have prisma-json-types-generator installed and have already defined types for your Json fields, you can enhance runtime validation and get more precise Zod schemas by providing your own Zod schemas.
To do this, use the extendSchema option in the generator config to specify where your schemas are defined.
schema.prisma:
// ...
generator json {
provider = "prisma-json-types-generator"
}
generator zod {
provider = "prisma-zod"
output = "./zod"
// This file must be placed next to `schema.prisma`
extendSchema = "zod-schema.ts"
}
model Log {
id Int @id
/// [LogMetaType]
meta Json
}Create zod-schema.ts next to your schema.prisma:
import z from "zod";
// Use the same name as specified in the AST comment.
// Since the generated Zod schemas will import this schema directly,
// you must export it explicitly.
export const LogMetaType = z.object({
timestamp: z.number(),
host: z.string(),
});In types.ts:
import type z from "zod";
import type { LogMetaType } from "./zod-schema";
declare global {
namespace PrismaJson {
type LogMetaType = z.infer<typeof LogMetaType>;
}
}Now Log.meta will be strongly typed as { timestamp: number; host: string }, and your generated schema will include the precise Zod definition:
// typeof LogSchema
z.ZodObject<{
id: z.ZodNumber;
meta: z.ZodObject<{
timestamp: z.ZodNumber;
host: z.ZodString;
}, z.core.$strip>;
}, z.core.$strip>By default, Prisma client generator will produce Date type for DateTime field, and bigint type for BigInt field.
However, these fields can't be serialized to JSON, so many users have introduced various workarounds to solve this (see prisma/prisma issue #5522).
If you have converted these fields to other types, you'll found a mismatch between your converted Prisma type and the Zod schemas generated by this library.
To avoid this, you can use dateSchema and bigintSchema options.
Controls the Zod schema generated for DateTime fields.
generator zod {
provider = "prisma-zod"
output = "./zod"
dateSchema = "string" // "default" | "string" | "number"
}| Option | Zod Schema | When to Use |
|---|---|---|
"default" |
z.coerce.date() |
Standard choice, coerces input to Date |
"string" |
z.string() |
When your API handles dates as ISO strings |
"number" |
z.number() |
When you convert dates to Unix timestamps |
Controls the Zod schema generated for BigInt fields.
generator zod {
provider = "prisma-zod"
output = "./zod"
bigintSchema = "string" // "default" | "number" | "union" | "string"
}| Option | Zod Schema | When to Use |
|---|---|---|
"default" |
z.bigint() |
Standard choice |
"string" |
z.string() |
When serializing BigInt to JSON |
"number" |
z.number() |
When BigInt values fit in safe integer range |
"union" |
z.union([z.bigint(), z.number()]) |
When you need both |
You can override the global dateSchema / bigintSchema setting for individual fields using AST comments in your Prisma schema:
model Event {
id Int @id
/// [string]
createdAt DateTime // Uses z.string() regardless of dateSchema
/// [number]
timestamp BigInt // Uses z.number() regardless of bigintSchema
}Supported overrides:
- DateTime:
/// [default]/// [string]/// [number] - BigInt:
/// [default]/// [string]/// [number]/// [union]
See CONTRIBUTING for development setup and guidelines.
Found a type mismatch between prisma-client and the generated Zod schema? Please open an issue.