跳到主要內容

擴充套件

資訊

Prisma Client 擴充套件在 4.16.0 及更高版本中已正式釋出。它們在 4.7.0 版本中作為預覽功能引入。如果你的版本低於 4.16.0,請確保啟用 clientExtensions 預覽功能標誌。

你可以使用 Prisma Client 擴充套件為你的模型、結果物件和查詢新增功能,或新增客戶端級別的方法。

你可以使用以下一種或多種元件型別建立擴充套件

例如,你可以建立一個使用 modelclient 元件型別的擴充套件。

關於 Prisma Client 擴充套件

當你使用 Prisma Client 擴充套件時,你會建立一個擴充套件客戶端。擴充套件客戶端是標準 Prisma Client 的輕量級變體,由一個或多個擴充套件包裝。標準客戶端不會被修改。你可以在專案中新增任意數量的擴充套件客戶端。瞭解更多關於擴充套件客戶端的資訊

你可以將單個擴充套件或多個擴充套件與擴充套件客戶端關聯。瞭解更多關於多個擴充套件的資訊

你可以與其它 Prisma ORM 使用者共享你的 Prisma Client 擴充套件,也可以將其它使用者開發的 Prisma Client 擴充套件匯入到你的 Prisma ORM 專案中。

擴充套件客戶端

擴充套件客戶端之間以及與標準客戶端的互動方式如下

  • 每個擴充套件客戶端都在一個獨立的例項中獨立執行。
  • 擴充套件客戶端之間以及與標準客戶端不會發生衝突。
  • 所有擴充套件客戶端和標準客戶端都與同一個Prisma ORM 查詢引擎通訊。
  • 所有擴充套件客戶端和標準客戶端共享同一個連線池。

注意:擴充套件的作者可以修改此行為,因為他們能夠作為擴充套件的一部分執行任意程式碼。例如,一個擴充套件實際上可能會建立一個全新的 PrismaClient 例項(包括其自己的查詢引擎和連線池)。請務必查閱你所使用的擴充套件的文件,瞭解它可能實現的任何特定行為。

擴充套件客戶端的示例用例

由於擴充套件客戶端在獨立的例項中執行,因此它們是完成以下任務的好方法,例如

  • 實現行級安全 (RLS),其中每個 HTTP 請求都有自己的客戶端及其 RLS 擴充套件,並使用會話資料進行自定義。這可以使每個使用者完全分離,每個使用者都在一個單獨的客戶端中。
  • User 模型新增 user.current() 方法以獲取當前登入使用者。
  • 如果設定了除錯 cookie,則為請求啟用更詳細的日誌記錄。
  • 為所有日誌附加唯一的請求 ID,以便你以後可以關聯它們,例如幫助你分析 Prisma Client 執行的操作。
  • 從模型中移除 delete 方法,除非應用程式呼叫管理員端點且使用者具有必要的許可權。

向 Prisma Client 新增擴充套件

你可以透過兩種主要方式建立擴充套件

  • 使用客戶端級別的 $extends 方法

    const prisma = new PrismaClient().$extends({
    name: 'signUp', // Optional: name appears in error logs
    model: { // This is a `model` component
    user: { ... } // The extension logic for the `user` model goes inside the curly braces
    },
    })
  • 使用 Prisma.defineExtension 方法定義擴充套件並將其賦值給變數,然後將該擴充套件傳遞給客戶端級別的 $extends 方法

    import { Prisma } from '@prisma/client'

    // Define the extension
    const myExtension = Prisma.defineExtension({
    name: 'signUp', // Optional: name appears in error logs
    model: { // This is a `model` component
    user: { ... } // The extension logic for the `user` model goes inside the curly braces
    },
    })

    // Pass the extension to a Prisma Client instance
    const prisma = new PrismaClient().$extends(myExtension)
    提示

    當你想將擴充套件分離到專案中的多個檔案或目錄時,此模式很有用。

以上示例使用 model 擴充套件元件來擴充套件 User 模型。

在你的 $extends 方法中,使用適當的擴充套件元件(modelclientresultquery)。

為錯誤日誌命名擴充套件

你可以為擴充套件命名,以便在錯誤日誌中識別它們。為此,請使用可選欄位 name。例如

const prisma = new PrismaClient().$extends({
name: `signUp`, // (Optional) Extension name
model: {
user: { ... }
},
})

多個擴充套件

你可以透過兩種方式將擴充套件與擴充套件客戶端關聯

  • 你可以將其單獨與一個擴充套件客戶端關聯,或者
  • 你可以將此擴充套件與其他擴充套件結合,並將所有這些擴充套件與一個擴充套件客戶端關聯。這些組合擴充套件的功能適用於同一個擴充套件客戶端。注意:組合擴充套件可能會衝突

