---
title: 3. Adding mutations to your API
---

## Overview

In this chapter you're going to add some write capability to your API. You'll learn about:

- Writing GraphQL mutations
- Exposing GraphQL objects for mutation operations
- Working with GraphQL Context
- Working with GraphQL arguments

To keep our learning gradual we'll stick to in-memory data for now but rest assured a proper databases is coming in an upcoming chapter.

## Wire up the context

The first thing we'll do is setup an in-memory database and expose it to our resolvers using the _GraphQL context_.

The GraphQL Context is a plain JavaScript object shared across all resolvers. Your GraphQL server creates a new one for each request. It is a good place to, for example, attach information about the logged-in user.

So go ahead and create the database with its type definition.

```bash-symbol copy
touch api/db.ts
```

```ts
// api/db.ts

export interface Post {
  id: number
  title: string
  body: string
  published: boolean
}

export interface Db {
  posts: Post[]
}

export const db: Db = {
  posts: [{ id: 1, title: 'Nexus', body: '...', published: false }],
}
```

Now to expose it in our GraphQL context there is two things we need to do:

1. Pass the `db` object to our GraphQL server context
1. Let Nexus know what the type of our context is

We'll begin by creating a new module to hold out the context and its type.

```bash-symbol copy
touch api/context.ts
```

```ts
// api/context.ts
import { Db, db } from './db'

export interface Context {
  db: Db
}

export const context = {
  db
}
```

Then we'll pass our in-memory database to our GraphQL server

<TabbedContent tabs={['Diff', 'Code']}>

<tab>

```ts
// api/server.ts
import { ApolloServer } from 'apollo-server'
+import { context } from './context'
import { schema } from './schema'

export const server = new ApolloServer({
  schema,
+  context 
})
```

</tab>

<tab>

```ts
// api/server.ts
import { ApolloServer } from 'apollo-server'
import { context } from './context'
import { schema } from './schema'

export const server = new ApolloServer({
  schema,
  context
})
```

</tab>

</TabbedContent>

The context passed to Apollo Server can either be a function or a plain JavaScript object. For this tutorial, we've used an Object for simplicity. We would need to use a function when we need to perform some calculation or get some data from an external source based on the request and then pass that derived data on to the context for all our resolvers to use. 

For example, if a user is logged in to your application, it would be useful to have the information regarding the user available to all the resolvers and this information would have to be retrieved from your database or an external service. The code responsible for that database or service call would be placed in the function which is passed to Apollo Server as the context.

Finally, let's configure Nexus to know the type of our GraphQL context by adjusting the configuration of the `makeSchema` in our `api/schema.ts`.

<TabbedContent tabs={['Diff', 'Code']}>

<tab>

```ts
// api/schema.ts
import { makeSchema } from 'nexus'
import { join } from 'path'
import * as types from './graphql'

export const schema = makeSchema({
  types,
  outputs: {
    typegen: join(__dirname, '..', 'nexus-typegen.ts'),
    schema: join(__dirname, '..', 'schema.graphql')
  },
+  contextType: {                                    // 1
+    module: join(__dirname, "./context.ts"),        // 2
+    export: "Context",                              // 3
+  },
})
```

</tab>

<tab>

```ts
// api/schema.ts
import { makeSchema } from 'nexus'
import { join } from 'path'
import * as types from './graphql'

export const schema = makeSchema({
  types,
  outputs: {
    typegen: join(__dirname, '..', 'nexus-typegen.ts'),
    schema: join(__dirname, '..', 'schema.graphql')
  },
  contextType: {                                    // 1
    module: join(__dirname, "./context.ts"),        // 2
    export: "Context",                        // 3
  },
})
```

</tab>

</TabbedContent>

1. Option to set the context type
1. Path to the module where the context type is exported
1. Name of the export in that module

## Use the context

Now let's use this data to re-implement the `Query.drafts` resolver from the previous chapter.

<TabbedContent tabs={['Diff', 'Code']}>

<tab>

```ts
// api/graphql/Post.ts

export const PostQuery = extendType({
  type: 'Query',
  definition(t) {
    t.list.field('drafts', {
      type: 'Post',
-      resolve() {
-        return [{ id: 1, title: 'Nexus', body: '...', published: false }]
+      resolve(_root, _args, ctx) {                              // 1
+        return ctx.db.posts.filter(p => p.published === false)  // 2
      },
    })
  },
})
```

