zod-prisma-types

repository·master·Indexed 21 days ago

https://github.com/chrishoermann/zod-prisma-types

A Prisma generator that automatically produces Zod schemas from Prisma models, including enums, inputs, and filters. It supports embedding custom Zod validation logic and constraints directly into Prisma schema comments. Compatible with Prisma 4.x - 6.x and Zod 3.x - 4.x.

Tokens
7.7K
Snippets
29
Records
37
Agent score
75%

What's inside zod-prisma-types

  1. What is zod-prisma-types?

    master

    zod-prisma-types is a Prisma generator that automatically creates Zod schemas from your Prisma models. It generates schemas for models, enums, input types, argument types, filters, and more.

    A key feature is the ability to write advanced Zod validators directly within your Prisma schema using rich comments.

  2. Use default validators or opt-out per field

    master

    The generator automatically adds Zod validators based on Prisma field attributes (e.g., cuid(), uuid(), int()).

    Global Control: Use useDefaultValidators = false in the generator config to disable this globally.

    Per-field Control: You can opt-out of a default validator for a specific field using rich comments in your Prisma schema:

    model Example {
      id String @id @default(cuid()) /// @zod.string.noDefault()
    }
    model WithDefaultValidators {
      id      String @id @default(cuid())
      idTwo   String @default(uuid())
      integer Int
    }
    
    // Becomes:
    // id: z.string().cuid()
    // idTwo: z.string().uuid()
    // integer: z.number().int()
  3. How to use custom Enums with Zod and TypeScript

    master

    For Prisma enums, the generator creates a separate type representing the enum values as a union. This is often more useful in TypeScript than standard enums. You can create a Zod schema for the enum using z.nativeEnum(PrismaClient.YourEnum) and then infer a string union type.

    // Prisma schema
    // enum MyEnum { A, B, C }
    
    export const MyEnumSchema = z.nativeEnum(PrismaClient.MyEnum);
    
    export type MyEnumType = `${z.infer<typeof MyEnumSchema>}`; // union of "A" | "B" | "C"
  4. Handling JSON null values in Zod schemas

    master

    Prisma distinguishes between Database NULL and JSON null. To support this in your Zod input schemas, you can pass the strings "DbNull" or "JsonNull". When the schema is parsed, these strings are automatically transformed into Prisma.DbNull or Prisma.JsonNull to satisfy Prisma's .create() or .update() methods.

    Note: This transformation only applies to input schemas (e.g., [myModel]CreateInputSchema). Model schemas (which represent database return values) are not affected and will contain actual null values.

    const parsedJsonSchema = myJsonSchema.parse({
      myJsonField: 'DbNull', // or "JsonNull"
    });
    
    // Result after transformation:
    // {
    //   myJsonField: Prisma.DbNull, // or Prisma.JsonNull
    // }
  5. Understand Zod schema naming conventions

    master

    Zod schemas are named by taking the generated Prisma type name and appending the string Schema. This allows you to easily identify the correct schema to import when working with Prisma functions (e.g., in tRPC procedures).

    import {
      UserFindFirstArgsSchema,
      UserFindManyArgsSchema,
      UserFindUniqueArgsSchema,
    } from './prisma/zod';
  6. Generate schemas with relation values

    master

    Setting createRelationValuesTypes = true generates a separate type and schema that includes all relation fields. This allows you to work with models that have their relations loaded.

    Note: Because this uses recursive types, the generated z.ZodType uses z.lazy() and has some limitations (e.g., you cannot use .merge() or .omit() on the resulting schema directly).

    generator zod {
      createRelationValuesTypes = true
    }
    
    model User {
      id    String @id
      posts Post[]
    }
  7. How Decimal fields are handled

    master

    Since zod does not support Decimals natively, the generator uses Prisma.Decimal and the DecimalJsLike type.

    • Input Schemas: These validate that the input is a valid string | number | Decimal | DecimalJsLike using a refine method and a regex helper. If decimal.js is installed in your project, the schema also validates against decimal.js instances.
    • Model Schemas: These reflect the actual return type from the database and use z.instanceof(Prisma.Decimal).

    Important: Because the generator uses instanceof Prisma.Decimal to validate inputs, you cannot import Prisma as a type-only import (import type { Prisma } ...) in files where these schemas are used; it must be a standard import.

  8. Generate Zod schemas from Prisma

    master

    After configuring your schema.prisma file, run the following command to generate a single index.ts file in the ./generated/zod output folder (by default) containing all your Zod schemas:

    npx prisma generate zod

    Then, import your schemas directly from the generated folder:

    import { mySchema } from './generated/zod';
  9. Add custom Zod validators via Prisma comments

    master

    You can inject custom Zod validation logic directly into your schema.prisma file using rich comments (///). This allows you to define specific constraints, error messages, and even custom logic for your generated schemas.

    Syntax: /// @zod.[zod-type + optional[(zod-error-messages)]].[zod validators for scalar-type]

    Capabilities:

    • Standard Zod methods: .min(), .max(), .gt(), .lt(), .int(), etc.
    • Custom logic: Use @zod.custom.use(...) to pass a full Zod expression (e.g., .refine() or .lazy()).
    • Imports: Use /// @zod.import(["import { x } from 'y'"]) at the model level to make external functions available to your custom validators.
    • Exclusion: Use /// @zod.omit(["field1", "field2"]) to exclude specific fields from generated schemas.
    /// @zod.import(["import { myFunction } from 'mypackage';"])
    model MyPrismaScalarsType {
      /// @zod.string({ invalid_type_error: "error message" }).cuid()
      id         String    @id @default(cuid())
    
      /// Some comment about string @zod.string.min(3, { message: "min error" }).max(10, { message: "max error" })
      string     String?
    
      /// @zod.custom.use(z.string().refine((val) => validator.isBIC(val), { message: 'BIC is not valid' }))
      bic        String?
    
      /// @zod.custom.use(z.lazy(() => InputJsonValue).refine((val) => myFunction(val), { message: 'Is not valid' }))
      json       Json
    
      /// @zod.custom.omit(["model", "input"])
      exclude    String?
    }
  10. Skip Zod schema generation via environment variable

    master

    You can prevent the generator from running by setting the SKIP_ZOD_PRISMA environment variable to 'true'. This is useful in environments like production where schemas are already generated and committed to your repository, and you only want to generate them during development.

    SKIP_ZOD_PRISMA = 'true';