APIのロジックに関する差異
GitHub には、REST API と GraphQL API という 2 つの API が用意されています。 GitHub の API について詳しくは、「GitHub の REST API と GraphQL API の比較」をご覧ください。
RESTからGraphQLへの移行は、APIロジックの大きな変化を示します。 スタイルとしての REST と仕様としての GraphQL との違いのために、REST API の呼び出しを GraphQL API のクエリに 1 対 1 で置き換えることは難しく、—しばしば望まない—結果になります。 移行の具体的な例を以下に示しました。
コードを REST API から GraphQL API に移行するには、以下を行います。
- GraphQL 仕様を確認する
- GitHub の GraphQL スキーマを確認する
- 現在のコードによるGitHub REST APIとのやりとりの考慮
- グローバル ノード ID を使用して API バージョン間でオブジェクトを参照する
GraphQLによる重要な利点には以下があります。
以下にそれぞれの例を示します。
例:必要なデータだけを取得
1つのREST API呼び出しで、Organizationのメンバーのリストを取得します。
curl -v https://api.github.com/orgs/:org/members
目的がメンバー名とアバターへのリンクの取得だけなのであれば、このRESTのペイロードには過剰なデータが含まれています。 しかし、GraphQLのクエリでは指定した内容だけが返されます。
query {
organization(login:"github") {
membersWithRole(first: 100) {
edges {
node {
name
avatarUrl
}
}
}
}
}
別の例を考えてみましょう。プルリクエストのリストを取得して、それぞれがマージ可能かをチェックします。 REST API を呼び出すと、pull request とその 概要表現の一覧が取得されます。
curl -v https://api.github.com/repos/:owner/:repo/pulls
pull request がマージ可能かを判断するには、個別にそれぞれの pull request の詳細な表現 (大きなペイロード) を取得し、その mergeable
属性が true か false かをチェックする必要があります。
curl -v https://api.github.com/repos/:owner/:repo/pulls/:number
GraphQL では、各 pull request の number
属性と mergeable
属性のみを取得できます。
query {
repository(owner:"octocat", name:"Hello-World") {
pullRequests(last: 10) {
edges {
node {
number
mergeable
}
}
}
}
}
例:入れ子
入れ子になったフィールドにクエリを行うことで、複数のRESTの呼び出しを少数のGraphQLクエリに置き換えられます。 たとえば、REST API を使って、コミット、非レビュー コメント、レビューと一緒に pull request を取得するには、4 つの別々の呼び出しが必要になります。
curl -v https://api.github.com/repos/:owner/:repo/pulls/:number
curl -v https://api.github.com/repos/:owner/:repo/pulls/:number/commits
curl -v https://api.github.com/repos/:owner/:repo/issues/:number/comments
curl -v https://api.github.com/repos/:owner/:repo/pulls/:number/reviews
GraphQL API を使えば、入れ子のフィールドを利用して単一のクエリでこのデータを取得できます。
{
repository(owner: "octocat", name: "Hello-World") {
pullRequest(number: 1) {
commits(first: 10) {
edges {
node {
commit {
oid
message
}
}
}
}
comments(first: 10) {
edges {
node {
body
author {
login
}
}
}
}
reviews(first: 10) {
edges {
node {
state
}
}
}
}
}
}
pull request 番号の 変数を置き換えることで、このクエリの機能を拡張することもできます。
例:強力な型付け
GraphQLスキーマは強く型付けされており、データの扱いが安全になっています。
GraphQL ミューテーションを使用して問題または pull request にコメントを追加し、clientMutationId
の値に文字列ではなく整数を誤って指定する例を考えてみましょう。
mutation {
addComment(input:{clientMutationId: 1234, subjectId: "MDA6SXNzdWUyMjcyMDA2MTT=", body: "Looks good to me!"}) {
clientMutationId
commentEdge {
node {
body
repository {
id
name
nameWithOwner
}
issue {
number
}
}
}
}
}
このクエリを実行すると、この操作に期待される型を指定したエラーが返されます。
{
"data": null,
"errors": [
{
"message": "Argument 'input' on Field 'addComment' has an invalid value. Expected type 'AddCommentInput!'.",
"locations": [
{
"line": 3,
"column": 3
}
]
},
{
"message": "Argument 'clientMutationId' on InputObject 'AddCommentInput' has an invalid value. Expected type 'String'.",
"locations": [
{
"line": 3,
"column": 20
}
]
}
]
}
クオートで 1234
をラップすると、この値を整数値から期待されている型である文字列に変換できます。
mutation {
addComment(input:{clientMutationId: "1234", subjectId: "MDA6SXNzdWUyMjcyMDA2MTT=", body: "Looks good to me!"}) {
clientMutationId
commentEdge {
node {
body
repository {
id
name
nameWithOwner
}
issue {
number
}
}
}
}
}