2019 年 2 月 12 日

將 GraphQL Nexus 與資料庫搭配使用

GraphQL Nexus 是一個程式碼優先、型別安全的 GraphQL 結構描述建構函式庫,適用於 JavaScript/TypeScript。了解如何使用 Prisma client 和新的 nexus-prisma 外掛程式將其連接到資料庫。

Using GraphQL Nexus with a Database

⚠️ 本文已過時,因為它與 Prisma 1 相關,而 Prisma 1 現在已棄用。若要深入了解最新版本的 Prisma,請閱讀文件。 ⚠️

重點回顧:使用 GraphQL Nexus 進行程式碼優先開發

在上一篇文章中,我們介紹了 GraphQL Nexus,這是一個 GraphQL 函式庫,可為 TypeScript 和 JavaScript 啟用程式碼優先開發。透過 Nexus,GraphQL 結構描述是以程式化方式定義和實作。因此,它遵循其他語言中 GraphQL 伺服器的成熟方法,例如 sangria-graphql (Scala)、graphlq-rubygraphene (Python)。

今天的文章是關於將基於 Nexus 的 GraphQL 伺服器連接到資料庫,使用 Prisma client 以及新的 nexus-prisma 外掛程式。稍後我們將逐步引導您從頭開始建構部落格應用程式的 GraphQL API 的實際範例。

nexus-prisma 可與 PostgreSQL、MySQL 和 MongoDB 搭配使用。在此尋找其文件


TLDR:nexus-prisma 外掛程式的優點

  • GraphQL 中 Prisma 模型的 CRUD 運算
  • 自訂您的 Prisma 模型,例如隱藏特定欄位新增計算欄位
  • 完全型別安全:GraphQL 結構描述和資料庫的一致類型集
  • 與 GraphQL 生態系統相容 (例如 apollo-servergraphql-yoga 等)

了解 nexus-prisma 工作流程

Prisma client 作為 ORM 替代方案

如果您之前未使用過 Prisma,以下是其運作方式的快速概述

  1. 定義您的資料模型或讓 Prisma 自行檢視您現有的資料庫
  2. 產生您的 Prisma client,即型別安全的資料庫用戶端
  3. 在應用程式 (例如 GraphQL API) 中使用 Prisma client 存取您的資料庫

nexus-prisma 外掛程式的幕後運作

nexus-prisma 新增至組合時,還有另一個步驟:叫用 nexus-prisma-generate codegen CLI。它會為您的 Prisma 模型產生完整 GraphQL CRUD API 的建構區塊,例如,對於 User 模型,它包含

  • 查詢
    • user(...):User!:擷取單一記錄
    • users(...):[User!]!:擷取記錄清單
    • usersConnection(...):UserConnection!Relay 連線和彙總
  • 突變
    • createUser(...):User!:建立新記錄
    • updateUser(...):User:更新記錄
    • deleteUser(...):User:刪除記錄
    • updatesManyUsers(...):BatchPayload!:大量更新多個記錄
    • deleteManyUsers(...):BatchPayload!:大量刪除多個記錄
  • GraphQL 輸入類型
    • UserCreateInput:包裝記錄的所有欄位
    • UserUpdateInput:包裝記錄的所有欄位
    • UserWhereInput:為記錄的所有欄位提供篩選器
    • UserWhereUniqueInput:為記錄的唯一欄位提供篩選器
    • UserUpdateManyMutationInput:包裝可批量更新的欄位
    • UserOrderByInput:指定依欄位升序或降序排序

UserCreateInputUserUpdateInput 在處理關係欄位的方式上有所不同。

當您使用 nexusnexus-prisma 撰寫 GraphQL 伺服器程式碼時,您可以透過公開和自訂這些運算來滿足您自己的 API 需求

Writing GraphQL server code with nexus and nexus-prisma

產生 CRUD 建構區塊後,您可以使用 nexus-prisma 中的 prismaObjectType 開始公開 (和自訂) 它們。以下程式碼片段描述了一個實作,該實作提供基於 Prisma 和 nexus-prisma 的 TODO 清單應用程式的 GraphQL API

我們將 prismaObjectType 應用於 QueryMutation。對於 Query,我們保留所有欄位 (即 todotodoestodoesConnection)。對於 Mutation,我們使用 prismaFields 自訂公開的運算。

prismaFields 可讓我們選取要公開的運算。在本例中,我們只想保留建立模型 (createTodo) 的運算。從產生的 CRUD 建構區塊中,我們既不包含 updateTodo 也不包含 deleteTodo,而是實作我們自己的 markAsDone(id: ID!) 突變,該突變會勾選特定的 Todo


