Adding Mutations with Express GraphQL
Tags: webdev, programming, javascript, graphql
Published: 2021-01-25 01:40:14

**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/**

We can create a simple GraphQL server with Express. To do this, we need the `express-graphql` and `graphql` packages.

In this article, we’ll look at how to create mutations and input types with Express and GraphQL.

Mutations and Input Types
=========================

To create mutations, we create a schema that has the `Mutation` type rather than a `Query` .

Then it’s a simple as making the API endpoint part of the top-level `Mutation` type instead of a `Query` type.

Both mutations and queries can be handled by root resolvers.

We can then create a GraphQL server that takes both queries and mutations as follows:

```
const express = require('express');  
const graphqlHTTP = require('express-graphql');  
const { buildSchema } = require('graphql');  
const crypto = require('crypto');  
const schema = buildSchema(`  
  input TodoInput {  
    text: String      
  } 

  type Todo {  
    id: ID!  
    text: String      
  } 

  type Query {  
    getTodo(id: ID!): Todo  
  } 

  type Mutation {  
    createTodo(input: TodoInput): Todo  
    updateTodo(id: ID!, input: TodoInput): Todo  
  }  
`);

class Todo {  
  constructor(id, { text }) {  
    this.id = id;  
    this.text = text;  
  }  
}

let todos = {};
const root = {  
  getTodo: ({ id }) => {  
    if (!todos[id]) {  
      throw new Error('Todo not found.');  
    }  
    return new Todo(id, todos[id]);  
  },  
  createTodo: ({ input }) => {  
    const id = crypto.randomBytes(10).toString('hex');  
    todos[id] = input;  
    return new Todo(id, input);  
  },  
  updateTodo: ({ id, input }) => {  
    if (!todos[id]) {  
      throw new Error('Todo not found');  
    }  
    todos[id] = input;  
    return new Todo(id, input);  
  },  
};

const app = express();app.use('/graphql', graphqlHTTP({  
  schema: schema,  
  rootValue: root,  
  graphiql: true,  
}));  
app.listen(3000, () => console.log('server started'));
```

In the code above, we defined our types by writing:

```
const schema = buildSchema(`  
  input TodoInput {  
    text: String      
  } 

  type Todo {  
    id: ID!  
    text: String      
  } 

  type Query {  
    getTodo(id: ID!): Todo  
  } 

  type Mutation {  
    createTodo(input: TodoInput): Todo  
    updateTodo(id: ID!, input: TodoInput): Todo  
  }  
`);
```

We created the input type `TodoInput` and the `Todo` type. Then we created the `Query` type with the `getTodo` member so that we can get our todo items.

Then in our `Mutation` , we added the `createTodo` and `updateTodo` members so that we can add and update todos.

Then we create our `Todo` class so that we can store the todo data:

```
class Todo {  
  constructor(id, { text }) {  
    this.id = id;  
    this.text = text;  
  }  
}
```

Next, we have our root resolver:

```
const root = {  
  getTodo: ({ id }) => {  
    if (!todos[id]) {  
      throw new Error('Todo not found.');  
    }  
    return new Todo(id, todos[id]);  
  },  
  createTodo: ({ input }) => {  
    const id = crypto.randomBytes(10).toString('hex');  
    todos[id] = input;  
    return new Todo(id, input);  
  },  
  updateTodo: ({ id, input }) => {  
    if (!todos[id]) {  
      throw new Error('Todo not found');  
    }  
    todos[id] = input;  
    return new Todo(id, input);  
  },  
};
```

It adds the functions with the same as we specified in our schema so that we can do something when we make some queries.

In this example, `getTodo` , we’ll return the todo with the given `id` .The todo that’s found will be returned. Otherwise, we throw an error.

In `createTodo` , we get the `input` from the query and then add the todo entry to our `todos` object, which is our fake database to store the todos. The todo that’s saved will be returned.

Then we have the `updateTodo` function to update the todo by `id` . Whatever has the given `id` will be replaced with the content of `input` . The todo that’s saved will be returned. We throw an error if a todo with the given `id` isn’t found.

Then when we go to the `/graphql` page, we can type in the following to the GraphiQL window:

```
mutation {  
  createTodo(input: {text: "eat"}) {  
    id  
    text  
  }  
}
```

Then we get something like:

```
{  
  "data": {  
    "createTodo": {  
      "id": "c141d1fda69e8d9084bd",  
      "text": "eat"  
    }  
  }  
}
```

as the response.

If we make a query for updating todo as follows:

```
mutation {  
  updateTodo(id: "e99ce10750c93793a23d", input: {text: "eat"}) {  
    id  
    text  
  }  
}
```

We get something like:

```
{  
  "data": {  
    "updateTodo": {  
      "id": "e99ce10750c93793a23d",  
      "text": "eat"  
    }  
  }  
}
```

back as the response.

If a todo isn’t found, then we get:

```
{  
  "errors": [  
    {  
      "message": "Todo not found",  
      "locations": [  
        {  
          "line": 9,  
          "column": 3  
        }  
      ],  
      "path": [  
        "updateTodo"  
      ]  
    }  
  ],  
  "data": {  
    "updateTodo": null  
  }  
}
```

as the response.

We can make the `getTodo` query as follows:

```
query {  
  getTodo(id: "e99ce10750c93793a23d"){  
    id  
    text  
  }  
}
```

Then we get:

```
{  
  "data": {  
    "getTodo": {  
      "id": "e99ce10750c93793a23d",  
      "text": "eat"  
    }  
  }  
}
```

as the response.

Conclusion
==========

We can create mutations as we do with queries.

To accept mutation operations in our GraphQL server, we make our types for storing our data, then we create our mutations by populating the `Mutation` type with our members.

We can then use the `buildSchema` function to build the schema we just specified.

Then in our root reducer, we make the functions that with the names that we specified in the type definitions.

Finally, we can make queries to our server to run the mutations.