If we look at the general structure of the common connection implementation you typically have the following:
TypeA -> TypeAToTypeBConnection (usually a field on TypeA with a name like typeBConnection
) -> TypeAToTypeBEdge (usually field of name on connection with name edges
) -> TypeB (usually field name on an edge with name node
)
A -> connection -> edges -> B
Connection types will normally have fields containing information which is specific to the entire connection which is typically paging information, total counts, etc.
Edge types normally have fields which have information which is specific to that connection but not common to all nodes. The most common field in this case is cursor
which represents the nodes ‘location’ in the connection which is not a globally unique ID but a way to return to that location in the connection.
Node type is normally just the type which the connection goes too which contains no connection specific information
In the case of github’s API the Edge type has the commonly implemented cursor
field which can be used as a reference within that connection later. They also have a field which bypasses the edge
type in the case you don't need the cursors. This is why you see both edges
and nodes
fields directly off the connection type.
To see these cursor fields you can send the following query to see what I am talking about:
{
repository(owner: "getsmarter", name: "moodle-api") {
issues(first:2 ) {
edges {
cursor
node {
id
}
}
}
}
}
For more detail on this style of connection take a look here: https://facebook.github.io/relay/graphql/connections.htm
EDIT - Additional response:
The purpose of allowing access to both an edge type and a node type right at the connection could be for, at least, 2 reasons which I can think of. Firstly, for the convenience of those using the API when their use case does not require cursors. Second, there might be a case in which, depending on the query sent, they may not need to ever even generate cursors. The second would likely be minimal savings in CPU time and would probably be more trouble than it is worth.
Having implemented cursors in a GraphQL endpoint myself in the past, once you get over the how, the actual generation of them is not really all that difficult. It is simply a matter of serializing a few key pieces of information. It also might be worth noting, it is pretty trivial to provide both (A->conn->edge->B
and A->conn->B
) once you have already created the Edge type.
As I do not work for Github, I can’t tell you what exact intention was. However, I would most definitely think it is the first reason… simply developer convenience.