Javascript Tutorials Web Development

Getting Started with GraphQL

May 11th, 2016 | By Camilo Reyes | 4 min read

GraphQL is a data query language and runtime. It is also a declarative, compositional, and strong-typed query language for querying dynamic data with a strong-typed schema.

The client gets to pick what it needs based on declarative syntax. The data is a hierarchical set of fields and queries that resemble the data. I like to think of it as a structured query language without SQL. This makes it easy for a product engineer to describe the data with declarative syntax.

Facebook has used this library since 2012 and recently went open source. The library has been on GitHub since 2015.

Type System

One of the features you get with GraphQL is a type system. This type system comes with introspection so you can query the types. This unit test illustrates how I query the sample schema:

const query = `
      query IntrospectionHumanTypeQuery {
        __type(name: "Human") {
          name
        }
      }
    `;

graphql.graphql(schema, query).then(function(result) {
    should(result.data.__type.name).equal('Human');
});


The schema points to a sample schema. I decided to stick with vanilla JavaScript in spite that GraphQL sits on top of Babel. Note that the query mimics the data I get back. I get a type.name which is close to the query of query { type { name } }.

There is a hierarchy between __type and name, just like the structure of the data. Queries return a Promise so I follow it up by then().

Unto the crux of this schema, below is the Human type I created:

const humanType = new graphql.GraphQLObjectType({
    name: 'Human',
    fields: {
        id: {
            type: new graphql.GraphQLNonNull(graphql.GraphQLInt)
        },
        name: {
            type: graphql.GraphQLString
        }
    }
});


GraphQL gives many options when defining the schema. I get GraphQLInt, GraphQLString for example. To make it awesome, I've added a constraint that makes the id non-nullable.

One big gotcha here is that GraphQL schemas need a query type to make them queryable. Below is the query type:

const queryType = new graphql.GraphQLObjectType({
    name: 'Query',
    fields: {
        human: {
            type: humanType,
            args: {
                id: {
                    type: new graphql.GraphQLNonNull(graphql.GraphQLInt)
                }
            },
            resolve: function(root, args) {
                return data[args.id];
            }
        }
    }
});


The queryType defines the way I expect to query the schema. Note the resolve callback, this gets called when the Promise gets fulfilled. You can just point this callback to a real call such as a database lookup.

Here, data is just plain old JSON. This callback executes within an asynchronous context. The same type of system used in humanType applies to queries. I expect to query this schema based on an id that is a GraphQLInt and non-nullable.

To finish the schema based on this type of system, we need a schema type:

const schema = new graphql.GraphQLSchema({
    query: queryType,
    types: [humanType]
});


I tell GraphQL precisely what I want. I need a humanType that gets queried by a queryType. I hope you can see how the type system comes together.

Validation

The upside of having a humanType and a queryType on the schema is validation. Say, I want to query the schema without arguments, like the test below:

 const query = `
      query HumanWithoutArgument {
        human {
        }
      }
    `;

graphql.graphql(target, query).then(function(result) {
    should.exist(result.errors);
});


Because I put a non-nullable constraint on the query type, this query fails. The test expects to see errors due to constraints on the type. This validation mechanism is a direct gain from the type system. One other validation one gets for free is that it has to be of type GraphQLInt. This is an integer type.

A query like a human(id: "1") { name } will fail. Adding double quotes around the number tells the type system to expect a GraphQLString type. There are many scalar types available that add richness to the validation mechanism.

The type system is powerful for expressive queries one can validate. Armed with this arsenal of knowledge, let's talk about querying the data.

Queries

Query composition derives from the type system. The example below illustrates this:

http://localhost:1337/?query={human(id:1){id,name}}


This query expects to see a human type with an integer id equal to 1. This human type contains a hierarchy of field types such as id and name. If you go back to the schema, this declarative query is almost identical. The query query string is just the way I pass the query into GraphQL. Below is the result I got back in application/json content-type:

{
    "data": {
        "human": {
            "id": 1,
            "name": "Obi-Wan Kenobi"
        }
    }
}


I get back a data type that contains the result of the query. The client gets to decide which field types to query. I could have just queried the name, for example, such as {human(id:1){name}}. If I donʼt specify a hierarchy like {human(id:1){}} then validation returns with a failure.

To set up this GraphQL API in the node, one can do:

var app = http.createServer(function(req, res) {
    const query = url.parse(req.url, true).query.query;

    graphql.graphql(schema, query).then(function(queryResult) {
        if (queryResult.errors) {
            res.writeHead(400, headers);

            res.end(JSON.stringify({
                error: queryResult.errors[0].message
            }));
        } else {
            res.writeHead(200, headers);

            res.end(JSON.stringify(queryResult));
        }
    });
});


The url library gives me a parse function to get the query string. Once the Promise gets fulfilled, I use JSON.stringify to convert to hypertext. The queryResult.errors is an Error type. This is why I get a message property that comes from the Error object in plain JavaScript.

Conclusion

GraphQL leaves it to the imagination to come up with nice ways of slicing and dicing data. Queries that are just objects that come from products in the real world. Feel free to check out the rest of my demo on GitHub.

Jscrambler

The leader in client-side Web security. With Jscrambler, JavaScript applications become self-defensive and capable of detecting and blocking client-side attacks like Magecart.

View All Articles

Must read next

Web Security

Build a GraphQL API with Node

Get started with GraphQL by building an API server with Node.js and Express which can be used to create, read, update and delete contacts from an SQLite DB.

May 24, 2019 | By Ahmed Bouchefra | 6 min read

Javascript

Developing An Isomorphic GraphQL App With React

Check more info about isomorphic programming in JavaScript with this short demo, while leveraging React and GraphQL

July 21, 2016 | By João Carvalho | 4 min read

Section Divider