Skip to content

Zod Prisma

Directory Structure

.
|-- package.json
|-- prisma
|   |-- migrations
|   |   |-- *_init
|   |   |   `-- migration.sql
|   |   `-- migration_lock.toml
|   |-- schema.prisma
|   `-- zod
|       |-- index.ts
|       `-- post.ts
|-- src
|   `-- index.ts
`-- tsconfig.json
sh
yarn add -D zod-prisma
prisma
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "sqlite"
  url      = env("DATABASE_URL")
}

generator zod {
  provider = "zod-prisma"
  output   = "./zod" // (default) the directory where generated zod schemas will be saved

  relationModel = true // (default) Create and export both plain and related models.
  // relationModel         = "default" // Do not export model without relations.
  // relationModel         = false // Do not generate related model

  modelCase = "PascalCase" // (default) Output models using pascal case (ex. UserModel, PostModel)
  // modelCase             = "camelCase" // Output models using camel case (ex. userModel, postModel)

  modelSuffix = "Model" // (default) Suffix to apply to your prisma models when naming Zod schemas

  // useDecimalJs          = false // (default) represent the prisma Decimal type using as a JS number
  useDecimalJs = true // represent the prisma Decimal type using Decimal.js (as Prisma does)

  // https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-by-null-values
  prismaJsonNullability = true // (default) uses prisma's scheme for JSON field nullability
  // prismaJsonNullability = false // allows null assignment to optional JSON fields
}

model Post {
  /// The unique identifier for the post
  /// @default {Generated by database}
  id String @id @default(uuid())

  /// A brief title that describes the contents of the post
  title String

  /// The actual contents of the post.
  contents String
}

Generate

sh
yarn prisma generate

Generated Zod

ts
export * from './post'
ts
import * as z from 'zod'

export const PostModel = z.object({
  /**
   * The unique identifier for the post
   * @default {Generated by database}
   */
  id: z.string(),
  /**
   * A brief title that describes the contents of the post
   */
  title: z.string(),
  /**
   * The actual contents of the post.
   */
  contents: z.string(),
})

Options

output

 生成された Zod スキーマの出力先ディレクトリを指定。デフォルトでは "./zod" ディレクトリに保存。

relationModel

  • true : 基本のモデルとリレーション付きモデルの両方をエクスポート。

  • false : リレーションモデルを生成しない。

  • defalut : リレーションのないモデルはエクスポートされない。

modelCase

  • PascalCase : PostModel

  • camelCase : postModel

modelSuffix

 生成される Zod スキーマのモデルに追加されるサフィックス(接尾辞)。デフォルトでは "Model" が追加される(例:UserModel)。

  • modelSuffix = "Schema" : postSchema

useDecimalJs

 Prisma の Decimal 型を Decimal.js ライブラリを使用して表現するかどうかを指定。

prismaJsonNullability

 Prismaでは、JSONフィールドにnull値を設定することが禁止されている。これは、データベース上でフィールドの値をNULLに設定することと、JSON内にnullを保存することの区別を明確にするため。これにより、zod-prisma(PrismaとZodを統合するライブラリ)はデフォルトでJSONフィールドにnull値を許可しない設定になっている。そのJSONフィールドがオプショナルであったとしても、nullは保存できない。

 もしnullをJSONフィールドに保存したい場合は、PrismaのジェネレーターオプションでprismaJsonNullabilityをfalseに設定することで、nullの代入を許可することができる。この設定を変更することで、JSONフィールドにnullを保存することが可能になる。

JSDoc

prisma
model Post {
  /// ID
  /// @default {Generated by database}
  id       String @id @default(uuid())
  /// タイトル
  title    String
  /// 投稿内容
  contents String
}

Generated Zod

ts
import * as z from 'zod'

export const postSchema = z.object({
  /**
   * ID
   * @default {Generated by database}
   */
  id: z.string(),
  /**
   * タイトル
   */
  title: z.string(),
  /**
   * 投稿内容
   */
  contents: z.string(),
})

Extending Zod Fields

prisma
model Post {
  /// ID
  /// @default {Generated by database}
  /// @zod.uuid()
  id       String @id @default(uuid())
  /// タイトル
  /// @zod.max(255, { message: "The title must be shorter than 256 characters" })
  title    String
  /// 投稿内容
  /// @zod.max(140)
  contents String
}

Generated Zod

ts
import * as z from 'zod'

export const postSchema = z.object({
  /**
   * ID
   * @default {Generated by database}
   */
  id: z.string().uuid(),
  /**
   * タイトル
   */
  title: z.string().max(255, { message: 'The title must be shorter than 256 characters' }),
  /**
   * 投稿内容
   */
  contents: z.string().max(140),
})