SKILL.md
唯讀
名稱
graphql-schema
描述
遵循業界最佳實務設計 GraphQL Schema 的指南。使用此技能時機:(1) 設計新的 GraphQL Schema 或 API,(2) 檢視現有 Schema 以尋求改進,(3) 決定型別結構或可空性,(4) 實作分頁或錯誤模式,(5) 確保 Schema 設計的安全性。
GraphQL Schema 設計指南
本指南涵蓋設計直觀、高效且易於維護的 GraphQL Schema 的最佳實務。Schema 設計主要是伺服器端的事項,但會直接影響 API 的可用性。
Schema 設計原則
1. 為客戶端需求設計
- 思考客戶端會撰寫哪些查詢
- 根據使用案例而非資料庫表格來組織型別
- 暴露能力,而非實作細節
2. 明確表達
- 使用清晰、描述性的名稱
- 有意識地決定可空性
- 使用描述文件來說明
3. 為演進設計
- 規劃向後相容性
- 在移除前先使用棄用標記
- 避免破壞性變更
快速參考
型別定義語法
"""
系統中的使用者。
"""
type User {
id: ID!
email: String!
name: String
posts(first: Int = 10, after: String): PostConnection!
createdAt: DateTime!
}
可空性規則
| 模式 | 意義 |
|---|---|
| String | 可空 - 可能為 null |
| String! | 非空 - 永遠有值 |
| [String] | 可空列表,可空項目 |
| [String!] | 可空列表,非空項目 |
| [String]! | 非空列表,可空項目 |
| [String!]! | 非空列表,非空項目 |
最佳實務: 對列表使用 [Type!]! - 空列表優於 null,且無 null 項目。
輸入與輸出型別
# 輸出型別 - 客戶端收到的內容
type User {
id: ID!
email: String!
createdAt: DateTime!
}
# 輸入型別 - 客戶端傳送的內容
input CreateUserInput {
email: String!
name: String
}
# 使用輸入型別的 Mutation
type Mutation {
createUser(input: CreateUserInput!): User!
}
介面模式
interface Node {
id: ID!
}
type User implements Node {
id: ID!
email: String!
}
type Post implements Node {
id: ID!
title: String!
}
聯合模式
union SearchResult = User | Post | Comment
type Query {
search(query: String!): [SearchResult!]!
}
參考文件
特定主題的詳細文件:
- 型別 - 型別設計模式、介面、聯合與自訂標量
- 命名 - 型別、欄位與引數的命名慣例
- 分頁 - Connection 模式與基於游標的分頁
- 錯誤 - 錯誤建模與結果型別
- 安全性 - Schema 設計的安全性最佳實務
關鍵規則
型別設計
- 根據領域概念而非資料儲存來定義型別
- 對跨型別的共用欄位使用介面
- 對互斥的型別使用聯合
- 保持型別專注(單一職責)
- 避免深層巢狀 - 盡可能扁平化
欄位設計
- 欄位應從客戶端角度命名
- 回傳最具體的型別
- 對昂貴的欄位明確標示(考慮使用引數)
- 使用引數進行篩選、排序、分頁
Mutation 設計
- 使用單一輸入引數模式:
mutation(input: InputType!) - 在 Mutation 回應中回傳受影響的物件
- 圍繞業務操作而非 CRUD 建模 Mutation
- 考慮回傳成功/錯誤型別的聯合
ID 策略
- 盡可能使用全域唯一 ID
- 實作
Node介面以支援重新擷取 - 必要時對複合 ID 進行 Base64 編碼
基本規則
- 務必為型別和欄位加上描述
- 對不能為 null 的欄位務必使用非空(!)
- 對列表務必使用 [Type!]! 模式
- 絕不在 Schema 中暴露資料庫內部細節
- 絕不破壞向後相容性而不先棄用
- 偏好使用專用輸入型別而非大量引數
- 對固定值偏好使用列舉而非任意字串
- 對識別碼使用
ID型別,而非String或Int - 對領域特定值(DateTime、Email、URL)使用自訂標量






