DEV Community

Cover image for How GraphQL works in the real world, a deep dive into Spectrum chat
Quod AI for Quod AI

Posted on

How GraphQL works in the real world, a deep dive into Spectrum chat

If you're a web developer, there’s a high chance that you’ve already heard of GraphQL. It completely changed the landscape of how APIs are queried and is growing at a tremendous pace with wider adoption from the developer community.

This article was originally posted at https://www.quod.ai/post/how-graphql-works-in-the-real-world-a-deep-dive-into-spectrum-chat

The specification for GraphQL was written by the folks over at Facebook and they implemented a JavaScript version of it, but now we have several implementations in several different languages. It is a query language (similar to SQL) that gives clients the power to request exactly what they want from an API and GraphQL does the magic for you. You might be wondering what the magic is. Today, we will be looking at just that.

Objectives

In this post, we will get into all the basic concepts behind GraphQL and what makes it a great solution for better web applications.

1.     Intro to GraphQL

2.     GraphQL Concepts

a.     Schema

b.     Type

c.      Queries, Resolvers, Mutations

3.     GraphQL using Spectrum

a.     Spectrum Introduction

b.     Queries in Action

Intro to GraphQL

As we wrote in the introduction, GraphQL was developed at Facebook. The specification was initially used in house, but they open sourced it. Now, there are several implementations of the specification in various different languages. GraphQL is a query language that sits in front of your API and integrates well with almost anything that you have. It is strongly typed, and expects you to know exactly what you want and it will give back clean, and concise results. Unlike REST APIs, GraphQL only has one single endpoint that does all the work. For instance, if you wanted to delete a product in your application, a REST endpoint would look something like this: /api/product/{id} and the type of request would be DELETE. If you had to buy a new product, there would be another endpoint like /api/product/buy and the type of request would be POST.

In GraphQL, we have a single endpoint and almost always, it is a POST request, that contains exactly what is to be sent back from the server. The request body determines what the server will send back, unlike in REST, where the server decides what to send. Before we use some of the terms in GraphQL, let’s take a look at high level concepts in more detail.

GraphQL concepts

If you ever have to have a discussion over GraphQL, these 5 terms would be of utmost importance. The beautiful thing about GraphQL is that it is very simple to get started with, but is so complex that you can never stop learning it.

Schema

A GraphQL schema dictates how the resources will be structured and organized and how the client can query them. You can think of a GraphQL schema as a DB schema, but for APIs. These schemas let you know what resources are available for querying and the way you need to query them.

Type

We have two kinds of types in GraphQL. They are scalar types and object types. Scalar types are similar to primitive data types and every field in a type should eventually run down to this. For instance, there can be an Object type called User with a field that references another Object type called Student, and so on. But the field that is referenced last will and should have scalar types. The scalar types available in GraphQL are: String, Int, Float, Boolean, ID (which is another String, but ensures uniqueness). Let’s look at a few sample types in GraphQL.

  type Message @cacheControl(maxAge: 600) {
    id: ID!
    timestamp: Date!
    thread: Thread
    content: MessageContent!
    author: ThreadParticipant! @cost(complexity: 2)
    reactions: ReactionData @cost(complexity: 1)
    messageType: MessageTypes!
    parent: Message
    modifiedAt: Date
    bot: Boolean
    sender: User! @deprecated(reason: "Use Message.author field instead")
Enter fullscreen mode Exit fullscreen mode

Line 1: This line has the keyword type to denote that it is a type followed by the name of the type, which is Message.

Line 2-12: These lines contain fields present inside the message type. You can see that we have a combination of scalar as well as Object types within the Message type. The fields id and bot are scalars. The rest of the fields are Object types. The ‘!’ mark next to the type tells that it is a non-nullable field.

Queries, mutations and resolvers

Queries - Queries in GraphQL determine what the client can access. In other words, it defines what your API can return.

Mutations - Mutations are queries that perform some changes to the data itself, therefore the name mutation.

Resolvers - In a traditional web application, we have controllers that route the request from the frontend to the server endpoint. Resolvers are basically like your controllers in a REST API. They are functions that return values for the different fields that are present in your type.

In just a bit, we will be looking at code that will showcase all these concepts in action.

GraphQL using Spectrum

Spectrum Introduction

To look at some GraphQL code, we will explore Spectrum chat. Spectrum is a community-based chat platform that gives additional functionalities like direct messaging, group messaging, ability to subscribe/unsubscribe to/from topics and specific chats. Spectrum is, however, moving over to GitHub Discussions and they don’t allow the creation of new communities anymore. By August 10, 2021, Spectrum will be completely archived and made read-only. This doesn’t stop us from going over some open-sourced code, does it?

Queries in Action

Now, let’s look at some of the queries in action which will incorporate most of the concepts that we covered before.

getMessageById - Query

export const getMessageByIdQuery = gql`
  query getMessageById($id: ID!) {
    message(id: $id) {
      ...messageInfo
    }
  }
  ${messageInfoFragment}
Enter fullscreen mode Exit fullscreen mode

View getMessageByIdQuery.js in context at Quod AI

Line 1-2: The first two lines denote exporting a constant named getMessageByIdQuery and we assign it a GraphQL query that is preceded by the ‘query’ keyword. You can see that the gql template literal tag is used to write the GraphQL query. This is imported from the graphql-tag library. If you notice, we have an argument id of type ID that is passed in as input to the query.

Line 3-7: Inside the query, we have the messageInfo which is preceded by three dots (this is not the spread/rest operator of JS). These are used to refer fragments within the code. You might be wondering, what are fragments? It is basically a piece of code that can be shared between multiple queries/mutations. In this query, we return a message, when an id is passed as in input. The MessageInfo fragment contains all the other fields that are needed to be returned by the message which includes an id, timestamp, messageType, content and more.

banUserMutation – Mutation

type BanUserInput = {
  userId: string,
  reason: string,
};


export const banUserMutation = gql`
  mutation banUser($input: BanUserInput!) {
    banUser(input: $input)
  }
`;
Enter fullscreen mode Exit fullscreen mode

View banUserMutation.js in context at Quod AI

Line 1-4: Mutations are also queries, but instead of just reading data, it updates data. This particular mutation is for banning a user. The first four lines denote the input type that is required to be given as input to the mutation. It has two fields, one is the userId and the next is the reason for banning the user.

Line 6-10: This shows the definition of the mutation itself, wherein we have the banUser mutation as the name which is preceded by the keyword ‘mutation’. It has a banUser field which takes in an input of the BanUserInput type we created above.

getCommunityById – Query

export const getMessageByIdQuery = gql`
  query getMessageById($id: ID!) {
    message(id: $id) {
      ...messageInfo
    }
  }
  ${messageInfoFragment}
`;
Enter fullscreen mode Exit fullscreen mode

View getCommunityByIdQuery.js in context at Quod AI

Line 1-9: Spectrum is all about communities and this particular query is used to retrieve a community by its id. Upon receiving an input id, this query returns two fragments, which are the communityInfo fragment and the communityMetaData fragment. You can check these two files under the following directory (spectrum/ shared/ graphql/ fragments/ community/ communityMetaData.js) and see the contents that are being returned by these two fragments.  

Conclusion

With that, we have covered some ground in GraphQL and also seen some concepts in action using Spectrum. You can check out the code in the GitHub repo here and see the app in action over here. Quod AI is the smartest way to search and navigate. We turn git repositories into documentation that developers actually use. Do follow us on twitter @quod_ai for updates on our product and DEVs community content. Check our app at: beta.quod.ai.

Top comments (0)