命名規則
-
Query
- getXXX
- getXXXs [複数形]
-
Mutation
- 動詞 + 名詞
- addXXX, createXXX。Github は db 操作のような insertXXX は使っていない。あくまでビジネス処理としての言葉を使っている。delete と remove は両方使っている。
- 引数
- [Mutation]Input. ex.) AddProjectInput
- 返り値
- [Mutation]Payload. ex.) AddProjectPayload
Connection
GitHubのGraphQL APIでは、Connectionを使用して、リレーションシップやページネーションを表現します。Connectionは、次のような要素で構成されています。
- Edges: コレクション内の個々の要素を表すオブジェクト。通常、データの実際のレコードまたはエンティティです。
- Node: Edge内のデータを表現するためのフィールド。これは通常、エッジに関連する実際のデータのプロパティやフィールドです。
- Cursor: Edgeを識別するための一意の識別子。通常はデータの一意の識別子やキーです。
- Page Info: クエリのページネーション情報を提供するためのメタ情報。通常、クエリの結果セットに関する追加の情報(例:次のページがあるかどうか、カーソルの位置など)を提供します。
GitHubのGraphQL APIでは、Connectionを定義する際にこれらの要素が使用されます。たとえば、GitHubのリポジトリやイシューをクエリする場合、Connectionを使用して結果がページネーションされ、エッジごとに個々のデータが提供されます。
type Query {
repositories(first: Int, after: String): RepositoryConnection!
}
type RepositoryConnection {
edges: [RepositoryEdge!]!
pageInfo: PageInfo!
}
type RepositoryEdge {
cursor: String!
node: Repository!
}
type Repository {
id: ID!
name: String!
description: String
}
Tips
-
Query には極力 Object を渡さない
- Github ではやっていない。
このへんが辛い
- フロント側的には input でまとめなくても variables でまとまる
- 引数を明示的に指定するのは 2-3 がほとんどであまり多くならない
- デフォルト値の指定が活用できずつらい
Node
ID を使った Get や List は Interface を実装した node(id (ID!)), nodes(ids ([ID!]!)) のような形で定義しておくと個々の Object ごとに XXXByID のようなメソッドを生やさなくて済む。Github ではこの手段をとっている。
type Query {
node(id: ID!): Node
}
interface Node {
id: ID!
}
type User implements Node {
id: ID!
name: String
}
クライアントは fragment を使って指定する
query {
node(id: "User:1") {
id
... on User {
name
email
}
}
}
Todo: この辺サーバの実装はどうなるんだろうか。switch して分けるしかない。。?type で判定してやるぽい。
directive
GraphQLのディレクティブは、クエリやスキーマ定義に対してメタデータや動作を追加するための機能です。ディレクティブは@で始まり、フィールドやフラグメント、変数定義などに適用することができます。
ディレクティブはGraphQLスキーマの柔軟性と拡張性を高めるために使用されます。
directive @directiveName(
argumentName: Type,
...
) on
| SCHEMA
| SCALAR
...
ここで、各要素は以下の意味を持ちます。
- @directiveName: ディレクティブの名前
- argumentName: Type: ディレクティブが受け取る引数の定義
- on: ディレクティブが適用可能な場所を指定する
具体的な例
directive @hide(if: Boolean!) on FIELD_DEFINITION
type User {
id: ID!
name: String!
email: String! @hide(if: true)
age: Int!
}
利用方法
query($hideEmail: Boolean!) {
user(id: "1") {
id
name
email @hide(if: $hideEmail)
age
}
}