iT邦幫忙

2024 iThome 鐵人賽

DAY 16
0
Modern Web

一些讓你看來很強的 ORM - prisma系列 第 16

Day16. 一些讓你看來很強的 ORM - prisma (Validator)上

  • 分享至 

  • xImage
  •  

今天的主題比較特別是本人非常喜歡的一個功能 Prisma validator ,他可以幫你自動 generate type 然後產生一個具有 type safeobject 根據你 model 的欄位

Creating a Typed Query

在沒有 Prisma validator 之前假設你有一個 userEmailobject 你希望重複利用這個 objectqueries 你要的 model data ,通常我們會用 prisma client generatetype 去定義這個 object 的型別, 如以下的 userEmail :

import { Prisma } from '@prisma/client'

const userEmail: Prisma.UserSelect = {
  email: true,
}

// Run inside async function
const user = await prisma.user.findUnique({
  where: {
    id: 3,
  },
  select: userEmail,
})

這個 query 是希望我們去找到 id 是 3 的 user 並在 return data 的時候只 return email 這個欄位,如果沒有這個 userreturn null

//index.ts
const getUser = async () => {
  const userEmail: Prisma.UserSelect = {
    email: true
  }
  const user = await prismaClient.user.findFirst({
    where: {
      id: 3
    },
    select: userEmail
  })
  console.log(user)
}

當我們執行 index.ts 會發現確實只有 email 欄位~

> tsx watch index.ts    
{ email: 'hiunji64@gmail.com' }

看起來是蠻順利的結果也如預期,但是當你 hover 後你會發現 userEmail 並沒有 type infer 出整個 object 有用到的 key type
https://ithelp.ithome.com.tw/upload/images/20240930/20145677NHFnGWSyMd.png

如果 userEmail 這個 object 只給 user.findFirst 使用倒是沒關係,但如果你把 userEmail export 出去給其他的 modelselect data ,就會有問題,因為目前的 object 並沒有限定只給 user.findFirst 使用,引用錯誤可能會導致存取到其他 model 的欄位,同時我們也無法知道 userEmail 他裡面 key type 到底有什麼,甚至也無法知道這個 object 有用過哪些 key

https://ithelp.ithome.com.tw/upload/images/20240930/20145677gKi3srkohu.png

假設我們需要更改 inputselect 結果,因為上圖 type 不明確,導致我們修改到錯誤的欄位

const userEmail: Prisma.UserSelect = {
    email: true
  }
  userEmail.name = true
  const user = await prismaClient.user.findFirst({
    where: {
      id: 3
    },
    select: userEmail
  })
 console.log(user)
}

如此我們就不小心存取到其他的欄位了,而且也不會爆 type error,顯然這是非常危險的

{ email: 'hiunji64@gmail.com', name: 'Danny' }

小結 所以使用 prisma client 提供的型別,他只是有 typed 但不是 type-safe 的,所以 prisma 為了解決這個問題,提供一個 Prisma validator 的功能~

Prisma Validator

使用 Prisma.validator 很簡單你只需要直接使用 prisma.validatorutils function 就好,同時需要提供哪個 model 的泛型

import { Prisma } from '@prisma/client'

//before
const userEmail: Prisma.UserSelect = {
  email: true,
}

//after
const userEmail = Prisma.validator<Prisma.UserSelect>()({
  email: true,
})

// Run inside async function
const user = await prisma.user.findUnique({
  where: {
    id: 3,
  },
  select: userEmail,
})

或這你可以再更詳細的定義這個 validator 用在哪個 model 哪個 methods

import { Prisma } from '@prisma/client'
import prisma from './lib/prisma'

const userEmail = Prisma.validator(
  prisma,
  'user',
  'findUnique',
  'select'
)({
  email: true,
})

如此現在 userEmail hover 上次後你會發現會自動看到哪些欄位是有使用到的了~

https://ithelp.ithome.com.tw/upload/images/20240930/20145677z5Ex7NoeiG.png

Demo

最後我們我們根據今天的內容寫一個小範例~

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

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

const createUserAndPost = (
  name: string,
  email: string,
  title: string,
) => {
  return Prisma.validator<Prisma.UserCreateInput>()({
    name,
    email,
    posts: {
      create: {
        title
      }
    }
  })
}
const findSpecificUser = (email: string) => {
  return Prisma.validator<Prisma.UserWhereInput>()({
    email
  })
}
const createUser = async () => {
  await prismaClient.user.create({
    data: createUserAndPost(
      'Rich',
      'rich@boop.com',
      'Life of Pie',
    )
  })
}
const getUser = async () => {
  const user = await prismaClient.user.findUnique({
    where: findSpecificUser('rich@boop.com')
  })
  console.log(user)
}

  • createUserAndPost: 定義 create Uservalidator
  • findSpecificUser: 定義 User.findUniquevalidator
  • getUser :使用 findSpecificUservalidatorget data

讀者可以根據 demo 的內容試著自己寫一遍,最終你會看到 getUserresponse

{ id: 1, name: 'Rich', email: 'rich@boop.com' }

大家如果有問題可以來小弟的群組討論~

✅ 前端社群 :
https://lihi3.cc/kBe0Y


上一篇
Day15. 一些讓你看來很強的 ORM - prisma (Self Relation)
下一篇
Day17. 一些讓你看來很強的 ORM - prisma (Validator)下
系列文
一些讓你看來很強的 ORM - prisma30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言