跳至主要内容

共享 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 提供了一些工具,允许你创建可共享的扩展。

要创建一个可共享的扩展

  1. 使用 Prisma.defineExtension 将扩展定义为模块
  2. 使用以 $all 前缀开头的方法,例如 $allModels$allOperations

定义扩展

使用 Prisma.defineExtension 方法使你的扩展可共享。你可以使用它来打包扩展,将其分离到一个单独的文件中,或者将其作为 npm 包与其他用户共享。

Prisma.defineExtension 的好处是,它为扩展的作者在开发过程中提供了严格的类型检查和自动完成,并为共享扩展的用户提供了类型安全保障。

使用通用方法

$allModels 下包含方法的扩展适用于每个模型,而不是某个特定的模型。类似地,在 $allOperations 下的方法适用于整个客户端实例,而不是某个命名的组件,例如 resultquery

你不需要对 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]
},
},
},
})
})

高级类型安全:用于定义通用扩展的类型工具

你可以使用 类型工具 来提高共享扩展的类型安全。