Prisma Client extensions
From version 4.7.0, you can use Prisma Client extensions to add functionality to your models, result objects, and queries, or to add client-level methods.
You can create an extension with one or more of the following component types:
model
: add custom methods or fields to your modelsclient
: add client-level methods to Prisma Clientquery
: create custom Prisma Client queriesresult
: add custom fields to your query results
For example, you might create an extension that uses the model
and client
component types.
About Prisma Client extensions
When you use a Prisma Client extension, you create an extended client. An extended client is a lightweight variant of the standard Prisma Client that is wrapped by one or more extensions. The standard client is not mutated. You can add as many extended clients as you want to your project. Learn more about extended clients.
You can associate a single extension, or multiple extensions, with an extended client. Learn more about multiple extensions.
You can share your Prisma Client extensions with other Prisma users, and import Prisma Client extensions developed by other users into your Prisma project.
Extended clients
Extended clients interact with each other, and with the standard client, as follows:
- Each extended client operates independently in an isolated instance.
- Extended clients cannot conflict with each other, or with the standard client.
- All extended clients and the standard client communicate with the same Prisma query engine.
- All extended clients and the standard client share the same connection pool.
Example use cases for extended clients
Because extended clients operate in isolated instances, they can be a good way to do the following, for example:
- Implement row-level security (RLS), where each HTTP request has its own client with its own RLS extension, customized with session data. This can keep each user entirely separate, each in a separate client.
- Add a
user.current()
method for theUser
model to get the currently logged-in user. - Enable more verbose logging for requests if a debug cookie is set.
- Attach a unique request id to all logs so that you can correlate them later, for example to help you analyze the operations that Prisma Client carries out.
- Remove a
delete
method from models unless the application calls the admin endpoint and the user has the necessary privileges.
Extensions prerequisites
Prisma Client extensions are available in Preview from version 4.7.0.
To use Prisma Client extensions, you must enable the clientExtensions
preview feature flag in the generator
block of your schema.prisma
file, as follows:
generator client {provider = "prisma-client-js"previewFeatures = ["clientExtensions"]}
Create an extension
Use the $extends
client-level method to create an extended client. In your $extends
structure, use the appropriate extension component or components (model
, client
, result
or query
).
For example, the following code uses a model
extension component to extend the User
model.
const xprisma = prisma.$extends({name: `signUp`, // Optional: name appears in error logsmodel: { // This is a `model` componentuser: { ... } // The extension logic for the `user` model goes inside the curly braces},})
Name an extension for error logs
You can name your extensions to help identify them in error logs. To do so, use the optional field name
. For example:
const xprisma = prisma.$extends({name: `signUp`, // (Optional) Extension namemodel: {user: { ... }},})
Multiple extensions
You can associate an extension with an extended client in one of two ways:
- You can associate it with an extended client on its own, or
- You can combine the extension with other extensions and associate all of these extensions with an extended client. The functionality from these combined extensions applies to the same extended client. Note: Combined extensions can conflict.
You can combine the two approaches above. For example, you might associate one extension with its own extended client and associate two other extensions with another extended client. Learn more about how client instances interact.
Apply multiple extensions to an extended client
In the following example, suppose that you have two extensions, extensionA
and extensionB
. There are two ways to combine these.
Option 1: Declare the new client in one line
With this option, you apply both extensions to a new client in one line of code.
// First of all, store your original Prisma Client in a variable as usualconst prisma = new PrismaClient()// Declare an extended client that has an extensionA and extensionBconst prismaAB = prisma.$extends(extensionA).$extends(extensionB)
You can then refer to prismaAB
in your code, for example prismaAB.myExtensionMethod()
.
Option 2: Declare multiple extended clients
The advantage of this option is that you can call any of the extended clients separately.
// First of all, store your original Prisma Client in a variable as usualconst prisma = new PrismaClient()// Declare an extended client that has extensionA appliedconst prismaA = prisma.$extends(extensionA)// Declare an extended client that has extensionB appliedconst prismaB = prisma.$extends(extensionB)// Declare an extended client that is a combination of clientA and clientBconst prismaAB = prismaA.$extends(extensionB)
In your code, you can call any of these clients separately, for example prismaA.myExtensionMethod()
, prismaB.myExtensionMethod()
, or prismaAB.myExtensionMethod()
.
Conflicts in combined extensions
When you combine two or more extensions into a single extended client, then the last extension that you declare takes precedence in any conflict. In the example in option 1 above, suppose there is a method called myExtensionMethod()
defined in extensionA
and a method called myExtensionMethod()
in extensionB
. When you call prismaAB.myExtensionMethod()
, then Prisma Client uses myExtensionMethod()
as defined in extensionB
.