GraphQL

GraphQL Apollo CRUD API using Node Express Server

January 29, 2018

author:

GraphQL Apollo CRUD API using Node Express Server

GraphQL a query language gives power to the client to specify and fetch the exact data required. GraphQL exposes only a single endpoint to fetch complex data as opposed to the multiple endpoints of REST. Thus it can is more powerful and faster than the novice REST API.

# What is GraphQL Apollo?

In the previous section, we have build a Node Express Server from GraphQL from scratch. However, it was a basic one with limited features. We can of course work on it to add new features. But GraphQL market already has built for us. In this section, we will use third party library called Apollo. It works as a bridge between Node Server and GraphQL Schema.

It supports all the popular JS servers like Express, Connect, Restify, Japi, Lamda and Koa. Graphql-tools is the package that includes these server tools. It is also created and maintained by Apollo community and hence work well with each other. With graphql-tools, we don’t need to use GraphQL.js type constructors directly; we can utilize this package’s production ready GraphQL schema language to build a schema. For this tutorial, we will use Express Server to build a GraphQL API with Apollo.

# Setup

We will create a GraphQL API for some random application with basic CRUD for companies with name as input field. It is apparent that you would need node installed in your system before moving any further. You can confirm with:

node -v

Create a new project, initiate npm and follow along its steps: (note, you can also clone the project from GitHub)

npm init

Next, install the required packages. Since we know what packages we need, we will install all of them here:

npm install expess graphql graphql-server-express graphql-tools lodash cors body-parser --save

For es6 syntax usage, also install dev-dependencies:

npm install babel-cli babel-preset-es2015 babel-preset-stage-0 --save-dev

# Folder Structure

It becomes easy to keep the folder structure clear so as to prevent any misunderstandings in the future:

-data
    --company.js //store dummy JSON data
-src
     --resolvers.js //store GraphQL-Apollo mutation
     --schema.js    //store GraphQL-Apollo schema
-server.js //express server setup
-package.json //store information about application and libraries
-node_modules //store installed packages

We discussed GraphQL components like type, query and mutation in great detail in GraphQL CRUD Tutorial, so we will not repeat the same explanation again and move faster this time. We will first see the overall types, queries and mutation for our project and then create a schema. Hence just look at the explanation for all the three below:

# GraphQL Type

As for a company, we need a company type with id and name as fields:

type Company {
  id: ID!
  name: String
}

Note that here id is a required field and we are using GraphQL’s inbuilt ID type as opposed to string type for uuid we did in the earlier post. This is for the understanding purpose; we will add this type a little later.

# GraphQL Query

As we already know by now, GraphQL queries are used as GET endpoint:

type Query {
   Companies: [Company]
   Company(id: ID!): Company
}

Here Query root type stores two queries. Companies would return a list of companies while Company would return a specific company with id. The id must be provided to fetch a single company.

# GraphQL Mutation

GraphQL utilizes mutations for Post and Delete endpoints. We will use mutation to create, update and delete the companies.

type Mutation {
   addCompany(name: String!): Company,
   updateCompany(id: ID!, name: String!): Company,
   deleteCompany(id: ID!): Company,
}

Mutation root type defines various mutation. Here all the mutations are self-explanatory which accept various arguments and return Company type which is quite obvious.

# GraphQL Schema

As we wish to use Apollo in our project, we have to create the GraphQL schema following its peculiar environment. Hence, add the following type, queries and mutation in schema.js:

# src/schema.js
const { makeExecutableSchema } = require('graphql-tools');
const resolvers = require('./resolvers');

const typeDefs = `
    type Company {
      id: ID!
      name: String
    }
    type Query {
      Companies: [Company]
      Company(id: ID!): Company
    }
    type Mutation {
      addCompany(name: String!): Company,
      updateCompany(id: ID!, name: String!): Company,
      deleteCompany(id: ID!): Company,
    }
    type Subscription {
      companyAdded: Company,
      companyEdited: Company,
      companyDeleted: Company
    }
    `;

const schema = makeExecutableSchema({ typeDefs, resolvers });
module.exports = schema;

Explanation:

const schema = makeExecutableSchema({ typeDefs, resolvers });

After defining all root types, we call makeExecutableSchema in the end and pass our schema and resolvers (which we will create in a moment). This maps the schema and resolvers together. We also export this schema so that we can import in our server a little later.

# GraphQL Apollo Resolvers

