2022 年 12 月 19 日

Prisma Client 變得更靈活了:Prisma Client 擴充功能 (預覽版)

Prisma Client 擴充功能 (預覽版) 實現了許多新的使用案例。本文將探討您可以使用擴充功能為 Prisma Client 新增自訂功能的各種方式。

Prisma Client Just Became a Lot More Flexible: Prisma Client Extensions (Preview)

目錄

簡介

Prisma Client 擴充功能提供了一種強大的新方法,可以類型安全的方式為 Prisma 新增功能。透過它們,您將能夠為 ORM (尚未) 原生支援的問題建立簡單、靈活的解決方案。您可以使用 TypeScript 或 JavaScript 定義擴充功能、組合它們,甚至建立具有不同擴充功能的多個輕量級 Prisma Client 實例。

當您準備好時,您可以將您的擴充功能作為程式碼片段與社群分享,或將它們打包並發佈到 npm。本文將向您展示擴充功能的可能性,並希望能激發您創建和分享自己的擴充功能!

注意: 我們相信 Prisma Client 擴充功能將為使用 Prisma 開啟許多新的可能性。但是,僅僅因為一個問題可以透過擴充功能解決,並不意味著它永遠不會透過第一級功能來解決。我們的目標之一是在將解決方案原生整合到 Prisma 之前,與我們的社群一起實驗和探索解決方案。

使用 Prisma Client 擴充功能

若要使用 Prisma Client 擴充功能,您需要先在您的 Prisma 結構描述檔案中啟用 clientExtensions 預覽功能

然後,您可以對 Prisma Client 實例呼叫 $extends 方法。這將傳回一個新的「擴充」用戶端實例,而不會修改原始實例。您可以鏈式呼叫 $extends 以使用多個擴充功能,並建立具有不同擴充功能的獨立實例

擴充功能的組成部分

擴充功能中可以包含四種不同類型的組件

  • 模型 組件允許您將新方法新增至模型。這是一種方便的方式,可以在預設方法 (如 findManycreate 等) 旁邊新增新的操作。您可以將其用作常用查詢方法的儲存庫、封裝模型的業務邏輯,或執行您可能在類別上的靜態方法中執行的任何操作。
  • 用戶端 組件可用於將新的頂層方法新增至 Prisma Client 本身。使用此功能擴充用戶端的功能,該功能不與特定模型相關聯。
  • 查詢 組件可讓您掛鉤到查詢生命週期並執行副作用、修改查詢引數或以類型安全的方式變更結果。這些是 middleware 的替代方案,它們提供完全的類型安全性,並且可以特別應用於不同的擴充用戶端實例。
  • 結果 組件將自訂欄位和方法新增至查詢結果物件。這些允許您實作虛擬/計算欄位、在單一位置定義模型實例的業務邏輯,以及轉換查詢傳回的資料。

單個擴充功能可以包含一個或多個組件,以及一個可選名稱以顯示在錯誤訊息中

若要查看定義每種類型擴充功能組件的完整語法,請參閱 文件

分享擴充功能

您可以使用 Prisma.defineExtension 公用程式來定義可以與其他使用者分享的擴充功能

當將共用擴充功能發佈到 npm 時,我們建議使用 prisma-extension-<package-name> 慣例。這將使使用者更容易在其應用程式中尋找和安裝您的擴充功能。

例如,如果您使用套件名稱 prisma-extension-find-or-create 發佈擴充功能,使用者可以像這樣安裝它

然後在其應用程式中使用擴充功能

閱讀 我們關於分享擴充功能的文件 以取得更多詳細資訊。

範例使用案例

我們編譯了一個可以使用擴充功能解決的使用案例清單,並且我們建立了一些關於如何編寫這些擴充功能的範例。讓我們來看看這些使用案例及其實作

注意:Prisma Client 擴充功能仍處於 預覽 階段,以下某些範例可能有一些限制。在已知的情況下,注意事項列在 GitHub 上的範例 README 檔案中。

範例:計算欄位

在 GitHub 上查看完整範例

此範例示範如何建立 Prisma Client 擴充功能,該功能將虛擬/計算欄位新增至 Prisma 模型。這些欄位未包含在資料庫中,而是在執行時計算。

計算欄位是類型安全的,並且可能會傳回從簡單值到複雜物件,甚至是可用作模型實例方法的功能的任何內容。計算欄位必須指定它們依賴的其他欄位,並且它們可以由其他計算欄位組成/重複使用。

範例:轉換欄位

在 GitHub 上查看完整範例

此範例示範如何使用 Prisma Client 擴充功能來轉換 Prisma 查詢傳回的結果中的欄位。在此範例中,date 欄位會轉換為特定地區設定的相對字串。

這展示了一種在應用程式的資料存取層實作國際化 (i18n) 的方法。但是,此技術可以讓您實作對查詢結果中的欄位進行任何種類的自訂轉換或序列化/還原序列化。

範例:混淆欄位

在 GitHub 上查看完整範例

此範例是先前 轉換欄位 範例的特殊情況。它使用擴充功能來隱藏 User 模型上的敏感 password 欄位。password 資料行未包含在基礎 SQL 查詢中的選定資料行中,並且當在使用者結果物件上存取時,它將解析為 undefined。它也可能解析為任何其他值,例如混淆字串 (如 "********")。

