跳至主要内容

共享 Prisma Client 扩展

您可以与其他用户共享您的 Prisma Client 扩展,无论是作为包还是模块,并将其他用户创建的扩展导入到您的项目中。

如果您想构建一个可共享的扩展,我们还建议使用 prisma-client-extension-starter 模板。

安装共享的打包扩展

在您的项目中,您可以安装任何其他用户发布到 npm 的 Prisma Client 扩展。为此,请运行以下命令

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 Client 操作的不同方法

对于 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> 约定,以便更容易查找和安装。

从打包的扩展中调用客户端级方法

警告

当前,对于引用 PrismaClient 并调用客户端级方法(如以下示例所示)的扩展存在限制。

如果您从 事务(交互式或批处理)内部触发扩展,则扩展代码将在新的连接中发出查询,并忽略当前事务上下文。

在 GitHub 上的此问题中了解更多信息: 需要使用客户端级方法的客户端扩展会静默忽略事务

在以下情况下,您需要引用扩展包装的 Prisma Client 实例

  • 当您想要在打包的扩展中使用 客户端级方法(例如 $queryRaw)时。
  • 当您想要在打包的扩展中链接多个 $extends 调用时。

但是,当有人将其项目包含在他们的项目中时,您的代码无法知道 Prisma Client 实例的详细信息。

您可以按如下方式引用此客户端实例

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]
},
},
},
})
})

高级类型安全:用于定义泛型扩展的类型实用程序

您可以使用 类型实用程序 提高共享扩展的类型安全性。