Resolvers have a job to map our schema and the actual data. They resolve the incoming and return types and thus respond to queries. Each and every query and mutation must have a specific resolver function. Every field in each type can also have its own resolver function. The resolver in Apollo is nothing but an object consisting all the logic to be executed for any particular query or mutation type.

# src/resolvers.js

const _ = require("lodash");

const resolvers = {
    Query: {
        Companies: () => {
            return Company;
        },
        Company: (root, { id }) => {
            return Company.find(c => c.id == id);
        },
    },
    Mutation: {
        addCompany: (root, { name }) => {
            const newCo = { id: nextId++, name: name };
            Company.push(newCo);
            pubsub.publish(ADD_COMPANY, { companyAdded: newCo });
            return newCo;
        },
        updateCompany: (root, { id, name }) => {
            const updateCo = { id: id, name: name };
            let findId = Company.findIndex(c => c.id == id);
            let update = Company.splice(findId, 1, updateCo);
            pubsub.publish(EDIT_COMPANY, { companyEdited: updateCo });
            return updateCo;
        },
        deleteCompany: (root, { id }) => {
            let deleteCo = Company.find(c => c.id == id);
            _.remove(Company, deleteCo);
            pubsub.publish(DELETE_COMPANY, { companyDeleted: deleteCo });
            return deleteCo;
        },
    }
};

module.exports = resolvers;

Explanation:
A resolver object has two keys namely Query and Mutation. It takes three optional argument root, args and context. Here args argument is the important one as it holds the data to be variables or string which are to be sent by the client. Moreover, these functions are same as declared in the schema. Like, schema, we are also exporting resolvers to use in our express server.

# Data for GraphQL API

# src/resolvers.js
...
const Company = require('../data/company.js');
let nextId = 5;
...

As you would have noticed, we are importing data from company.js. For this example, instead of some actual mongo or MySQL database, we are using a stored array. It basically stores dummy data to work around.

# data/company.js

const Company = [
    { id: 1, name: 'Apple' },
    { id: 2, name: 'Microsoft' },
    { id: 3, name: 'Samsung' },
    { id: 4, name: 'Mi' },
];

module.exports = Company;

# Apollo and Express

It is necessary to tie schema and resolver with the server. Apollo provides ready to use implementation for various JavaScript libraries; we will use Express in this tutorial. We will define two endpoints. One for basic GraphQL client request which will run through the entire query-mutation blocks and finally return some result.

app.use('/graphql', bodyParser.json(), graphqlExpress({
 schema
}));

While the second endpoint will be used for our testing purpose in GraphiQL. With GraphiQL, we will test all the queries and mutations.

app.use('/graphiql', graphiqlExpress({
    endpointURL: '/graphql'
}));

And here’s the whole express server with Apollo implementation:

# server.js

import express from 'express';
import {
  graphqlExpress,
  graphiqlExpress,
} from 'graphql-server-express';
import bodyParser from 'body-parser';

import { schema } from './src/schema';

const PORT = 8080;
const server = express();

server.use('/graphql', bodyParser.json(), graphqlExpress({
  schema
}));

server.use('/graphiql', graphiqlExpress({
  endpointURL: '/graphql'
}));

app.listen(PORT);
console.log('GraphQL API Server up and running at localhost:' + PORT);

# Testing

To test the API,

npm server.js
http://localhost:8080/graphiql

Display in GraphQL:

query CompanyList{
  Companies {
    id
    name
  }
}
GraphQL Apolllo API read query

Create Operation in GraphQL:

mutation AddNewCo {
  addCompany (name: "HP"){
    name
  }
}
GraphQL Apolllo API create mutation

Update Operation in GraphQL:

mutation UpdateCo {
  updateCompany (id: 2, name: "Sony"){
    name    
  }
}
GraphQL Apolllo API update mutation

Delete Operation in GraphQL:

mutation DeleteCo {
  deleteCompany (id: 3){
    id
  }
}
GraphQL Apolllo API delete mutation

Conclusion:

It was a good time learning about Apollo and its usage. We did set up a fresh application and made GraphQL API using Node.js Express and Apollo Server. We also tested the application in GraphiQL.

Questions & Comments:

Hope it was fruitful, if you have any questions or suggestions on building a GraphQL Apollo API Server, share them in the comment section below.

Leave a comment

Your email address will not be published. Required fields are marked *