範例:實例方法

在 GitHub 上查看完整範例

此範例示範如何將類似 Active Record 的介面新增至 Prisma 結果物件。它使用 result 擴充功能將 savedelete 方法直接新增至 Prisma Client 方法傳回的 User 模型物件。

此技術可用於使用行為自訂 Prisma 結果物件,類似於將實例方法新增至模型類別。

範例:靜態方法

在 GitHub 上查看完整範例

此範例示範如何建立 Prisma Client 擴充功能,該功能將 signUp()findManyByDomain() 方法新增至 User 模型。

此技術可用於抽象化常用查詢/操作的邏輯、建立類似儲存庫的介面,或執行您可能使用靜態類別方法執行的任何操作。

範例:模型篩選器

在 GitHub 上查看完整範例

此範例示範一個 Prisma Client 擴充功能,該功能為模型新增可重複使用的篩選器,這些篩選器可以組成並傳遞至查詢的 where 條件。複雜、常用的篩選條件可以編寫一次,並透過擴充的 Prisma Client 實例在許多查詢中存取。

範例:唯讀用戶端

在 GitHub 上查看完整範例

此範例建立一個僅允許讀取操作 (如 findManycount),而不允許寫入操作 (如 createupdate) 的用戶端。呼叫寫入操作將在執行時以及使用 TypeScript 在編譯時產生錯誤。

範例:輸入轉換

在 GitHub 上查看完整範例

此範例建立一個擴充的用戶端實例,該實例修改查詢引數以僅包含 published 的貼文。

由於 query 擴充功能允許修改查詢引數,因此可以使用此方法套用各種預設篩選器。

範例:輸入驗證

在 GitHub 上查看完整範例

此範例使用 Prisma Client 擴充功能,在建立和更新資料庫物件時執行自訂執行階段驗證。它使用 Zod 執行階段結構描述來檢查傳遞給 Prisma 寫入方法的資料是否有效。

這可以用於清理使用者輸入,或拒絕不符合您的業務邏輯規則定義的某些條件的變更。

範例:JSON 欄位類型

在 GitHub 上查看完整範例

下一個範例結合了 輸入驗證轉換欄位 範例中顯示的方法,為 Json 欄位提供靜態和執行階段類型。它使用 Zod 來剖析欄位資料並推斷靜態 TypeScript 類型。

此範例包含具有 JSON 設定檔欄位的 User 模型,該欄位具有稀疏結構,可能因使用者而異。擴充功能包含兩個部分

  • 一個 result 擴充功能,新增了計算的 profile 欄位。此欄位使用 Profile Zod 結構描述來剖析基礎非類型化的 profile 欄位。TypeScript 從剖析器推斷靜態資料類型,因此查詢結果同時具有靜態和執行階段類型安全性。
  • 一個 query 擴充功能,用於剖析 User 模型的寫入方法 (如 createupdate) 的輸入資料上的 profile 欄位。

範例:查詢記錄

在 GitHub 上查看完整範例

此範例示範如何使用 Prisma Client 擴充功能來執行類似於 middleware 的任務。在此範例中,query 擴充功能會追蹤完成每個查詢所需的時間,並記錄結果以及查詢和引數本身。

此技術可用於執行一般記錄、發出事件、追蹤使用情況等。

注意:您可能對 OpenTelemetry 追蹤Metrics 功能 (均為預覽版) 感興趣,它們提供有關效能以及 Prisma 如何與資料庫互動的詳細見解。

範例:重試交易

在 GitHub 上查看完整範例

此範例示範如何使用 Prisma Client 擴充功能來自動重試因寫入衝突/死鎖逾時而失敗的交易。失敗的交易將使用 指數退避和抖動 進行重試,以減少高流量下的爭用。

範例:無回呼互動式交易

在 GitHub 上查看完整範例

此範例示範一個 Prisma Client 擴充功能,該功能為啟動 互動式交易 新增了一個新的 API,無需回呼。

這使您擁有 互動式交易 (例如讀取-修改-寫入循環) 的全部功能,但在更命令式的 API 中。在某些情況下,這可能比互動式交易的正常回呼樣式 API 更方便。

範例:稽核日誌內容

在 GitHub 上查看完整範例

此範例示範如何使用 Prisma Client 擴充功能來提供目前應用程式使用者的 ID 作為 Postgres 中稽核日誌觸發程序的內容。使用者 ID 包含在稽核追蹤中,追蹤表格中資料列的每次變更。

有關此解決方案的詳細說明,請參閱 GitHub 上範例的 README

範例:資料列層級安全性

在 GitHub 上查看完整範例

此範例示範如何使用 Prisma Client 擴充功能,在使用 Postgres 中的資料列層級安全性 (RLS) 的多租戶應用程式中隔離租戶之間的資料。

有關此解決方案的詳細說明,請參閱 GitHub 上範例的 README

告訴我們您的想法

我們希望您和我們一樣對 Prisma Client 擴充功能創造的可能性感到興奮!

💡 您可以在 此 GitHub issue 中與我們分享您的意見回饋。

不要錯過下一篇文章!

註冊 Prisma 電子報