Intro to GraphQL ❤️
Tags: graphql, javascript, beginners, apollo
Published: 2020-07-09 23:39:15

It's been around 5 years since GraphQL was released by the Facebook Engineering team back in 2015. Since then, GraphQL has risen in popularity. Besides Facebook, companies like Airbnb, Netflix, Coursera, and many more have adopted GraphQL and it seems that have played very well from them not just in productivity but scalability. 


### What is GrapQL?

- GraphQL is just a query language for fetching data
- It serves as a specification, not an implementation. That being said, GraphQL does not tell you how to implement your solution that you can adapt to your needs.
- It only exposes a single endpoint to the client that consists of queries, mutations and subscriptions.
- The client only queries the data that it needs and the data is returned in the shape that it was requested. 


### Schema

We start by defining the schema in the server.
```graphql
type User {
   id: ID!
   firstName: String!
   lastName: String!
   """
   company that the user is associated with
   """
   company: Company
}

type Company {
   id: ID!
   name: String
   """
   where is this company located
   """
   location: String
}

input UserInput {
   firstName: String!
   lastName: String!
   company: CompanyInput
}

input CompanyInput {
   name: String!
   location: String!
   userID: ID!
}

type Query {
   """
   fetch the current user
   """
   currentUser: User
}

type Mutation {
   userCreate(userInput: UserInput!): 
}
```

Schemas are the core of the GraphQL server implementation. It describes everything that your API can do. All the queries the client can execute will be run against the scheme definition. 


- `Query` is the type where all your queries will be encapsulated.
- `Mutation` is the type where your *update-create-delete* actions will happen.
- `input` is normally used when mutating any data to defined the argument passed 

As you noticed, this is how we comment in GraphQL :
```
"""
Comment here
"""
```

### Resolvers for the Schema

After defining the schema, we need to define the “Resolvers”.  A Resolver is basically a function that knows how to resolve the type that the client is asking for.

```js
const user = { id: 1, firstName: "Henry", lastName: "Arbolaez" };
const Query = {
  currentUser: (parent, args, context) => {
    /**
     in the real world you would connect to some database.
     return context.db.User.findById(context.userId);
    */
    return user;
  }
}
```

That's how we defined a resolver for the currentUser.

### Querying for the current user

```graphql
query {
  currentUser {
    id
    firstName
    lastName
  }
}
```

When we query for the current user using the above query, we will return the data in the exact shape that it was requested.

```JSON
 {
   "currentUser": {
       "id": 1,
       "firstName": "Henry",
       "lastName": "Arbolaez",
    }
 }
```


But, let’s say, we want to query for the company of the current user. 

```graphql
query {
  currentUser {
    id
    firstNmae
    lastName
    company {
      id
      name
      location
    }
  }
}
```

When we execute the company query, `null` will be returned because there are no resolvers that know how to resolve the company type inside the user type 

We can get around this by resolving the company in the currentUser resolver *extending the currentUser resolver above*

```js
const user = { id: 1, firstName: "Henry", lastName: "Arbolaez" };
const companies = { 1: { id: 1, userID: 1, name: "Course Hero", location: "Redwood City" } };

const Query = {
  currentUser: (parent, args, context) => {
    // const company = context.db.Company.findById(parent.id);
    const company = companies[user.id];
    return {
      ...user,
      company,
    }
  }
}
```

**Note** There is a problem with this approach. We cannot guarantee that whenever the client asks for currentUser, it will always ask for the company that the user is associated with. A better approach is to have a resolver for the company type, and only resolve if the client asks for it.

```js
const companies = { 1: { id: 1, userID: 1, name: "Course Hero", location: "Redwood City" } };

const Query = {
  currentUser: ....,
  User: {
    company: (parent, args, context) => {
      /**
        parent: is the user object in this case. Think as the parent, as the Type that is wrapping this resolver. In this case the User type.
      */
      // return context.db.Company.findById(parent.id)
      return companies[parent.id]
    }
  }
}
```
We added the `company` resolver under the `User` type to match our schema definition. If we were to put the company in the `Query` type, it wouldn’t know what it’s going to resolve for,  since the schema explicitly said that the company belongs to the `User` type.

By doing this - it’s quite an optimization since the client doesn’t have to ask for the company type when asking for the current user.  The extra request to fetch the company is eliminated and our server is happy!!

### Why Graphql?

- GraphQL limits the number of requests being made to the server, enabling multiple queries simultaneously in one expansive query.
   - Usually, in REST, you will have different RESTful endpoints to do X operation.
```
-- users
GET https://example.com/users
CREATE https://example.com/users
GET https://example.com/users/1
DELETE https://example.com/users/1
PUT https://example.com/users/1

-- companies
GET https://example.com/companies
CREATE https://example.com/companies
GET https://example.com/companies/1
DELETE https://example.com/companies/1
PUT https://example.com/companies/1

-- companies associated with the user
GET https://example.com/user/1/companies
GET https://example.com/user/1/companies/1
```
   - i.e. if we want to fetch all the companies for a given user, we will need to:
      1. Fetch the user endpoint to get the userId
      2. Fetch the companies for the given userId
   - Also, in REST, we aren’t aware of the shape of the data is coming back and the type of it.
   - in GraphQL this could be simply be sent to the server as one query while reusing code that is already there, and we would know beforehand what is the shape and type of that data.
```
query currentUser {
  companies {
    id
    name
  }
}
```
- Improve developer experience and productivity
   - GraphQL is a strong type and has validation
   - There are a lot of tools around GraphQL, that increase productivity. One of them is the [GraphQL Playground](https://github.com/prisma-labs/graphql-playground), which lets you introspect the query before having to write any code.
   - GraphQL will help standardized and simplify complexity in our API's. In the example above for the REST API, we wouldn't need to worry about creating those many resources.


### Wrapping

I hope this intro to GraphQL has helped you to understand the basics of what a schema, resolvers, and the client request are. There are quite a few other topics that we can cover, but with this brief introduction of GraphQL, you can build a simple graph and dive deeper into more advanced topics. Here are some resources that I find useful.

Here are some resources that I find that are going to be useful:

- [GraphQL.org](http://GraphQL.org)
- [GraphQL Learn](https://graphql.org/learn/)
- [GraphQL Awesome](https://github.com/chentsulin/awesome-graphql)
- [Apollo](https://www.apollographql.com/docs/)
- [Apollo Federation](https://www.apollographql.com/docs/apollo-server/federation/introduction/)