範例:從標準 CRUD 到自訂 GraphQL API

現在讓我們快速瀏覽一個標準 Prisma 用例,看看如何在幾個簡單的步驟中快速建構部落格應用程式的 GraphQL API。以下是我們要執行的操作

  1. 使用 TypeScript 設定 Prisma 專案 (使用免費示範資料庫)
  2. 定義模型、遷移資料庫並產生 Prisma client
  3. 透過 nexus-prisma 公開完整 CRUD GraphQL API
  4. 透過 nexus-prisma 自訂 GraphQL API

如果您想跟著操作,則需要安裝 Prisma CLI

1) 使用 TypeScript、nexusnexus-prisma 設定 Prisma 專案

本節主要處理您的專案設定。如果您不想跟著編碼,可以隨時跳過它,否則請展開以下章節。

使用 Prisma CLI 建立簡單的 Prisma 專案

在互動式提示中,選取以下選項

  1. 選取示範伺服器 (包含 Prisma Cloud 中免費和託管的示範資料庫)
  2. 在瀏覽器中使用 Prisma Cloud 驗證 (如有必要)
  3. 返回終端機,確認所有建議的值

作為示範伺服器的替代方案,您也可以使用 Docker 在本機執行 Prisma

接下來,您需要設定 nexus-prisma 工作流程。新增以下相依性 (在 myblog 目錄內)

接下來,將以下兩行新增到 prisma.yml 的末尾

這可確保在您變更模型時,Prisma client 以及產生的 nexus-prisma CRUD 建構區塊都會更新。

由於我們使用 TypeScript,因此讓我們快速新增 tsconfig.json

最後,繼續新增您將用於開發的 start 指令碼。它會啟動開發伺服器,該伺服器會在背景監看您的檔案,並在您編碼時更新產生的 SDL 和 Nexus 型別。將此新增到您的 package.json

2) 定義模型、遷移資料庫和產生 Prisma client

prisma init 命令在 datamodel.prisma 中建立預設 User 模型。由於我們正在建構部落格應用程式,因此讓我們將模型調整為我們的應用程式網域

接下來,您需要透過將資料模型應用於資料庫來遷移資料庫。使用以下命令,在 datamodel.prisma 中定義的每個模型都將對應到基礎資料庫中的資料表

由於您先前在 prisma.yml 中設定了 post-deploy 勾點,因此您的 Prisma client 和 CRUD 建構區塊會自動更新。

3) 透過 nexus-prisma 公開完整 CRUD GraphQL API

在專案的早期階段,通常有助於讓 API 公開完整 CRUD 功能 - 更受限制的 API 需求通常會隨著時間推移而出現。nexus-prisma 透過提供從完整 CRUD 到自訂 API 運算的直接路徑來完美地解決這個問題。

讓我們從公開針對已定義模型的完整 CRUD 的 GraphQL API 開始 (請注意,這包括篩選器、分頁和排序)。建立一個名為 index.ts 的新檔案,並將以下程式碼新增到其中

在本簡短教學課程中,我們並未過多關注檔案結構。請查看我們的 graphql-auth 範例,以取得適當的設定和模組化結構描述。

執行 npm run start 後,您可以在 https://127.0.0.1:4000 上開啟 GraphQL 伺服器的 GraphQL Playground。透過您在上面撰寫的少量程式碼,您已經可以使用完整的 GraphQL CRUD API。

範例查詢

範例突變

它是如何運作的?nexus-prisma-generate 產生了一個 GraphQL 結構描述,該結構描述為 Prisma 模型 (您的CRUD 建構區塊) 提供 CRUD API。此 GraphQL 結構描述遵循 OpenCRUD 規格。使用 prismaObjectType 函數,您現在可以公開和自訂該結構描述的運算。

prismaObjectTypeprismaFields 使用白名單方法,這表示您需要明確列出要公開的欄位。萬用字元運算子 * 包含所有欄位。

Expose full CRUD GraphQL API via nexus-prisma

4) 透過 nexus-prisma 自訂 GraphQL API

在本節中,我們將了解如何自訂 nexus-prisma 中的 CRUD GraphQL API。具體來說,我們將要

  1. User 模型中隱藏欄位
  2. 將計算欄位新增到 Post 模型
  3. 隱藏 createPostupdatePost 突變
  4. 新增兩個自訂 createDraftpublish 突變

4.1) 從 User 模型中隱藏欄位

