I was pretty excited to see that the new Github API (v4) used Graphql. I wanted to retrieve the last x commits from master for a project I was working on. Should be easy right? After a bunch of time wasted on GitHub’s GraphQL Explorer I came up with the following which didn’t really solve my issue:

query{
  repository(owner: "typelevel", name: "cats") {
    defaultBranchRef {
      name
      prefix
      associatedPullRequests(states: [MERGED], last: 5) {
        edges {
          node {
            title
          }
        }
      }
    }
  }
}

It was limited to PRs and didn’t really seem like a nice solution.

I then asked this question on Stackoverflow.

Meanwhile while rummaging around the Github platform Forum I came across this post that gave me some clues:

{
  repository(owner: "golang", name: "go") {
    defaultBranchRef {
      target {
        ... on Commit {
          history(first: 10) {
            pageInfo {
              hasNextPage
              endCursor
            }
            edges {
              node {
                oid
                messageHeadline
              }
            }
          }
        }
      }
    }
  }
}

So I modified the above to suit my needs and came up with this query that returned the most recent commits on master:

query {
  repository(owner: "typelevel", name: "cats") {
    ref(qualifiedName: "master") {
      target {
        ... on Commit {
          history(first: 10) {
            pageInfo {
              hasNextPage
              endCursor
            }
            edges {
              node {
                oid
                messageHeadline
              }
            }
          }
        }
      }
    }
  }
}

Graphql was supposed to make understanding the structure of an API much easier with automatically generated documentation and tools like Graphiql. What still seems to be missing is how to sort through interfaces and their implementations easily to figure out what type of objects are returned from query.

For example in the Github API, the Repository object implements the following other interfaces:

  1. Node
  2. ProjectOwner
  3. Subscribable
  4. Starrable
  5. UniformResourceLocatable
  6. RepositoryInfo

And if we just look at the Node interface, we see that it has the following implementations:

  1. Organization
  2. Project
  3. ProjectColumn
  4. ProjectCard
  5. Issue
  6. User
  7. Repository
  8. CommitComment
  9. Reaction
  10. Commit
  11. Status
  12. StatusContext
  13. Tree
  14. Ref
  15. PullRequest
  16. Label
  17. IssueComment
  18. PullRequestCommit
  19. Milestone
  20. ReviewRequest
  21. PullRequestReview
  22. PullRequestReviewComment
  23. CommitCommentThread
  24. PullRequestReviewThread
  25. ClosedEvent
  26. ReopenedEvent
  27. SubscribedEvent
  28. UnsubscribedEvent
  29. MergedEvent
  30. ReferencedEvent
  31. CrossReferencedEvent
  32. AssignedEvent
  33. UnassignedEvent
  34. LabeledEvent
  35. UnlabeledEvent
  36. MilestonedEvent
  37. DemilestonedEvent
  38. RenamedTitleEvent
  39. LockedEvent
  40. UnlockedEvent
  41. DeployedEvent
  42. Deployment
  43. DeploymentStatus
  44. HeadRefDeletedEvent
  45. HeadRefRestoredEvent
  46. HeadRefForcePushedEvent
  47. BaseRefForcePushedEvent
  48. ReviewRequestedEvent
  49. ReviewRequestRemovedEvent
  50. ReviewDismissedEvent
  51. Language
  52. ProtectedBranch
  53. PushAllowance
  54. Team
  55. ReviewDismissalAllowance
  56. Release
  57. ReleaseAsset
  58. RepositoryTopic
  59. Topic
  60. Gist
  61. GistComment
  62. OrganizationIdentityProvider
  63. ExternalIdentity
  64. Blob
  65. Bot
  66. RepositoryInvitation
  67. Tag
  68. AddedToProjectEvent
  69. BaseRefChangedEvent
  70. CommentDeletedEvent
  71. ConvertedNoteToIssueEvent
  72. MentionedEvent
  73. MovedColumnsInProjectEvent

That’s a few too many options to manually sort through.

The example documentation has a very simple example with a few implementations of an interface:

{
  search(text: "an") {
    ... on Human {
      name
      height
    }
    ... on Droid {
      name
      primaryFunction
    }
    ... on Starship {
      name
      length
    }
  }
}

While this seems manageable it can easily get out of hand as per the Github API.

So even though Graphql does provide automatic documentation, if your domain model is complex enough, you probably still need to provide the users of your API some documentation on how everything hangs together.