Creating GraphQL Input Types with Express-GraphQL

John Au-Yeung - Jan 25 '21 - - Dev Community

Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62

Subscribe to my email list now at http://jauyeung.net/subscribe/

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'));
Enter fullscreen mode Exit fullscreen mode

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) },
  }
});
Enter fullscreen mode Exit fullscreen mode

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;
      }
    }
  }
});
Enter fullscreen mode Exit fullscreen mode

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;
      }
    }
  }
});
Enter fullscreen mode Exit fullscreen mode

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
  }
}
Enter fullscreen mode Exit fullscreen mode

We get:

{
  "data": {
    "createPerson": {
      "firstName": "John",
      "lastName": "Doe"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

as the response.

When we make a query as follows:

{
  person {
    firstName
    lastName
  }
}
Enter fullscreen mode Exit fullscreen mode

We get back:

{
  "data": {
    "person": {
      "firstName": "John",
      "lastName": "Doe"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

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.

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