</tab>

<tab>

```ts
// api/graphql/Post.ts

export const PostQuery = extendType({
  type: 'Query',
  definition(t) {
    t.list.field('drafts', {
      type: 'Post',
      resolve(_root, _args, ctx) {                             // 1
       return ctx.db.posts.filter(p => p.published === false)  // 2
      },
    })
  },
})
```

</tab>

</TabbedContent>

1. Context is the _third_ parameter, usually identified as `ctx`
2. Return the filtered data by un-published posts, _aka_ drafts . Nexus makes sure the types line up.

## Your first mutation

Alright, now that we know how to wire things into our context, let's implement our first mutation. We're going to make it possible for your API clients to create new drafts.

This mutation will need a name. Rather than simply call it `createPost` we'll use language from our domain. In this case `createDraft` seems reasonable. There are similarities with our previous work with `Query.drafts`:

- `Mutation` is a root type, its fields are entrypoints.
- We can colocate mutation fields with the objects they relate to or centralize all mutation fields.

As before we will take the collocation approach.

<ParallelBlocks>

<block>

<!-- prettier-ignore -->
```ts
// api/graphql/Post.ts

export const PostMutation = extendType({
  type: 'Mutation',
  definition(t) {
    t.nonNull.field('createDraft', {
      type: 'Post',
      resolve(_root, args, ctx) {
        ctx.db.posts.push(/*...*/)
        return // ...
      },
    })
  },
})
```

</block>

<block>

```graphql
Mutation {
  createDraft: Post!
}
```

</block>

</ParallelBlocks>

We need to get the client's input data to complete our resolver. This brings us to a new concept, GraphQL arguments. Every field in GraphQL may accept them. Effectively you can think of each field in GraphQL like a function, accepting some input, doing something, and returning an output. Most of the time "doing something" is a matter of some read-like operation but with `Mutation` fields the "doing something" usually entails a process with side-effects (e.g. writing to the database).

Let's revise our implementation with GraphQL arguments.

<TabbedContent tabs={['Diff', 'Code', 'SDL']}>

<tab>


```ts
import { objectType, extendType } from 'nexus'
+import { objectType, extendType, stringArg, nonNull } from 'nexus'

export const PostMutation = extendType({
  type: 'Mutation',
  definition(t) {
    t.nonNull.field('createDraft', {
      type: 'Post',
+      args: {                                        // 1
+        title: nonNull(stringArg()),                 // 2
+        body: nonNull(stringArg()),                  // 2
+      },
      resolve(_root, args, ctx) {
+        const draft = {
+          id: ctx.db.posts.length + 1,
+          title: args.title,                         // 3
+          body: args.body,                           // 3
+          published: false,
+        }
+        ctx.db.posts.push(draft)
+        return draft
-        ctx.db.posts.push(/*...*/)
-        return // ...
      },
    })
  },
})
```

</tab>

<tab>

```ts
import { objectType, extendType, stringArg, nonNull } from 'nexus'

export const PostMutation = extendType({
  type: 'Mutation',
  definition(t) {
    t.nonNull.field('createDraft', {
      type: 'Post',
      args: {                                        // 1
        title: nonNull(stringArg()),                 // 2
        body: nonNull(stringArg()),                  // 2
      },
      resolve(_root, args, ctx) {
        const draft = {
          id: ctx.db.posts.length + 1,
          title: args.title,                         // 3
          body: args.body,                           // 3
          published: false,
        }
        ctx.db.posts.push(draft)
        return draft
      },
    })
  },
})
```

</tab>

<tab>

```ts
Mutation {
-  createDraft: Post
+  createDraft(title: String!, body: String!): Post!
}
```

</tab>

</TabbedContent>

1. Add an `args` property to the field definition to define its args. Keys are arg names and values are type specifications.
2. Use the Nexus helpers for defining an arg type. There is one such helper for every GraphQL scalar such as `intArg` and `booleanArg`. If you want to reference a type like some InputObject then use `arg({ type: "..." })`. You can use the helpers `nonNull` and `nullable` to adjust the nullability type of the arg. You can use the functional helper `list` to turn the arg into a list type too.
3. In our resolver, access the args we specified above and pass them through to our custom logic. If you hover over the `args` parameter you'll see that Nexus has properly typed them including the fact that they cannot be undefined.

