Creating GraphQL Input Types with Express-GraphQL

John Au-Yeung - Jul 24 '20 - - Dev Community

With GraphQL, we can create scalar types as we do with object types and other compound data types.

In this article, we’ll look at how to create GraphQL input types with the GraphQLInputObjectType constructor.

GraphQLInputObjectType Constructor

We can use the GraphQLInputObjectType constructor to create a new input type.

To do this, we pass in an object to the GraphQLInputObjectType constructor with the name property to set the name of our input type, and then a fields object with the field names as the keys and the values are objects with the type property to specify the types of the fields.

To specify a required field, we use the GraphQLNonNull constructor. Also, we can specify a default value by specifying a value for the defaultValue property.

For example, we can specify a mutation as follows:

const express = require('express');
const graphqlHTTP = require('express-graphql');
const graphql = require('graphql');

class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }
}

const PersonInputType = new graphql.GraphQLInputObjectType({
  name: 'PersonInput',
  fields: {
    firstName: { type: new graphql.GraphQLNonNull(graphql.GraphQLString) },
    lastName: { type: new graphql.GraphQLNonNull(graphql.GraphQLString) },
  }
});

const PersonType = new graphql.GraphQLObjectType({
  name: 'Person',
  fields: {
    firstName: { type: graphql.GraphQLString },
    lastName: { type: graphql.GraphQLString },
  }
});

let person = new Person('Jane', 'Smith');

const mutationType = new graphql.GraphQLObjectType({
  name: 'Mutation',
  fields: {
    createPerson: {
      type: PersonType,
      args: {
        person: {
          type: new graphql.GraphQLNonNull(PersonInputType),
        },
      },
      resolve: (_, { person: { firstName, lastName } }) => {
        person = new Person(firstName, lastName);
        return person;
      }
    }
  }
});

const queryType = new graphql.GraphQLObjectType({
  name: 'Query',
  fields: {
    person: {
      type: PersonType,
      resolve: () => {
        return person;
      }
    }
  }
});

const schema = new graphql.GraphQLSchema({ query: queryType, mutation: mutationType });

const app = express();
app.use('/graphql', graphqlHTTP({
  schema: schema,
  graphiql: true,
}));

app.listen(3000, () => console.log('server started'));

In the code above, we created the PersonInputType input type as follows:

const PersonInputType = new graphql.GraphQLInputObjectType({
  name: 'PersonInput',
  fields: {
    firstName: { type: new graphql.GraphQLNonNull(graphql.GraphQLString) },
    lastName: { type: new graphql.GraphQLNonNull(graphql.GraphQLString) },
  }
});

We used the GraphQLInputObjectType constructor and we pass in an object with the name field with value 'PersonInput' to specify the name of the type.

Then in the fields property, we specified that the type has a firstName and lastName field, each of which is required since we used the GraphQLNonNull constructor with the GraphQLString type passed into it.

Input types can only be used with mutations.

We then create a mutation that takes a PersonInputType argument as follows:

const mutationType = new graphql.GraphQLObjectType({
  name: 'Mutation',
  fields: {
    createPerson: {
      type: PersonType,
      args: {
        person: {
          type: new graphql.GraphQLNonNull(PersonInputType),
        },
      },
      resolve: (_, { person: { firstName, lastName } }) => {
        person = new Person(firstName, lastName);
        return person;
      }
    }
  }
});

In the code above, we created a createPerson mutation with the type specifying the output type, which is the PersonType which we specified in the code.

In the args property, we specified the person argument with the type set to the PersonInputType . This specifies that out mutation takes the PersonInuptType input type object.

Then in our resolve function, we get the firstName and lastName from the args parameter in the second parameter and created a new Person object, set it to person and returns it.

All GraphQL server apps have to have a root query type, so we also specified a queryType as follows:

const queryType = new graphql.GraphQLObjectType({
  name: 'Query',
  fields: {
    person: {
      type: PersonType,
      resolve: () => {
        return person;
      }
    }
  }
});

We return a Person object and returns the person variable.

Then when we make a mutation as follows:

mutation {
  createPerson(person: {firstName: "John", lastName: "Doe"}){
    firstName
    lastName
  }
}

We get:

{
  "data": {
    "createPerson": {
      "firstName": "John",
      "lastName": "Doe"
    }
  }
}

as the response.

When we make a query as follows:

{
  person {
    firstName
    lastName
  }
}

We get back:

{
  "data": {
    "person": {
      "firstName": "John",
      "lastName": "Doe"
    }
  }
}

Conclusion

We can create a GraphQL input type with the GraphQLInputObjectType constructor with the name and fields properties passed in together in one object to the constructor.

The name field has the name and the fields object has fields and the type.

We can use the GraphQLNonNull to specify that a field is required.

Then in our mutation, we specify the input data type in the args property.

The post Creating GraphQL Input Types with Express-GraphQL appeared first on The Web Dev.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .