Anuj'BlogAnuj Verma

Express-GraphQl by example

express-grpahql provides a simple way to implement graphql server.

Let’s get started by initializing project and installing dependancies.

npm init -y

yarn add express graphql express-graphql graphql-import graphql-tag graphql-tools

Next we need to implement schema and resolvers for defining and accessing data.

Let’s try to define different schemas in different files and use importSchema to combine and make typeDefs for later use.

schema/index.js

const { importSchema } = require('graphql-import')
const { makeExecutableSchema } = require('graphql-tools')

const typeDefs = importSchema('./schema/schema.graphql')

const schema = makeExecutableSchema({ typeDefs })

module.exports = schema

This will import all the schemas from schema.graphql file and make executable schema.

Now, let’s define product schema first before going to work on schema.graphql

schema/product.grpahql

type Product {
  id: String!,
  name: String,
  slug: String,
  brand: String,
  type: String,
  image: String,
  price: Int,
  size: String,
  rating: Int
}

That’s it.

Now it’s time to define schema.graphql. Here we will import (import syntax is little strange) product schema. And also we will define all the Query that this schema can make to fetch results. Let’s get to work on it.

schema/schema.grpahql

# import Product from "product.graphql"

type Query {
  products(brands: [String!], types: [String!], limit: Int, offset: Int, sort: OrderByInput): ProductResult!
}

type ProductResult {
  products: [Product!]
  total: Int!
  hasMore: Boolean!
}

enum OrderByInput {
  name_asc
  name_desc
  price_asc
  price_desc
}

We have defined ProductResult this is the type of result that we will get when we query products. It will have products per page and total number of products as well as has more flag, to help implement infinite scroll if UI needs one. Another enum OrderByInput is used to get the sort input form UI and perform the sort based on this type.

Main part is Query here. This says that it will accept the query for products and reply an object like ProductResult.

This can be one example query to get the list of products with their id, name and brand.

{
  products{
    {
      id,
      name,
      brand
    }
    total,
    hasMore
  }
}

We know how to create schema and query data. But still we have to implement resolvers to fetch and format data for any datasource.

resolver/product.resolver.js

const { DEFAULT_PAGE_SIZE }  = require('../../constants')
const ProductRepository = require('./product-repository')
const productRepository = new ProductRepository()

const isArrayNotEmpty = arr => arr && arr.length

module.exports = {
    products: (args) => {
        let products = productRepository.findAll()
        ...

        if(args.sort === "name_asc"){
            products = products.sort((a, b) => a.name < b.name? -1: 1)
        }
        ...

        const offset  = args.offset || 0
        const limit =  args.limit || DEFAULT_PAGE_SIZE

        const total = products.length;
        const hasMore = offset + limit < total;

        if(args.offset ||  args.limit){
            products =  products.slice(offset, offset + limit)
        }

        return {
            products,
            total,
            hasMore
        }
    }
}

ProductRepository is your datasource. So you know how to get data and reply. For starter you can get a json file to work with and later configure your datasource.

I have shown how to do sorting and pagination. Rest all filters you can apply very easily. All the query params you will get in args object and you can use that to get the relevant data.

How to combine all the resolvers ??

Import all the resolvers in index.js and export from there. There you go…

resolver/index.js

const products = require('./product/product.resolver')

module.exports = {
  ...products,
}

Now our schema and resolvers are ready and its time to implement our express server.

const express = require('express')
const graphqlHTTP = require('express-graphql')
const schema = require('./schema')
const root = require('./resolvers')

const app = express()
const normalisePort = port => parseInt(port, 10)
const PORT = normalisePort(process.env.PORT || 4000)

app.use('/graphql', graphqlHTTP({ schema, rootValue: root, graphiql: true }))

app.listen(PORT, () => {
  console.log(`Server Started !`)
})

now you can go to http://localhost:4000/graphql and try to query products.

{
  products{
    {
      id,
      name,
      brand
    }
    total,
    hasMore
  }
}
Me

Anuj Verma