在 prisma client 中除了昨天介紹的透過 zod 在 prisma.$extends 中 validate query input,以及透過 prisma.$extends.result 去 Computed fields 外,其實還有其他的功能,在 prisma.$extends 我們也可以客製化 model 的 methods 至於怎麼做到我們繼續看下去
一樣這是今天的 model
User 有 email 跟 password 欄位Password model 去管理 user
model User {
id String @id @default(cuid())
email String
password Password?
}
model Password {
hash String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId String @unique
}
我們今天的範例主要是做一個 user 註冊的功能,所以我們 User model 才會有 email 以及 password 的欄位,通常我們在 create User 的時候,我們不會在 DB 直接存取 password ,取而代之的是我們會存 hash 過後的內容,以防止 user 的 password 被偷走,在 $extends 中我們實作 signUp 邏輯
這邊我們需要先 install bcryptjs 來幫我們 hash password
>npm i bcryptjs
>npm i --save-dev @types/bcryptjs
在 $extends.model 中我們可以自訂想要的 function 在特定的 model 裡,在 user.signUp 我們吃兩個參數 email 跟 password ,為了防止 user 的 password 存到 DB ,所以我們使用 bcrypt 幫我們 hash password,最後我們 return create user 的結果
import bcrypt from 'bcryptjs'
const prismaClient = new PrismaClient().$extends({
model: {
user: {
signUp: async (email: string, password: string) => {
const hash = await bcrypt.hash(password, 10)
return prismaClient.user.create({
data: {
email,
password: {
create: {
hash
}
}
}
})
}
}
}
})
使用 signUp 這個 function 也很簡單,所有在 $extends.model 的內容,prisma client 都會自動幫你產生對應的 type,使用起來非常方便

如此我們就成功 create 一個 user 了~
const user = await prismaClient.user.signUp('hiunji64@gmail.com', '123456')
{
user: { id: 'cm1te0z5r0000p581g6thkkqn', email: 'hiunji64@gmail.com' }
}
接著我們在定另外一個 function ,去找到使用特定 domain 當作 email 的 user 有哪些,如以下的 findManyByDomain
const prismaClient = new PrismaClient().$extends({
model: {
user: {
//..
findManyByDomain: (domain: string) => {
return prismaClient.user.findMany({
where: {
email: {
endsWith: `@${domain}`
}
}
})
}
}
}
})
如此我們就可以透過 findManyByDomain 拿查詢內容拉,是不是簡化非常多~
const userLists = await prismaClient.user.findManyByDomain('gmail.com')
{
userLists: [
{ id: 'cm1tcqxoz0000b1cl7j9dy9xb', email: 'hiunji64@gmail.com' }
]
}
最後我們再補充一個 signIn 來驗證 user 的 email 或是 password 是否正確,步驟如下:
findUser 有資料,代表 email 是正確的,沒有的話直接 return user not found
bcrypt.compare 去驗證 findUser.password.hash 是否跟 input 的 password 是否一樣const prismaClient = new PrismaClient().$extends({
model: {
user: {
//..
signIn: async (email: string, password: string) => {
const findUser = await prismaClient.user.findFirst({
where: {
email
},
include: {
password: true
}
})
if (findUser === null) {
return 'user not found'
}
const verifyResult = await bcrypt.compare(password, findUser.password?.hash ?? '')
return {
verifyResult
}
}
}
}
})
接著我們測試一下如果 input 不存在的 email,顯然有正確 return user not found
const result = await prismaClient.user.signIn('aaa@gmail.com', '123456')
{ result: 'user not found' }
如果 email 正確蛋 password 錯誤,則 verifyResult 就是 false
const result = await prismaClient.user.signIn('hiunji64@gmail.com', '123456dd')
{ result: { verifyResult: false } }
反之如果 password 正確則驗證就成功了,之後就可以呼叫 prismaClient.user.signIn 去判斷 input 的來源是否正確~
const result = await prismaClient.user.signIn('hiunji64@gmail.com', '123456')
{ result: { verifyResult: true } }
以上就是今天的內容希望大家喜歡~
✅ 前端社群 :
https://lihi3.cc/kBe0Y