In this post, we will learn how to create a GraphQL Schema using GraphQL.js. We will use the express-graphql package to handle the webserver part of the application.

In case you are completely new to GraphQL, I will recommend you to start with our Introduction to GraphQL.

A schema is the core component of a GraphQL application. It defines the capabilities of the GraphQL application. To elaborate further, a GraphQL schema is like a description of the data available from your application. It also defines the various queries and mutations that clients can use to interact with the server. In a way, the schema is the heart of a GraphQL application.

1 – Setting up the Project

We will first create a project and install the express, graphql-express and graphql packages. You can read more about these packages by going through this post about building your first GraphQL server.

Then, we will create a file named server.js to handle the configuration and startup of our application.

See below:

const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const schema = require('./schema/schema')

var app = express();

app.use("/graphql", graphqlHTTP({
    schema,
    graphiql: true
}));

app.listen(4000);

console.log('GraphQL API server available at http://localhost:4000/graphql');

You can ignore the third line for the time being where we require a schema file. We will be creating it in the next section. Basically, we import the schema and provide it to the graphqlHTTP() function. Also, we set the graphiql property as true. Setting this to true enables the GraphQL playground where we can test our GraphQL queries. Finally, we start the application to listen on port 4000.

2 – Creating the Book Object Type

Now, we create the schema file for the application.

To demonstrate how a GraphQL Schema works, we will take the example of a Book entity.

See below:

const graphql = require('graphql');
const { GraphQLObjectType, GraphQLString } = graphql;

const BookType = new GraphQLObjectType({
    name: 'Book',
    fields: () => ({
        id: {type: GraphQLString},
        title: {type: GraphQLString},
        genre: {type: GraphQLString}
    })
})

We first get the reference to graphql package and use ES6 object de-structuring to pull out GraphQLObjectType and GraphQLString from the graphql package.

Then, we create a new GraphQLObjectType. The constructor takes an object as input. It has two properties – the name of the object type (in this case, we call it Book) and fields that are part of the object. There are three fields – id, title and genre. All of these are of type GraphQLString. The graphql package has similar types for other primitive data types such as integer, boolean and so on.

3 – The Root Query

Next step is to create the root query.

A root query is nothing but an entry point to our application. There can be multiple root queries in an application depending on the needs of the client.

For this example, we create a root query to fetch a book based on its id.

const RootQuery = new GraphQLObjectType({
    name: 'RootQueryType',
    fields: {
        book: {
            type: BookType,
            args: {id: {type: GraphQLString}},
            resolve(parent, args) {
                return _.find(books, {id: args.id})
            }
        }
    }
})

As you can see, we create another GraphQLObjectType. This time the name of the object is RootQueryType. The fields are basically the queries supported by our application.

For example, we support a query named book. The type property denotes the type of data that this query supports (in this case, it is the BookType. The args denote the type of input arguments to the query. In other words, the id of the book.

Lastly, we have the resolve() function. This function basically resolves the query and returns a response. To resolve the query, this function may reach out to a database or some other service. In this example, we use lodash to search a list of hard-coded books. Below is the complete code for the same.

const graphql = require('graphql');
const _ = require('lodash')

const { GraphQLObjectType, GraphQLString } = graphql;


var books = [
    {id: '1', title: 'The Foundation', genre: 'Science Fiction'},
    {id: '2', title: 'The Fellowship of the Ring', genre: 'Fantasy'},
    {id: '3', title: 'The Eye of the World', genre: 'Fantasy'}
]

const BookType = new GraphQLObjectType({
    name: 'Book',
    fields: () => ({
        id: {type: GraphQLString},
        title: {type: GraphQLString},
        genre: {type: GraphQLString}
    })
})

const RootQuery = new GraphQLObjectType({
    name: 'RootQueryType',
    fields: {
        book: {
            type: BookType,
            args: {id: {type: GraphQLString}},
            resolve(parent, args) {
                return _.find(books, {id: args.id})
            }
        }
    }
})

4 – Creating the GraphQL Schema

We now have all the pieces to create a GraphQL Schema.

Below is the final code of the schema.js file.

const graphql = require('graphql');
const _ = require('lodash')

const { GraphQLObjectType, GraphQLString, GraphQLSchema } = graphql;

//Dummy data for demo purpose
var books = [
    {id: '1', title: 'The Foundation', genre: 'Science Fiction'},
    {id: '2', title: 'The Fellowship of the Ring', genre: 'Fantasy'},
    {id: '3', title: 'The Eye of the World', genre: 'Fantasy'}
]

//This is the type of data supported by the queries
const BookType = new GraphQLObjectType({
    name: 'Book',
    fields: () => ({
        id: {type: GraphQLString},
        title: {type: GraphQLString},
        genre: {type: GraphQLString}
    })
})

//Each field is a type of root query. In other words, all are entry points into the Graph
const RootQuery = new GraphQLObjectType({
    name: 'RootQueryType',
    fields: {
        book: {
            type: BookType,
            args: {id: {type: GraphQLString}},
            resolve(parent, args) {
                return _.find(books, {id: args.id})
            }
        }
    }
})

//Initialize and export the schema
module.exports = new GraphQLSchema({
    query: RootQuery
})

As you can see, we also grab the GraphQLSchema property from the graphql package and use to it initialize a new schema. The input to the constructor object is nothing but the RootQuery. We use module.exports to export the schema so that it will be available in the server.js.

5 – Testing the GraphQL Schema

We can now use the graphiql interface to trigger a query with a particular book id as input.

graphql schema

See above screenshot where we trigger the query and get the response from the hard-coded books array. As you can see, the book object is wrapped within the top-level data object.

If we request data for an id that is not present, we get a null object as below.

{
  "data": {
    "book": null
  }
}

Conclusion

With this, we have learnt how to create a GraphQL Schema with GraphQL.js and Express. We used GraphQLObjectType to create the GraphQL data object and the GraphQL query type.

If you have any comments or queries about this post, please feel free to mention in the comments section below.

Categories: BlogGraphQL

Saurabh Dashora

Saurabh is a Software Architect with over 12 years of experience. He has worked on large-scale distributed systems across various domains and organizations. He is also a passionate Technical Writer and loves sharing knowledge in the community.

2 Comments

Barz · December 15, 2022 at 6:43 am

This is basically how I have my graphql set up, but now working on authentication and need to access the request object. Not sure how to do that.

Leave a Reply

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