zod-prisma-types で Prisma から Zod を生成する

zod-prisma-types で Prisma から Zod を生成する

2023-03-1311 min read

目次

  1. 概要
  2. 環境
  3. インストール
  4. prisma-schema-の定義
  5. コメントを利用したバリデーションルールの定義
  6. 類似パッケージとの比較

概要

NestJS Prisma Zod OpenAPI で型を堅牢にしたアプリケーションの開発 | 404 motivation not foundを書いている際に Prisma から Zod のオブジェクトを生成するパッケージをいくつか利用して比較しました。

その中でも zod-prisma-types というパッケージが比較的に良かったので、これについて書いていきます。

環境

  • Prisma: 4.11
  • zod-prisma-types: 2.5

インストール

パッケージマネージャに合わせてPrismazod-prisma-typesのインストールを行います。

npm install zod-prisma-types
# or
yarn add zod-prisma-types
# or
pnpm add zod-prisma-types

Prisma Schema の定義

今回は sqlite を利用します。 以下のようにテスト用のテーブルを定義します。

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

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

model User {
  id    Int     @id @default(autoincrement())
  email String  @unique
  name  String?
  posts Post[]
}

model Post {
  id        Int      @id @default(autoincrement())
  title     String
  content   String?
  published Boolean? @default(false)
  author    User?    @relation(fields: [authorId], references: [id])
  authorId  Int?
}

このスキーマに対して、zod-prisma-typesのオプションを追加します。

generator zod {
  provider                         = "zod-prisma-types"
  // 自動生成されたファイルが配置されるパス
  output                           = "../src/schema/zod"
  // ファイル分割の定義
  // useMultipleFiles                 = true // default is false
  createInputTypes                 = false // default is true
  // createModelTypes                 = false // default is true
  // addInputTypeValidation           = false // default is true
  // addIncludeType                   = false // default is true
  // addSelectType                    = false // default is true
  // validateWhereUniqueInput         = true // default is false
  // createOptionalDefaultValuesTypes = true // default is false
  // createRelationValuesTypes        = true // default is false
  // createPartialTypes               = true // default is false
  // useDefaultValidators             = false // default is true
  // coerceDate                       = false // default is true
  // writeNullishInModelTypes         = true // default is false
  // prismaClientPath                 = "./path/to/prisma/client" // default is client output path
}

createInputTypes = false としたのは Prisma の Create や Update で利用される全ての Schema を生成してしまうために、 最低限のファイルを生成するようにしたためです。

これにより次のファイルが生成されます。

import { z } from "zod";
import type { Prisma } from "@prisma/client";

export const PostScalarFieldEnumSchema = z.enum([
  "id",
  "title",
  "content",
  "published",
  "authorId",
]);

export const SortOrderSchema = z.enum(["asc", "desc"]);

export const TransactionIsolationLevelSchema = z.enum(["Serializable"]);

export const UserScalarFieldEnumSchema = z.enum(["id", "email", "name"]);

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

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

export const PostSchema = z.object({
  id: z.number().int(),
  title: z.string(),
  content: z.string().nullable(),
  published: z.boolean().nullable(),
  authorId: z.number().int().nullable(),
});

export type Post = z.infer<typeof PostSchema>;

コメントを利用したバリデーションルールの定義

以下コードのようにコメントを利用して zod のルールを定義をすると生成したファイルの zod オブジェクトにもルールが追加されます。

model User {
  id    Int     @id @default(autoincrement())
  /// @zod.string.email()
  email String  @unique
  /// @zod.string.max(255, { message: "max error" })
  name  String?
  posts Post[]
}
export const UserSchema = z.object({
  id: z.number().int(),
  email: z.string().email(),
  name: z.string().max(255, { message: "max error" }).nullable(),
});

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

ちなみに、このバージョンでは /// @zod.string.max(255, { message: "255字未満で入力してください" }) のように日本語を利用すると正しく zod のオブジェクトが生成されませんでした。

類似パッケージとの比較

zod-prisma-typesを検証するにあたり、類似のパッケージも比較しましたが、最終的にこれに落ち着きました。

Prisma Zod Generator

基本的な機能には不満はなかったのですが、利用できるオプションが少なく自由度が低いと思いました。

Zod Prisma

こちらも機能には不満はなかったのですが、2023 年 3 月時点で最終更新が 1 年前であり、更新が止まっている点が気になりました。

Is this library alive? · Issue #148 · CarterGrimmeisen/zod-prisma å

Tags
javascript(110)
node.js(54)
linux(54)
amazon%20aws(47)
typescript(45)
%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0(36)
%E7%94%BB%E5%83%8F%E5%87%A6%E7%90%86(30)
html5(29)
php(24)
centos(24)
python(22)
%E7%AB%B6%E6%8A%80%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0(21)
mac(21)
mysql(20)
canvas(19)
opencv(17)
%E9%9B%91%E8%AB%87(16)
docker(16)
wordpress(15)
atcoder(14)
apache(12)
%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92(12)
%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9(12)
amazon%20s3(12)
red%20hat(12)
prisma(12)
ubuntu(11)
github(10)
git(10)
vue.js(10)
%E7%94%BB%E5%83%8F%E5%87%A6%E7%90%86100%E6%9C%AC%E3%83%8E%E3%83%83%E3%82%AF(10)
mariadb(10)
react(9)
aws%20cdk(9)
css3(8)
%E5%8F%AF%E8%A6%96%E5%8C%96(8)
%E5%B0%8F%E3%83%8D%E3%82%BF(8)
nestjs(8)
amazon%20lightsail(7)
next.js(7)
%E3%83%96%E3%83%AD%E3%82%B0(6)
cms(6)
oracle(6)
perl(6)
gitlab(6)
iam(5)
amazon%20ec2(5)
%E8%B3%87%E6%A0%BC%E8%A9%A6%E9%A8%93(5)
aws%20amplify(5)
curl(4)
Author
githubzennqiita
ただの備忘録です。

※外部送信に関する公表事項