共享 Prisma 客户端扩展
你可以与其他用户共享你的 Prisma 客户端扩展,无论是作为包还是模块,还可以将其他用户创建的扩展导入你的项目。
如果你想要构建一个可共享的扩展,我们也建议你使用 prisma-client-extension-starter
模板。
安装一个共享的、打包的扩展
在你的项目中,你可以安装任何其他用户发布到 npm
的 Prisma 客户端扩展。为此,请运行以下命令
npm install prisma-extension-<package-name>
例如,如果一个可用扩展的包名为 prisma-extension-find-or-create
,你可以按以下方式安装它
npm install prisma-extension-find-or-create
要从上面的示例中导入 find-or-create
扩展,并用它包装你的客户端实例,你可以使用以下代码。此示例假设扩展名是 findOrCreate
。
import findOrCreate from 'prisma-extension-find-or-create'
const prisma = new PrismaClient().$extends(findOrCreate)
const user = await prisma.user.findOrCreate()
当你在扩展中调用方法时,请使用来自 $extends
语句的常量名,而不是 prisma
。在上面的示例中,xprisma.user.findOrCreate
可以正常工作,但 prisma.user.findOrCreate
不行,因为原始的 prisma
没有被修改。
创建可共享的扩展
当你想要创建其他用户可以使用的扩展,并且这些扩展不是专门为你自己的模式量身定制的,Prisma ORM 提供了一些工具,允许你创建可共享的扩展。
要创建一个可共享的扩展
- 使用
Prisma.defineExtension
将扩展定义为模块 - 使用以
$all
前缀开头的方法,例如$allModels
或$allOperations
定义扩展
使用 Prisma.defineExtension
方法使你的扩展可共享。你可以使用它来打包扩展,将其分离到一个单独的文件中,或者将其作为 npm 包与其他用户共享。
Prisma.defineExtension
的好处是,它为扩展的作者在开发过程中提供了严格的类型检查和自动完成,并为共享扩展的用户提供了类型安全保障。
使用通用方法
在 $allModels
下包含方法的扩展适用于每个模型,而不是某个特定的模型。类似地,在 $allOperations
下的方法适用于整个客户端实例,而不是某个命名的组件,例如 result
或 query
。
你不需要对 client
组件使用 $all
前缀,因为 client
组件始终适用于客户端实例。
例如,一个通用的扩展可能具有以下形式
export default Prisma.defineExtension({
name: 'prisma-extension-find-or-create', //Extension name
model: {
$allModels: {
// new method
findOrCreate(/* args */) {
/* code for the new method */
return query(args)
},
},
},
})
参考以下页面,了解可以修改 Prisma 客户端操作的不同方法
对于 4.16.0 之前的版本
Prisma
导入可从以下代码段中所示的不同路径获得
import { Prisma } from '@prisma/client/scripts/default-index'
export default Prisma.defineExtension({
name: 'prisma-extension-<extension-name>',
})
将可共享的扩展发布到 npm
然后,你可以在 npm
上共享该扩展。当你选择包名时,我们建议你使用 prisma-extension-<package-name>
约定,以便更容易地找到和安装它。
从打包的扩展中调用客户端级别的方法
在以下情况下,你需要引用扩展所包装的 Prisma 客户端实例
- 当你想要在打包的扩展中使用 客户端级别方法,例如
$queryRaw
。 - 当你想要在打包的扩展中链式调用多个
$extends
调用。
但是,当有人将你的打包的扩展包含在他们的项目中时,你的代码无法知道 Prisma 客户端实例的详细信息。
你可以按以下方式引用该客户端实例
Prisma.defineExtension((client) => {
// The Prisma Client instance that the extension user applies the extension to
return client.$extends({
name: 'prisma-extension-<extension-name>',
})
})
例如
export default Prisma.defineExtension((client) => {
return client.$extends({
name: 'prisma-extension-find-or-create',
query: {
$allModels: {
async findOrCreate({ args, query, operation }) {
return (await client.$transaction([query(args)]))[0]
},
},
},
})
})
高级类型安全:用于定义通用扩展的类型工具
你可以使用 类型工具 来提高共享扩展的类型安全。