## Model the domain: Part 2

Before we wrap this chapter let's flush out our schema a bit more. We'll add a `publish` mutation to transform a draft into an actual published post.

<TabbedContent tabs={['Diff', 'Content', 'SDL']}>

<tab>

```ts
// api/graphql/Post.ts
-import { objectType, extendType, stringArg, nonNull } from 'nexus'
+import { objectType, extendType, stringArg, nonNull, intArg } from 'nexus'

export const PostMutation = extendType({
  type: 'Mutation',
  definition(t) {
    // ...
+    t.field('publish', {
+      type: 'Post',
+      args: {
+        draftId: nonNull(intArg()),
+      },
+      resolve(_root, args, ctx) {
+        let draftToPublish = ctx.db.posts.find(p => p.id === args.draftId)
+
+        if (!draftToPublish) {
+          throw new Error('Could not find draft with id ' + args.draftId)
+        }
+
+        draftToPublish.published = true
+
+        return draftToPublish
+      },
+    })
  },
})
```

</tab>

<tab>

```ts
// api/graphql/Post.ts
import { objectType, extendType, stringArg, nonNull, intArg } from 'nexus'

export const PostMutation = extendType({
  type: 'Mutation',
  definition(t) {
    // ...
    t.field('publish', {
      type: 'Post',
      args: {
        draftId: nonNull(intArg()),
      },
      resolve(_root, args, ctx) {
        let draftToPublish = ctx.db.posts.find(p => p.id === args.draftId)

        if (!draftToPublish) {
          throw new Error('Could not find draft with id ' + args.draftId)
        }

        draftToPublish.published = true

        return draftToPublish
      },
    })
  },
})
```

</tab>

<tab>

```ts
type Mutation {
  createDraft(body: String!, title: String!): Post!
+  publish(draftId: Int!): Post
}
```

</tab>

</TabbedContent>

Then, we'll let API clients read these published posts.

<TabbedContent tabs={['Diff', 'Content', 'SDL']}>

<tab>

```ts
// api/graphql/Post.ts
import { extendType } from 'nexus'

export const PostQuery = extendType({
  type: 'Query',
  definition(t) {
    // ...

+    t.list.field('posts', {
+      type: 'Post',
+      resolve(_root, _args, ctx) {
+        return ctx.db.posts.filter(p => p.published === true)
+      },
+    })

  },
})
```

</tab>

<tab>

```ts
// api/graphql/Post.ts
import { extendType } from 'nexus'

export const PostQuery = extendType({
  type: 'Query',
  definition(t) {
    // ...

    t.list.field('posts', {
      type: 'Post',
      resolve(_root, _args, ctx) {
        return ctx.db.posts.filter(p => p.published === true)
      },
    })

  },
})
```

</tab>

<tab>

```graphql
type Query {
  drafts: [Post]!
+  posts: [Post]
}
```

</tab>

</TabbedContent>

## Try it out

Great, now head on over to the GraphQL Playground and run this query (left). If everything went well, you should see a response like this (right):

<ParallelBlocks>
  
<block>

```graphql copy
mutation {
  publish(draftId: 1) {
    id
    title
    body
    published
  }
}
```

</block>

<block>

```json
{
  "data": {
    "publish": {
      "id": 1,
      "title": "Nexus",
      "body": "...",
      "published": true
    }
  }
}
```

</block>

</ParallelBlocks>

Now, that published draft should be visible via the `posts` Query. Run this query (left) and expect the following response (right):


<ParallelBlocks>

<block>

```graphql copy
query {
  posts {
    id
    title
    body
    published
  }
}
```

</block>

<block>

```json
{
  "data": {
    "posts": [
      {
        "id": 1,
        "title": "Nexus",
        "body": "...",
        "published": true
      }
    ]
  }
}
```

</block>

</ParallelBlocks>

## Wrapping up

Congratulations! You can now read and write to your API.

But, so far you've been validating your work by manually interacting with the Playground. That may be reasonable at first (depending on your relationship to TDD) but it will not scale. At some point you are going to want automated testing. Nexus takes testing seriously and in the next chapter we'll show you how. See you there!

<ButtonLink color="dark" type="primary" href="/getting-started/tutorial/chapter-testing-your-api">
  Next &rarr;
</ButtonLink>