在本節中,我們將從 User 模型中隱藏 email 欄位。

若要自訂模型,我們需要將 prismaObjectType 函數應用於模型,並將 definition(t) 函數作為選項傳遞

透過在模型 t 上呼叫 prismaFields,我們可以自訂公開的欄位 (及其引數)。由於 email 未包含在清單中,因此它會從我們的 GraphQL API 中移除。

Hide a field from the User model

若要套用變更,您需要明確地將 User 傳遞到 makePrismaSchema 內的 types 陣列

請注意,您的編輯器能夠根據產生的 CRUD 建構區塊建議要傳遞到 prismaObjectTypeprismaFields 中的內容。這表示當您輸入 prismaObjectType('') 並按下 ctrl+space 時,它會建議所有產生的 CRUD 建構區塊的名稱。當呼叫 t.prismaFields(['']) 時,它會建議 t 的欄位

4.2) 將計算欄位新增到 Post 模型

使用 nexus-prisma 的新程式碼優先方法也讓將計算欄位新增到 Prisma 模型變得容易。假設您想要將欄位新增到 Post,該欄位始終傳回完全大寫的 title。以下是如何實作它

我們使用來自 graphql-nexust.string(...) API 將新欄位新增到我們的模型。由於它是計算欄位 (因此無法由 nexus-prisma 自動解析),因此我們也需要將解析器附加到它。

Customize the GraphQL API via nexus-prisma

與之前一樣,您需要明確地將自訂的 Post 模型新增到 types 陣列

4.3) 隱藏 createPostupdatePost 突變

以我們從 User 模型中隱藏 email 欄位的相同方式,我們也可以從屬於產生的 nexus-prisma CRUD 建構區塊的 Query/Mutation 類型中隱藏運算。

若要隱藏 createPostupdatePost,我們再次需要將 definition(t) 作為選項傳遞給 prismaObjectType。請注意,一旦我們在類型上呼叫 prismaFields,我們就需要明確列出我們要保留的所有欄位 (空陣列將被解讀為「不保留任何運算」)

產生的 CRUD GraphQL API 也包含批次和 upsert 運算,為簡潔起見,我們在此處將其排除。

4. 新增兩個自訂 createDraftpublish 突變

最後,我們將兩個自訂突變新增到我們的 GraphQL API。以下是它們的 SDL 定義的樣子

若要實作這些突變,您需要將兩個欄位 (透過從 nexus API 呼叫 t.field( ... )) 新增到 Mutation 類型

請務必從 nexus 套件匯入 stringArgidArg,以使此操作生效。

GraphQL Nexus 也會產生 GraphQL 結構描述的 SDL 版本,您可以在 ./generated/schema.graphql 中找到它。我們的 GraphQL API 的最終版本如下所示


從我們的程式碼優先 GraphQL 文章中獲得 3 個主要重點

這是我們關於程式碼優先 GraphQL 伺服器開發系列文章的最後一部分。

GraphQL Nexusnexus-prisma 外掛程式實作了我們從作為 GraphQL 生態系統的活躍貢獻者超過兩年所收集的經驗。在發現 SDL 優先方法存在太多問題後,我們對目前正在興起的新程式碼優先工具感到非常興奮。

我們堅信 GraphQL Nexus (和其他程式碼優先方法,例如 TypeGraphQL) 將徹底改變未來建構 GraphQL 結構描述的方式。

以下是我們從本系列中獲得的主要重點

  1. 程式碼優先方法可讓您以符合語言習慣的方式建構 GraphQL 伺服器,而無需額外的工具 («您唯一需要的工具是您的程式設計語言»),同時保留 SDL 作為通訊工具的優點。
  2. GraphQL Nexus 讓開發人員可以使用彈性且型別安全的 API 建構其結構描述。由於自動完成和建置時錯誤檢查,開發人員獲得絕佳的體驗。
  3. nexus-prisma 外掛程式建構於 Prisma 模型之上,讓開發人員可以透過公開和自訂自動產生的 CRUD 建構區塊來建構 GraphQL API。

立即試用 nexus-prisma 🙌

您有多種方法可以試用 nexus-prisma。您可以依照文件中的開始使用章節,或瀏覽我們的TypeScript GraphQL 範例

請透過開啟 GitHub 問題或在我們的 Slack 中聯絡我們,分享您的意見反應。


非常感謝我們的開放原始碼工程師 Flavian Desvernenexus-prisma 外掛程式上所做的出色工作 💪✨

不要錯過下一篇文章!

訂閱 Prisma 電子報