Library / SDK
omar-dulaimi/prisma-zod-generator avatar
omar-dulaimi/prisma-zod-generator

Prisma Zod Generator: Zod schemas generated from your Prisma schema

Prisma 2+ generator to emit Zod schemas from your Prisma schema

831 stars77 forksTypeScriptMIT

At a glance

What is it?
A Prisma generator that emits Zod schemas alongside the generated client, so validation and types come from one source. It reads existing annotations, but it does not replace other generators.
Who is it for?
Prisma Zod Generator suits a TypeScript team already on Prisma that wants request validation tied to the same schema that defines the database, and that wants validators declared next to the fields they apply to. It does not suit a project that needs the typed JSON fields another generator produces, because the README is explicit that this tool adds runtime validation only and that the other generator must stay installed.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 63 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

One schema file, two consumers

The problem this solves is drift. A Prisma schema defines the database, the generated Prisma Client defines the types, and a hand written Zod schema defines what a request body may contain, so three descriptions of the same model have to be kept in step by hand. This generator removes the third copy by running as part of prisma generate, so the validation schemas are regenerated from the same source of truth as the client. The README describes it as a Prisma 2 and later generator that emits Zod schemas from your Prisma schema, and the supported versions are specific: Node.js 20.19.0 or newer with 22.x recommended, Prisma 7.x, Zod from 3.25.0 up to but not including 5, and TypeScript 5.4 or newer. Both Zod v3 and v4 output are emitted, so a project can move between the two major versions without regenerating by hand.

Adding the generator block and running prisma generate

Installation is two npm commands, and the README insists on a local install:

bash
npm install --save-dev prisma-zod-generator
npm install zod

The reason is mechanical rather than stylistic. Prisma resolves the generator executable from node_modules/.bin, so a global install is not found and provider = "prisma-zod-generator" fails. Zod is a peer dependency in the range 3.25.0 to below 5 because the generated files import it at runtime. The generator is then declared in schema.prisma alongside the usual client generator:

prisma
generator client {
  provider = "prisma-client"
  output   = "../src/generated/prisma"
}

generator zod {
  provider = "prisma-zod-generator"
  // output defaults to <schema dir>/generated
  // config = "./zod-generator.config.json"
}

Running npx prisma generate then produces the schemas. Without any configuration you get one file per CRUD operation plus the input object and enum schemas they reference, laid out under a generated/schemas directory with subdirectories for objects, enums, results and variants, and an index.ts barrel re-export. A helpers directory appears next to schemas when the Prisma schema contains Json or Decimal fields, and models appears once pureModels is enabled.

Every operation exports a typed and an untyped schema

The detail that matters most in the generated output is that each operation file exports its schema twice. The first export is annotated as z.ZodType<Prisma.<Model><Operation>Args>, so the parsed result can be handed straight to the Prisma Client. The second export is the same object without the annotation, kept for the cases where you want to call .extend(), .partial() or .omit() on it. A typical route handler therefore looks like this:

ts
import { UserFindManySchema } from './prisma/generated/schemas/findManyUser.schema';

const args = UserFindManySchema.parse(req.query);
const users = await prisma.user.findMany(args);

If you would rather have a plain schema per model with no CRUD wrappers and no Prisma types, pureModels: true emits those under a models directory, with an inferred type exported alongside:

ts
export const UserSchema = z.object({
  id: z.number().int(),
  email: z.string(),
  name: z.string().nullish(),
});

export type UserType = z.infer<typeof UserSchema>;

Validators are declared next to the field they apply to

Where the project goes beyond plain type mirroring is the annotation mechanism. A triple-slash comment above a field in the Prisma schema is compiled into the generated field schema, so a validator lives next to the column it constrains rather than in a separate file:

prisma
model User {
  id    Int     @id @default(autoincrement())
  /// @zod.email()
  email String  @unique
  /// @zod.min(2).max(80)
  name  String?
}

