GraphQL Server Primer
Tags: webdev, graphql, javascript
Published: 2019-03-25 12:59:17

---
title: GraphQL Server Primer
published: true
description: Learning how to build a GraphQL API server
tags: webdev, graphql, javascript
cover_image: https://thepracticaldev.s3.amazonaws.com/i/484z39z76rm5pg1n20ct.png
canonical_url: https://andrewdavis.me/post/graphql-server-primer/
---
GraphQL is one of the hottest topics in web development right now. I do a lot of work with Magento and they recently announced a whole new GraphQL API to be used for front end development. To learn GraphQL, [I built an experimental Magento frontend using Next.js](https://andrewdavis.me/post/creating-a-magento-theme-with-nextjs-and-graphql/). After that project, I still did not understand how to build a GraphQL server. As a result, I decided to build an example GraphQL server using Node.js. The original GraphQL specification was written in JavaScript so it is a good language to use when learning GraphQL. I created a GitHub repository called [graphql-nodejs-example](https://github.com/restoreddev/graphql-nodejs-example/) if you want to view the whole project. In this post, I want to discuss a few concepts about GraphQL that really helped me understand how it works.

## A GraphQL Server Has Only One Endpoint
In REST APIs, it is common to have multiple URLs for a single resource. You might have several endpoints for loading and creating data like `/tasks`, `tasks/1`, `/tasks/create`. In GraphQL, your server runs only a single endpoint, usually at the root `/` or at `/graphql`. When submitting a query to a GraphQL server, you explicitly set the resource you want in the request body, so the server can decide what values to return.

## GraphQL Is About Types
In a GraphQL API, you define what resources you have using a type language. GraphQL supports [five scalar types](https://graphql.org/learn/schema/#scalar-types) that you can use to compose more complex object types. The five scalar types are: `Int`, `Float`, `String`, `Boolean` and `ID`. To create a resource, you build an object type for it. I wanted to emulate a forum so I created three resources: `User`, `Thread` and `Comment`. In GraphQL types, those resources look like this:
```graphql
type User {
  id: Int!
  userName: String!
  firstName: String
  lastName: String
}

type Thread {
  id: Int!
  name: String!
  description: String!
  user: User!
  comments: [Comment]
}

type Comment {
  id: Int!
  description: String!
  user: User!
}
```
You can see that you can create an object type using the `type` keyword followed by a name. In curly braces, you define the properties of the object by writing the name of the property followed by a colon and the type. An exclamation point `!` after the property indicates that the value cannot be null.

You can also use custom types in other custom types. The `Thread` type has a user and comments property that reference the other two types I created. Brackets around the type name like `[Comment]` indicate that the property is an array.

When writing a server, where do you put those types? I put them all in a file called `schema.graphql` and used the Apollo Server helper `gql` to import that file into my server.

## Requests Are Handled By a Query and Mutation Type
In GraphQL, there are two types of requests you can send to a GraphQL server: `query` and `mutation`. A `query` is used to retrieve data and a `mutation` is used to perform actions on data, like creating or updating. In your server schema, you define a query object type and a mutation object type, like so:
```graphql
type Query {
  thread(id: Int!): Thread
  threads: [Thread]
}

type Mutation {
  createThread(name: String!, description: String!, userId: Int!): Thread
  createComment(userId: Int!, threadId: Int!, description: String!): Comment
}
```
You can see in my `Query` type, I define two ways to retrieve a thread. The `threads` property returns an array of all threads and the `thread(id: ID!)` returns a single thread. The parentheses denote arguments that can be passed in the query. Since I marked `id` as a non-nullable `Int`, to retrieve a single thread you have to pass in the `id` of a thread in your GraphQL request.

In the `Mutation` type, there are two properties for creating a thread and creating a comment. Each operation requires a set of values for creating the resource and each returns the newly created resource.

## Resolving Your Queries and Mutations
After defining the schema, how do you implement the logic to load the resources from a data source? You use resolvers! Resolvers are similar to controllers in a REST API. For each `Query` and `Mutation` property, you create a JavaScript function that accepts arguments and performs the operation on the resource to load data or change it.

I used the [Apollo Server](https://www.apollographql.com/docs/apollo-server/) library to build my GraphQL API. The library allows you to write your schema, import it and pass in a resolver object that will handle all of the requests.

My Apollo Server setup looks like this:
```javascript
const fs = require('fs');
const { ApolloServer, gql } = require('apollo-server');
const schema = fs.readFileSync(__dirname.concat('/schema.graphql'), 'utf8');
const typeDefs = gql(schema);
const resolvers = require('./resolvers');

const server = new ApolloServer({ typeDefs, resolvers });
server.listen().then(({ url }) => {
  console.log(`Server ready at ${url}`)
});
```
All I need for my Apollo Server instance is to pass in my schema and resolvers and it will start a node server that I can query.

My resolvers file just exports a JavaScript object with a Query and Mutation property that holds references to functions for each property defined in my schema:
```javascript
const threads = require('./threads');
const comments = require('./comments');

module.exports = {
  Query: {
    threads: threads.all,
    thread: threads.findOne,
  },
  Mutation: {
    createThread: threads.create,
    createComment: comments.create,
  }
};
```
The `threads` and `comments` imports each return an object of functions that can be passed into the resolver object.

So what does a resolver function look like? Here is a query resolver that returns all `Thread` types from a database:
```javascript
exports.all = async function () {
  const threads = await db.Thread.query().eager('[comments.[user], user]');

  return threads;
};
```
The function queries a database for the data needed to resolve the `Thread` type and then Apollo Server pulls out the values it needs and returns it to the client that requested all the threads.

A mutation is very similar:
```javascript
exports.create = async function (parent, args) {
  const thread = await db.Thread.query().eager('user').insertAndFetch({
    userId,
    name,
    description,
  } = args);
  thread.comments = [];

  return thread;
};
```
The second parameter a resolver function receives is all the arguments passed from the request. I use those arguments to create a new thread in the database and then return the data for Apollo Server to pass back to the client.

## Querying the Server
There are many ways to test a GraphQL API. I like to use [Insomnia](https://insomnia.rest/). In development mode, Apollo Server will return your schema so that Insomnia can read it, allowing you to auto-complete queries for the API.

Here is an example query you can send to the server with the above schema:
```graphql
query getThreads {
  threads {
    id
    name
    description
    user {
      id
      firstName
      lastName
      userName
    }
    comments {
      id
      description
      user {
        id
        userName
      }
    }
  }
}
```
In the query, I am requesting the `threads` property of the query object and passing in the attributes I want for each thread. Dynamic queries are what make GraphQL so good, because you can ask for as little or as much data as the API can provide. The following json represents what the API server returns to the client:
```json
{
  "data": {
    "threads": [
      {
        "id": 1,
        "name": "Thread 1",
        "description": "This is the first thread",
        "user": {
          "id": 1,
          "firstName": "Test",
          "lastName": "User 1",
          "userName": "testuser1"
        },
        "comments": [
          {
            "id": 1,
            "description": "This is a comment on the first thread",
            "user": {
              "id": 2,
              "userName": "testuser2"
            }
          },
          {
            "id": 3,
            "description": "Another comment",
            "user": {
              "id": 1,
              "userName": "testuser1"
            }
          }
        ]
      },
      {
        "id": 2,
        "name": "Thread 2",
        "description": "This is the second thread",
        "user": {
          "id": 2,
          "firstName": "Test",
          "lastName": "User 2",
          "userName": "testuser2"
        },
        "comments": [
          {
            "id": 2,
            "description": "This is a comment on the second thread",
            "user": {
              "id": 1,
              "userName": "testuser1"
            }
          }
        ]
      }
    ]
  }
}
```

A mutation query for creating a thread looks like this:
```graphql
mutation createThread {
  createThread(
    userId: 1,
    name: "A new thread",
    description: "This is a description"
  ) {
    id
    name
    description
    user {
      id
      firstName
      lastName
      userName
    }
  }
}
```
I am calling the `createThread` property of the mutation type and passing in the required arguments. It returns to me the resource that it just created:
```json
{
  "data": {
    "createThread": {
      "id": 7,
      "name": "A new thread",
      "description": "This is a description",
      "user": {
        "id": 1,
        "firstName": "Test",
        "lastName": "User 1",
        "userName": "testuser1"
      }
    }
  }
}
```

## Some General Tips and Tricks
Here are a few more general tips for starting a GraphQL server project:

- If you use a database, use a NoSQL database like MongoDB or a SQL database with an ORM that supports eager loading. GraphQL types often use nested objects so it can be difficult to write plain SQL queries and map the data for your responses. I used the [Objection.js](https://vincit.github.io/objection.js/) ORM with sqlite and that made my database code much simpler.

- GraphQL naturally validates the data types of any arguments passed into your API, but it only validates the type. By default, a string type can be empty or any length. I used the validation features of Objection.js to prevent the use of empty strings in mutations.

- The `ID` scalar type converts ID values to a string. That will work great for some databases, but in my case I was using sqlite with numeric primary keys so I left my ID values as an `Int`.

## Conclusion
I was surprised by how quickly you can build a GraphQL API, especially with the help of libraries like Apollo Server and Objection.js. I really like being able to define my API around types which become natural documentation for your available resources. Not having to set up URL routing or type validation saves a lot of time as well. The benefits of GraphQL for building API clients have been touted widely, but I think there are some real advantages for the server too.

I hope this article helped you understand GraphQL servers even better. Leave a comment if you have any questions or thoughts about this post!