GraphQL: Learn by Doing (Part 2 of 3)

Armand Aquino
EdgeCoders

--

This is Part 2 out of 3 of this GraphQLLearn by Doing” series.

Hope you enjoyed Part 1 and have a working GraphQL server. Let’s make it do some cooler things.

In this series we’ll be querying data from an external source. GraphQL is a server that is part of the data service layer in your application architecture. It doesn’t store the data but only queries the data or sends data to the data source so it can make the mutations. We‘ll only focus on the GraphQL query portion in *this* series but I’ll do another series on just mutations later.

Note that GraphQL can query data from multiple types of data sources. It can be from a relational database like PostgreSQL or a NoSQL datbase like MongoDB or a text file or a local private variable or from an RESTful API call. We’ll be making calls to the GitHub API to get our data. I chose the GitHub API because it is an external data source that doesn’t require any additional setup, doesn’t require you to sign up for an API access key, and many people can relate to it.

This is the URL you call to the API on either a browser or a XHR method:

https://api.github.com/users/apaquino

The last portion is like the where clause and should change to the github user login of the user you want to get data for. The return data will look something like this.

{
login: “apaquino”,
id: 8031866,
avatar_url: “https://avatars.githubusercontent.com/u/8031866?v=3",
site_admin
: false,
...
following
: 12,
...
}

There are 30 fields in total but I only included a few in this example.

Most apps don’t need all 30 fields and only use a few to display on the UI, but when they make a RESTful API call, they get all 30 fields. If this was a “user” table in a relational database and you only need 5 specific fields, then would you use the SQL statement below? I hope not!

SELECT * from USERS where LOGIN = ‘apaquino’

Now lets make the GraphQL objects we need to setup the schema so our GraphQL server knows how to get the data.

First, let’s make a GraphQL object type that will have the fields we need so it can be the root query field. The data from the API call helps you determine the name and type to declare each field. For this example, I did not add a “description” field. If there is no “resolve” function, then it will match the name of the field from the data source to the field in the query “fields” object and return the value as-is. For example, “login” from the GitHub API will be returned when you query for login in the GraphQL server.

const UserInfoType = new GraphQLObjectType({
name: “UserInfo”,
description: “Basic information on a GitHub user”,
fields: () => ({
“login”: { type: GraphQLString },
“id”: { type: GraphQLInt },
“avatar_url”: { type: GraphQLString },
...
"site_admin": { type: GraphQLBoolean },
...
})

Now let’s update the query object to use this UserInfoType for the fields.

const query = new GraphQLObjectType({
name: “Query”,
description: “First GraphQL Server Config — Yay!”,
fields: () => ({
gitHubUser: {
type: UserInfoType,
description: “GitHub user API data with enhanced and additional data”,
args: {
username: {
type: new GraphQLNonNull(GraphQLString),
description: “The GitHub user login you want information on”,
},
},
resolve: (_,{username}) => {
const url = `https://api.github.com/users/${username}`;
return axios.get(url)
.then(function(response) {
return response.data;
});
}
},
})
});
  • Add a root query field called gitHubUser
  • Declare it is has the fields defined in the UserInfoType we just created
  • Declare it will accept 1 argument named “username” that cannot be null
  • Describe how it will resolve getting the data by creating a URL string based on the argument passed in, use the get method in the axios module to make the RESTful API call, and return the data.

There are a few fields that return a value that I think will require most front-end developers to perform extra work. Here is an example of one of them.

following_url: “https://api.github.com/users/apaquino/following{/other_user}",

That is the URL that can be used to make another RESTful API call. If you use that as-is, then you will get an error because of the {/other_user} portion. So you have to remove it.

With GraphQL, you can modify that value before it is returned to the app. In the “following_url” field in the UserInfoType fields object, let’s add a “resolve” function so we can perform some javascript on it before it is returned. Now it is more useful for the developer and developer and app has to do less work. This saves time for everyone so unless you are mean a person, you should love this.

...
"following_url”: {
type: GraphQLString,
resolve: (obj) => {
const brackIndex = obj.following_url.indexOf(“{“);
return obj.following_url.slice(0, brackIndex);
}
},
...

This implementation is just JavaScript so you can use it’s full power to do a lot of neat things. Since I have the entire return object at my disposal, we can access the data and any field, find out the position of the “{“ , slice the “following_url” field to return to the app a deep copy of the “following_url” without the portion we don’t want. (Try not to use splice to mutate the original object and make in-place updates, just don’t.)

Here is a screenshot of GraphiQL with a query for just 5 fields we want and the output that would be returned. Also, on the right is the UI explorer to see all the fields that is available and it’s type … just in case you don’t want to just depend on the autocomplete feature when typing your query.

Notice the “following_url” is nice and neat, and can be passed in to another a RESTful API call. Now suppose you want to make that call in just one trip? Note that you have access to the entire object that is returned so you can make new fields for the developer to query and give it a “resolve” function that can not only manipulate the data before it is returned but also make other JavaScript calls, like axios, to get the data. That is what will do in Part 3 :)

Code from this blog can be found here. I will have different branches for each part of the series.

Hope you enjoyed the second installment of GraphQL: Learn by Doing.

If you thought this article was helpful, then consider recommending ❤ the story so more people will find it.

Thanks for reading and stay tuned for more.

--

--

Armand Aquino
EdgeCoders

Quantitative Analyst/Developer at Optimal Asset Management, Inc. ✌♠️