The documentation covers the supported validators, custom imports and metadata annotations. The trade-off is a real one: the Prisma schema stops being a pure database description and starts carrying application rules, so a team that prefers to own its validation schemas in TypeScript may find that separation uncomfortable. The generator's answer to that is pureModels, and the emitNamespace option, which the README describes as making the Zod schema the single authored definition with the PrismaJson type derived from it via z.infer so the two cannot drift.

Interop with prisma-json-types-generator, but not a replacement for it

A migration question comes up for anyone already using prisma-json-types-generator, and the README answers it in unusually blunt terms. The generator can read that project's annotations directly, so the /// [TypeName] and /// ![<ts type>] comments already in a schema start validating at runtime with no annotation or schema changes. But the section is headed as additive rather than a migration, and it says to keep prisma-json-types-generator installed. The reason is that the two tools cover different halves of the problem. The JSON types generator types the generated Prisma Client so prisma.workflow.findFirst() returns a typed nodes value, and this generator cannot do that and does not try. What it adds is runtime validation, including on String, Int and Float literal unions that neither library checked before. Fields with no annotation are left untouched, and with no typedJson block in the configuration the output is unchanged.

Configuration precedence and the split between the two licences

Options can be set in the generator block or in a JSON file next to schema.prisma. The file name zod-generator.config.json is discovered automatically, and any other path can be passed with config, resolved relative to the schema file:

json
{
  "$schema": "../node_modules/prisma-zod-generator/lib/config/schema.json",
  "mode": "full",
  "pureModels": true,
  "useMultipleFiles": true
}

The $schema line gives autocomplete, hover documentation and validation in a JSON aware editor. The options listed in the README include mode with full, minimal and custom values, output, useMultipleFiles and singleFileName, pureModels, variants, naming, optionalFieldBehavior, dateTimeStrategy, strictMode, emit, zodImportTarget and zodImportPath. Setting useMultipleFiles to false collapses the output into a single schemas.ts. The repository root also carries a second licence file, LICENSE-PRO.md, next to LICENSE, and the package registers a pzg-pro binary beside prisma-zod-generator, so the project is published in two editions with the paid one documented on its own pricing page.

Editorial conclusion

Prisma Zod Generator suits a TypeScript team already on Prisma that wants request validation tied to the same schema that defines the database, and that wants validators declared next to the fields they apply to. It does not suit a project that needs the typed JSON fields another generator produces, because the README is explicit that this tool adds runtime validation only and that the other generator must stay installed. Before adopting, pin Prisma to 7.x and Zod to 3.25 or later, and check whether your validation should live in the Prisma schema or in the Zod schema you control directly.

Frequently asked questions

How do I install prisma-zod-generator?

Run npm install --save-dev prisma-zod-generator and npm install zod. The README says to install it locally rather than globally, because Prisma resolves the generator executable from node_modules/.bin.

How do I add a custom Zod validator to a Prisma field?

Use a triple-slash comment above the field, for example /// @zod.email() on an email field or /// @zod.min(2).max(80) on a name field. The annotations are compiled into the generated field schemas.

Can prisma-zod-generator replace prisma-json-types-generator?

No. The README describes the support as additive and not a migration, and says to keep prisma-json-types-generator installed, because that project types the generated Prisma Client while this one adds runtime validation.

What are the version requirements for prisma-zod-generator?

Node.js 20.19.0 or newer, Prisma 7.x, Zod from 3.25.0 up to but not including 5, and TypeScript 5.4 or newer.

How do I get plain model schemas without Prisma types?

Set pureModels to true in the generator configuration. The generator then emits one plain schema per model under a models directory, with an inferred type derived from it.

Official sources

  1. License: MIT
  2. omar-dulaimi/prisma-zod-generator on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/omar-dulaimi-prisma-zod-generator.svg)](https://hysenlabs.com/projects/omar-dulaimi-prisma-zod-generator)

Was this useful?