自定义验证
你可以通过以下方式之一为 Prisma 客户端查询的用户输入添加运行时验证:
¥You can add runtime validation for your user input for Prisma Client queries in one of the following ways:
-
自定义函数
¥A custom function
你可以使用任何你想要的验证库。Node.js 生态系统提供了许多高质量、易于使用的验证库可供选择,包括:joi、validator.js、是的、佐德 和 Superstruct。
¥You can use any validation library you'd like. The Node.js ecosystem offers a number of high-quality, easy-to-use validation libraries to choose from including: joi, validator.js, Yup, Zod and Superstruct.
使用 Prisma 客户端扩展进行输入验证
¥Input validation with Prisma Client extensions
此示例在使用 Zod 架构创建和更新值时添加运行时验证,以检查传递到 Prisma Client 的数据是否有效。
¥This example adds runtime validation when creating and updating values using a Zod schema to check that the data passed to Prisma Client is valid.
查询扩展当前不适用于嵌套操作。在此示例中,验证仅在传递给 prisma.product.create()
等方法的顶层数据对象上运行。以这种方式实现的验证不会自动针对 嵌套写入 运行。
¥Query extensions do not currently work for nested operations. In this example, validations are only run on the top level data object passed to methods such as prisma.product.create()
. Validations implemented this way do not automatically run for nested writes.
- Prisma Client extension
- Prisma schema
import { PrismaClient, Prisma } from '@prisma/client'
import { z } from 'zod'
/**
* Zod schema
*/
export const ProductCreateInput = z.object({
slug: z
.string()
.max(100)
.regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/),
name: z.string().max(100),
description: z.string().max(1000),
price: z
.instanceof(Prisma.Decimal)
.refine((price) => price.gte('0.01') && price.lt('1000000.00')),
}) satisfies z.Schema<Prisma.ProductUncheckedCreateInput>
/**
* Prisma Client Extension
*/
const prisma = new PrismaClient().$extends({
query: {
product: {
create({ args, query }) {
args.data = ProductCreateInput.parse(args.data)
return query(args)
},
update({ args, query }) {
args.data = ProductCreateInput.partial().parse(args.data)
return query(args)
},
updateMany({ args, query }) {
args.data = ProductCreateInput.partial().parse(args.data)
return query(args)
},
upsert({ args, query }) {
args.create = ProductCreateInput.parse(args.create)
args.update = ProductCreateInput.partial().parse(args.update)
return query(args)
},
},
},
})
async function main() {
/**
* Example usage
*/
// Valid product
const product = await prisma.product.create({
data: {
slug: 'example-product',
name: 'Example Product',
description: 'Lorem ipsum dolor sit amet',
price: new Prisma.Decimal('10.95'),
},
})
// Invalid product
try {
await prisma.product.create({
data: {
slug: 'invalid-product',
name: 'Invalid Product',
description: 'Lorem ipsum dolor sit amet',
price: new Prisma.Decimal('-1.00'),
},
})
} catch (err: any) {
console.log(err?.cause?.issues)
}
}
main()
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
model Product {
id String @id @default(cuid())
slug String
name String
description String
price Decimal
reviews Review[]
}
model Review {
id String @id @default(cuid())
body String
stars Int
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
productId String
}
上面的示例使用 Zod 架构在将记录写入数据库之前在运行时验证和解析查询中提供的数据。
¥The above example uses a Zod schema to validate and parse data provided in a query at runtime before a record is written to the database.
使用自定义验证函数进行输入验证
¥Input validation with a custom validation function
以下是使用 Superstruct 验证注册新用户所需的数据是否正确的示例:
¥Here's an example using Superstruct to validate that the data needed to signup a new user is correct:
import { PrismaClient, Prisma, User } from '@prisma/client'
import { assert, object, string, size, refine } from 'superstruct'
import isEmail from 'isemail'
const prisma = new PrismaClient()
// Runtime validation
const Signup = object({
// string and a valid email address
email: refine(string(), 'email', (v) => isEmail.validate(v)),
// password is between 7 and 30 characters long
password: size(string(), 7, 30),
// first name is between 2 and 50 characters long
firstName: size(string(), 2, 50),
// last name is between 2 and 50 characters long
lastName: size(string(), 2, 50),
})
type Signup = Omit<Prisma.UserCreateArgs['data'], 'id'>
// Signup function
async function signup(input: Signup): Promise<User> {
// Assert that input conforms to Signup, throwing with a helpful
// error message if input is invalid.
assert(input, Signup)
return prisma.user.create({
data: input.user,
})
}
上面的示例显示了如何创建自定义类型安全 signup
函数,以确保在创建用户之前输入有效。
¥The example above shows how you can create a custom type-safe signup
function that ensures the input is valid before creating a user.
更进一步
¥Going further
-
了解如何使用 Prisma 客户端扩展 为查询添加输入验证 - example。
¥Learn how you can use Prisma Client extensions to add input validation for your queries — example.
-
了解如何通过将
signup
函数移至 定制模型 来更好地组织代码。¥Learn how you can organize your code better by moving the
signup
function into a custom model. -
有一个 突出的功能请求 将用户验证烘焙到 Prisma 客户端中。如果你希望看到这种情况发生,请务必对该问题进行投票并分享你的用例!
¥There's an outstanding feature request to bake user validation into Prisma Client. If you'd like to see that happen, make sure to upvote that issue and share your use case!