Custom validation
You can add runtime validation for your user input for Prisma Client queries in one of the following ways:
- Prisma Client extensions
- A custom function
You can use any validation library you'd like. The Node.js ecosystem offers a number of validation libraries to choose from, including: joi, validator.js, Yup, Zod and Superstruct.
Input validation with Prisma Client extensions
Section titled “Input validation with Prisma Client extensions”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.
import { PrismaClient, Prisma } from "../prisma/generated/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"
}
generator client {
provider = "prisma-client"
output = "./generated"
}
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
}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.
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
Section titled “Input validation with a custom validation function”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,
});
}The example above shows how you can create a custom type-safe signup function that ensures the input is valid before creating a user.
- Learn how you can use Prisma Client extensions to add input validation for your queries — example.
- Learn how you can organize your code better by moving the
signupfunction into a custom model. - 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!