你可以結合上述兩種方法。例如,你可以將一個擴充套件與其自己的擴充套件客戶端關聯,並將另外兩個擴充套件與另一個擴充套件客戶端關聯。瞭解更多關於客戶端例項如何互動的資訊

將多個擴充套件應用於擴充套件客戶端

在以下示例中,假設你有兩個擴充套件,extensionAextensionB。有兩種方法可以組合它們。

選項 1:在一行中宣告新客戶端

使用此選項,你可以在一行程式碼中將兩個擴充套件應用於新客戶端。

// First of all, store your original Prisma Client in a variable as usual
const prisma = new PrismaClient()

// Declare an extended client that has an extensionA and extensionB
const prismaAB = prisma.$extends(extensionA).$extends(extensionB)

然後你可以在程式碼中引用 prismaAB,例如 prismaAB.myExtensionMethod()

選項 2:宣告多個擴充套件客戶端

此選項的優點是你可以單獨呼叫任何擴充套件客戶端。

// First of all, store your original Prisma Client in a variable as usual
const prisma = new PrismaClient()

// Declare an extended client that has extensionA applied
const prismaA = prisma.$extends(extensionA)

// Declare an extended client that has extensionB applied
const prismaB = prisma.$extends(extensionB)

// Declare an extended client that is a combination of clientA and clientB
const prismaAB = prismaA.$extends(extensionB)

在你的程式碼中,你可以單獨呼叫這些客戶端中的任何一個,例如 prismaA.myExtensionMethod()prismaB.myExtensionMethod()prismaAB.myExtensionMethod()

組合擴充套件中的衝突

當你將兩個或更多擴充套件組合到一個擴充套件客戶端中時,你宣告的最後一個擴充套件在任何衝突中都具有優先權。在上面選項 1 的示例中,假設 extensionA 中定義了一個名為 myExtensionMethod() 的方法,並且 extensionB 中也定義了一個名為 myExtensionMethod() 的方法。當你呼叫 prismaAB.myExtensionMethod() 時,Prisma Client 將使用 extensionB 中定義的 myExtensionMethod()

擴充套件客戶端的型別

你可以使用 typeof 工具推斷擴充套件 Prisma Client 例項的型別,如下所示

const extendedPrismaClient = new PrismaClient().$extends({
/** extension */
})

type ExtendedPrismaClient = typeof extendedPrismaClient

如果你將 Prisma Client 用作單例,你可以使用 typeofReturnType 工具獲取擴充套件 Prisma Client 例項的型別,如下所示

function getExtendedClient() {
return new PrismaClient().$extends({
/* extension */
})
}

type ExtendedPrismaClient = ReturnType<typeof getExtendedClient>

使用 Prisma.Result 擴充套件模型型別

你可以使用 Prisma.Result 型別工具擴充套件模型型別,以包含透過客戶端擴充套件新增的屬性。這允許你推斷擴充套件模型的型別,包括擴充套件屬性。

示例

以下示例演示瞭如何使用 Prisma.Result 擴充套件 User 模型型別,以包含透過客戶端擴充套件新增的 __typename 屬性。

import { PrismaClient, Prisma } from '@prisma/client'

const prisma = new PrismaClient().$extends({
result: {
user: {
__typename: {
needs: {},
compute() {
return 'User'
},
},
},
},
})

type ExtendedUser = Prisma.Result<typeof prisma.user, { select: { id: true } }, 'findFirstOrThrow'>

async function main() {
const user: ExtendedUser = await prisma.user.findFirstOrThrow({
select: {
id: true,
__typename: true,
},
})

console.log(user.__typename) // Output: 'User'
}

main()

Prisma.Result 型別工具用於推斷擴充套件 User 模型的型別,包括透過客戶端擴充套件新增的 __typename 屬性。

限制

$on$use 在擴充套件客戶端中的用法

$on$use 在擴充套件客戶端中不可用。如果你想繼續在擴充套件客戶端中使用這些客戶端級別方法,你需要先在擴充套件客戶端之前進行連線。

const prisma = new PrismaClient()

prisma.$use(async (params, next) => {
console.log('This is middleware!')
return next(params)
})

const xPrisma = prisma.$extends({
name: 'myExtension',
model: {
user: {
async signUp(email: string) {
await prisma.user.create({ data: { email } })
},
},
},
})

要了解更多資訊,請參閱我們關於 $on$use 的文件

客戶端級別方法在擴充套件客戶端中的用法

客戶端級別方法不一定存在於擴充套件客戶端上。對於這些客戶端,你需要在使用前先檢查其是否存在。

const xPrisma = new PrismaClient().$extends(...);

if (xPrisma.$connect) {
xPrisma.$connect()
}

與巢狀操作一起使用

query 擴充套件型別不支援巢狀讀寫操作。

© . This site is unofficial and not affiliated with Prisma Data, Inc.