Architecture

Before going further in understanding GraphQL, it's useful to get a sense of how GraphQL is actually used in an HTTP client (typically a web/mobile app).

GraphQL over HTTP

Check out the diagram below, to get a sense of how GraphQL is typically used in your stack:

GraphQL over HTTP

GraphQL client-server flow:

  1. Note that the GraphQL query is not really JSON; it looks like the shape of the JSON you want. So when we make a 'POST' request to send our GraphQL query to the server, it is sent as a "string" by the client.
  2. The server gets the JSON object and extracts the query string. As per the GraphQL syntax and the graph data model (GraphQL schema), the server processes and validates the GraphQL query.
  3. Just like a typical API server, the GraphQL API server then makes calls to a database or other services to fetch the data that the client requested.
  4. The server then takes the data and returns it to the client in a JSON object.

Example GraphQL client setup:

In your day to day work, you don't actually need to worry about the underlying HTTP requests & responses.

Just like when you work with a REST API and use a HTTP client to reduce the boilerplate in making API calls and handling responses, you can choose a GraphQL client to make writing GraphQL queries, sending them and handling responses much easier.

Now the tricker part is how do we send a GraphQL query from an elm app? The most hacky way would be to construct a Graphql query using a multiline string and use elm/http to transmit the query and receive the response. You will quickly run into following problems ☹

queryDefinition : String
queryDefinition =
"""
query {
user {
id
name
}
}
"""
  • You lose the awesomeness of the elm type system
  • You need to parse the response into appropriate data structures to make it usable inside the application (DECODERS!!!)

And so on...

There are tools which solves the above problem in a nice way. One such tool is elm-graphql which does all the heavy lifting for you.

Here's what a typical setup and making a query would look like:

-- Skipping the imports --
{-
GraphQL query is constructed using the helper functions generated by elm-graphql
For now lets assume `makeGraphQLQuery` will generate a query as below when invoked.
query {
user {
id
name
}
}
-}
type alias User =
{
id : Int
name: String
}
type alias Users =
List User
fetchUsersQuery : SelectionSet Users RootQuery
fetchUsersQuery =
Query.user identity userListSelection
userListSelection : SelectionSet User Hasura.Object.User
userListSelection =
SelectionSet.map2 User
user.id
user.name
-- Use the client provided by elm-graphql to make the GraphQL query request
makeGraphQLQuery : SelectionSet Users RootQuery -> (Result (Graphql.Http.Error Users) Users -> msg) -> Cmd msg
makeGraphQLQuery query msgType =
query
|> Graphql.Http.queryRequest "https://myapi.com/graphql"
|> Graphql.Http.send msgType

The code above demonstrates how

  • A GraphQL query is constructed - Using Query.user, SelectionSet functions generated by elm-graphql
  • A GraphQL query is sent to the server - Using Graphql.Http.queryRequest function provided by elm-graphql