跳到主要内容

共享 Prisma Client 扩展

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

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

要探索 Prisma 官方 Client 扩展以及社区创建的扩展示例,请访问页面。

安装共享的、打包的扩展

在您的项目中,您可以安装其他用户发布到 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]
},
},
},
})
})

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

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