Shared Prisma Client extensions
You can share your Prisma Client extensions with other users, either as packages or as code snippets, and import extensions that other users create into your Prisma projects.
Share Prisma Client extensions
When you want to create extensions that will work for other users, and not just for your specific schema, use the $all
prefix, such as $allModels
. Extensions that use $all
apply generally, not just to a named component of a specific schema.
You do not need to use the $all
prefix with the client
component, because the client
component always applies generally.
For example, a generic extension might take the following form:
const xprisma = prisma.$extends({model: {$allModels: {// new methodfindOrCreate(...) { } // code for the new method goes inside the brackets}}})
Package an extension
Use Prisma.defineExtension
to make your extensions shareable. You can use it to package a feature that you want to share with other users. When someone wants to use your extension in their project, they can apply the extension to a Prisma Client instance with prisma.$extends
.
You can also use Prisma.defineExtension
to move an extension to another file in your project. When you do this, you benefit from auto-completion and type checks.
To package an extension, you might use the following code:
import { Prisma } from '@prisma/client'export default Prisma.defineExtension({model: {$allModels: {// new methodfindOrCreate(...) { } // code for the new method goes inside the brackets}}})
You can then share the extension on npm
. When you choose a package name, we recommend that you use the prisma-extension-<package-name>
convention, to make it easier to find and install.
Call a client-level method from your packaged extension
In the following situations, you need to refer to a Prisma Client instance that your extension wraps:
- When you want to use a client-level method, such as
$queryRaw
, in your packaged extension. - When you want to chain multiple
$extends
calls in your packaged extension.
However, when someone includes your packaged extension in their project, your code cannot know the details of the Prisma Client instance.
You can refer to this client instance as follows:
Prisma.defineExtension((client) => {// The Prisma Client instance that the extension user applies the extension toreturn client.$extends({})})
For example:
export default Prisma.defineExtension((client) => {return client.$extends({query: {$allModels: {async findOrCreate({ args, query, operation }) {return (await client.$transaction([query(args)]))[0]},},},})})
Improve the type safety and developer experience of your shared extensions
You can improve the type-safety and developer experience of your shared extensions with the type utilities on model
components.
Install a packaged extension
In your project, you can install any Prisma Client extension that another user has published to npm
. To do so, run the following command:
$npm install prisma-extension-<package-name>
For example, if the package name for an available extension is prisma-extension-find-or-create
, you could install it as follows:
$npm install prisma-extension-find-or-create
To import the find-or-create
extension from the example above, and wrap your client instance with it, you could use the following code. This example assumes that the extension name is findOrCreate
.
import findOrCreate from 'prisma-extension-find-or-create'const xprisma = prisma.$extends(findOrCreate)const user = await xprisma.user.findOrCreate({ ... })xprisma.user.findOrCreate()
When you call a method in an extension, use the constant name from your $extends
statement, not prisma
. In the above example,xprisma.user.findOrCreate
works, but prisma.user.findOrCreate
does not, because the original prisma
is not modified.