`model`: Add custom methods to your models

Prisma Client extensions are Generally Available from versions 4.16.0 and later. They were introduced in Preview in version 4.7.0. Make sure you enable the clientExtensions Preview feature flag if you are running on a version earlier than 4.16.0.

You can use the model Prisma Client extensions component type to add custom methods to your models.

Possible uses for the model component include the following:

  • New operations to operate alongside existing Prisma Client operations, such as findMany
  • Encapsulated business logic
  • Repetitive operations
  • Model-specific utilities

Add a custom method

Use the $extends client-level method to create an extended client. An extended client is a variant of the standard Prisma Client that is wrapped by one or more extensions. Use the model extension component to add methods to models in your schema.

Add a custom method to a specific model

To extend a specific model in your schema, use the following structure. This example adds a method to the user model.

const prisma = new PrismaClient().$extends({
name?: '<name>', // (optional) names the extension for error logs
model?: {
user: { ... } // in this case, we extend the `user` model
},
});

Example

The following example adds a method called signUp to the user model. This method creates a new user with the specified email address.

const prisma = new PrismaClient().$extends({
model: {
user: {
async signUp(email: string) {
await prisma.user.create({ data: { email } })
},
},
},
})

You would call signUp in your application as follows:

const user = await prisma.user.signUp('john@prisma.io')

When you call a method in an extension, use the constant name from your $extends statement, not prisma. In the above example, prisma.user.signUp works, but prisma.user.signUp does not, because the original prisma is not modified.

Add a custom method to all models in your schema

To extend all models in your schema, use the following structure:

const prisma = new PrismaClient().$extends({
name?: '<name>', // `name` is an optional field that you can use to name the extension for error logs
model?: {
$allModels: { ... }
},
})

Example

The following example adds an exists method to all models.

const prisma = new PrismaClient().$extends({
model: {
$allModels: {
async exists<T>(
this: T,
where: Prisma.Args<T, 'findFirst'>['where']
): Promise<boolean> {
// Get the current model at runtime
const context = Prisma.getExtensionContext(this)
const result = await (context as any).findFirst({ where })
return result !== null
},
},
},
})

You would call exists in your application as follows:

// `exists` method available on all models
await prisma.user.exists({ name: 'Alice' })
await prisma.post.exists({
OR: [{ title: { contains: 'Prisma' } }, { content: { contains: 'Prisma' } }],
})

Call a custom method from another custom method

You can call a custom method from another custom method, if the two methods are declared on the same model. For example, you can call a custom method on the user model from another custom method on the user model. It does not matter if the two methods are declared in the same extension or in different extensions.

To do so, use Prisma.getExtensionContext(this).methodName. Note that you cannot use prisma.user.methodName. This is because prisma is not extended yet, and therefore does not contain the new method.

For example:

const prisma = new PrismaClient().$extends({
model: {
user: {
firstMethod() {
...
},
secondMethod() {
Prisma.getExtensionContext(this).firstMethod()
}
}
}
})

Get the current model name at runtime

This feature is available from version 4.9.0.

You can get the name of the current model at runtime with Prisma.getExtensionContext(this).name. You might use this to write out the model name to a log, to send the name to another service, or to branch your code based on the model.

For example:

// `context` refers to the current model
const context = Prisma.getExtensionContext(this)
// `context.name` returns the name of the current model
console.log(context.name)
// Usage
await(context as any).findFirst({ args })

Refer to Add a custom method to all models in your schema for a concrete example for retrieving the current model name at runtime.

Advanced type safety: type utilities for defining generic extensions

You can improve the type-safety of model components in your shared extensions with type utilities.