- [Mutations](#mutations)
  - [Create](#create)
    - [Example](#example)
  - [Update](#update)
    - [Examples](#examples)
      - [Update the city name and push onto neighborhoods](#update-the-city-name-and-push-onto-neighborhoods)
      - [Update the user nested with city with passing conditions](#update-the-user-nested-with-city-with-passing-conditions)
      - [Update the city with failing conditions](#update-the-city-with-failing-conditions)
  - [Upsert](#upsert)
    - [Examples](#examples-1)
      - [Upsert a user resulting in a create](#upsert-a-user-resulting-in-a-create)
      - [Upsert a user resulting in an update](#upsert-a-user-resulting-in-an-update)
  - [Delete](#delete)
    - [Examples](#examples-2)
      - [Delete a user](#delete-a-user)
  - [UpdateMany and DeleteMany](#updatemany-and-deletemany)
    - [Examples](#examples-3)
      - [UpdateManyUsers](#updatemanyusers)
      - [Delete Every User](#delete-every-user)
  - [Import Data](#import-data)

# Mutations

If you would rather learn by playing with a demo checkout the [client demo](https://genie-team.github.io/graphql-genie-client/).

GraphQL Genie follows [Relay GraphQL Server Specifications](https://facebook.github.io/relay/docs/en/graphql-server-specification.html#mutations). 

> Uses a common pattern for mutations, where they are root fields on the mutation type with a single argument, input, and where the input and output both contain a client mutation identifier used to reconcile requests and responses.

For each type in your model genie can generate [create](#create), [update](#update), [delete](#delete) and [upsert](#upsert) mutations.



For the below schema definition these mutations will be created:
* createCity
* createUser
* updateCity
* updateManyCities
* updateUser
* updateManyUsers
* upsertCity
* upsertUser
* deleteCity
* deleteManyCities
* deleteUser
* deleteManyUsers

Also Genie allows nested mutations, so when creating a city you can create a related user, or connect your relation to an existing user. When updating a city you can create, connect, disconnect, delete, update or upsert a related user.

```typescript 
const typeDefs = `
type City {
  id: ID! @unique
  name: String!
  neighborhoods: [String]
  user: [User]
  founded: Date
  population: Int
}
type User {
  id: ID! @unique
  displayname: String @unique
  email: String! @unique
  address: City
}
`
const genie = new GraphQLGenie({ 
  typeDefs, 
  generatorOptions: {
    generateCreate: true,
    generateUpdate: true,
    generateDelete: true,
    generateUpsert: true
  }
});
```

## Create

We will take a look at the createCity mutation

```graphql
createCity(input: CreateCityMutationInput!): CityPayload

input CreateCityMutationInput {
  data: CityCreateInput!
  # clientMutationID is optional, but if provided the same clientMutationId will be returned
  clientMutationId: String
}

input CityCreateInput {
  name: String!
  neighborhoods: [String]
  # nested create, create or connect User objects. 
  # Relation will be built automatically to the newly created City
  user: UserCreateManyWithoutAddressInput
  founded: Date
  population: Int
}

input UserCreateManyWithoutAddressInput {
  # create one or more new User objects
  create: [UserCreateWithoutAddressInput!]
  # setup a relation to one or more existing User options, you can connect based on any unique field
  connect: [UserWhereUniqueInput!]
}

input UserWhereUniqueInput {
  id: ID
  displayname: String
  email: String
}
```

### Example
Create a city and a related user

```graphql
mutation {
  createCity(input:{
    data: {
      name: "NY",
      neighborhoods: ["queens", "manhattan"]
      user: {
        create: {
          email: "steve@example.com",
          displayname: "steve"
        }
      }
    },
    clientMutationId: "createNY"
  }) {
    data {
      id
      name
      neighborhoods
      user {
        displayname
      }
    }
    clientMutationId
  }
}
```

will return

```json
{
  "data": {
    "createCity": {
      "data": {
        "id": "ID1",
        "name": "NY",
        "neighborhoods": [
          "queens",
          "manhattan"
        ],
        "user": [
          {
            "displayname": "steve"
          }
        ]
      },
      "clientMutationId": "createNY"
    }
  }
}
```

## Update

Updates also have a single argument, input. input has data and clientMutationId arguments like create. They also have a where field. The where field type is the where unique input, same that we saw in the create if we were connecting a User (UserWhereUniqueInput). You can update based on id or any other field that has the @unique directive.

Updates also have a conditions field, if the condition isn't met the update won't happen. This could of course always be done with multiple server calls and some client side logic but this can help minimize round trips. The payload will have the `unalteredData` field with the current store data (normal updates that succeed fill the `data` field).

```graphql
updateCity(input: UpdateCityMutationInput!): CityPayload

input UpdateCityMutationInput {
  data: CityUpdateInput!
  # In the case of city this will just be id, but any field with @unique would be allowed
  where: CityWhereUniqueInput!
  clientMutationId: String
  # Update will only be performed if these conditions are met
  conditions: CityWhereInput
}

# The update input is similar to the unique input. 
# Note that updating a scalar field is an input object which has fields for push, pull and set

```

A major difference between the UpdateInput and the CreateInput is on related types. While creating a City you can only create/connect a user. But while updating a City you can create, connect, disconnect, delete, update and upsert.

```graphql
type CityUpdateInput {
  name: String
  # neighborhoods is a list field, so we have the option of push, pull or set when updating
  neighborhoods: StringScalarListInput
  user: UserUpdateManyWithoutAddressInput
  founded: Date
  population: Int
}
type UserUpdateManyWithoutAddressInput {
  # create a new user that is related to this city
  create: [UserCreateWithoutAddressInput!]
  # relate an existing user to this city
  connect: [UserWhereUniqueInput!]
  # un-relate a user matching the where unique input
  disconnect: [UserWhereUniqueInput!]
  # delete a user matching the where unique input
  delete: [UserWhereUniqueInput!]
  # update a user matching the where unique input with the supplied data
  update: [UserUpdateWithWhereUniqueWithoutAddressInput!]
  # upsert a user matching the where unique input with the supplied data
  upsert: [UserUpsertWithWhereUniqueWithoutAddressInput!]
}
```

### Examples

#### Update the city name and push onto neighborhoods

Say we wanted to update the created city above, we could use the update resolver.

```graphql
mutation {
  updateCity(input:{
    where: {id: "ID1"}
      data: {
      name: "New York",
      # neighborhoods is a list field, so we have the option of push, pull or set when updating
      neighborhoods: {
        push: ["east side"]
      }      
    },
    clientMutationId: "updateNY"
    }) {
    data {
      id
      name
      neighborhoods
      user {
        displayname
      }
    }
    clientMutationId
  }
}
```

will return

```json
{
  "data": {
    "updateCity": {
      "data": {
        "id": "ID1",
        "name": "New York",
        "neighborhoods": [
          "queens",
          "manhattan",
          "east side"
        ],
        "user": [
          {
            "displayname": "steve"
          }
        ]
      },
      "clientMutationId": "updateNY"
    }
  }
}

```

#### Update the user nested with city with passing conditions

```graphql
mutation {
  updateCity(input:{
    where: {id: "ID1"}
    data: {
      name: "New York",
      user: {
        update: {
          where: {
            displayname: "steve"
          }
          data: {
            email: "steven@example.com"
          }
        }
      }
    },
    conditions: {
      match: {
        neighborhoods: "east side"
      }
    }
  }) {
    data {
      name
      user {
        displayname
        email
      }
    }
    unalteredData {
      neighborhoods
    }
  }
}
```

will return

```json
{
  "data": {
    "updateCity": {
      "data": {
        "name": "New York",
        "user": [
          {
            "displayname": "steve",
            "email": "steven@example.com"
          }
        ]
      },
      "unalteredData": null
    }
  }
}
```

#### Update the city with failing conditions
```graphql
mutation {
  updateCity(input:{
    where: {id: "ID1"}
    data: {
      name: "NYC",
    },
    conditions: {
      match: {
        neighborhoods: "bronx"
      }
    }
  }) {
    data {
      name
    }
    unalteredData {
      name
      neighborhoods
    }
  }
}
```

will return (note data is null instead of unalteredData and the name is not changed)

```json
{
  "data": {
    "updateCity": {
      "data": null,
      "unalteredData": {
        "name": New York
        "neighborhoods": [
          "queens",
          "manhattan",
          "east side"
        ],
      }
    }
  }
}
```

## Upsert

Upserts also have a single argument, input. input has where and clientMutationId arguments like update. But instead of a data field it has a create and an update field. If the where argument finds something the update data will be used and the record will be updated, otherwise a new record will be created with the create data

Upsert also have a conditions field, in case of an update the condition isn't met the update won't happen. On create conditions are ignored.

```graphql
type UpsertUserMutationInput {
  create: UserCreateInput!
  update: UserUpdateInput!
  where: UserWhereUniqueInput!
  clientMutationId: String
  conditions: UserWhereInput
}
```

### Examples

#### Upsert a user resulting in a create

```graphql
mutation {
  upsertUser(input:{
    where: {email: "zeus@example.com"},
    create: {
      email: "zeus@example.com"     
    },
    update: {
      displayname: "zeus"
    }
  }) {
    data {      
      displayname
      email
    }
  }
}
```

will return 

```json
{
  "data": {
    "upsertUser": {
      "data": {
        "displayname": null,
        "email": "zeus@example.com"
      }
    }
  }
}
```

#### Upsert a user resulting in an update

```graphql
mutation {
  upsertUser(input:{
    where: {email: "zeus@example.com"},
    create: {
      email: "zeus@example.com"     
    },
    update: {
      displayname: "zeus"
    }
  }) {
    data {      
      displayname
      email
    }
  }
}
```

will return 

```json
{
  "data": {
    "upsertUser": {
      "data": {
        "displayname": "zeus",
        "email": "zeus@example.com"
      }
    }
  }
}
```

## Delete

Deletes also have a single argument, input. input has where and clientMutationId arguments. The data returned will be of the record that used to exist

Deletes also have a conditions argument, if the conditions don't pass the delete won't be performed.

### Examples

#### Delete a user
```graphql
mutation {
  deleteUser(input:{
    where: {email: "zeus@example.com"},
    clientMutationId: "deleteUser"
  }) {
    data {      
      displayname
      email
    }
    clientMutationId
  }
}
```

will return

```json
{
  "data": {
    "deleteUser": {
      "data": {
        "displayname": "zeus",
        "email": "zeus@example.com"
      },
      "clientMutationId": "deleteUser"
    }
  }
}
```

## UpdateMany and DeleteMany

UpdateMany and DeleteMany have a single argument input. input has the same arguments (where, clientMutationId and data if an update). The difference is the where argument contains all the arguments used in [queries](https://github.com/genie-team/graphql-genie/blob/master/docs/queries.md), not just the unique fields. Many mutations return a BatchPayload which has the number of fields updated

```graphql
input UpdateManyCitiesMutationInput {
  data: CityUpdateInput!
  where: CityWhereInput!
  clientMutationId: String
}: BatchPayload

# see type queries documentation for more info on these arguments
input CityWhereInput {
  user: UserWhereInput
  exists: CityExistsInput
  match: CityMatchInput
  range: CityRangeInput
  and: [CityWhereInput!]
  or: [CityWhereInput!]
  not: CityWhereInput
}

type BatchPayload {
  # The number of nodes that have been affected by the Batch operation.
  count: Int!  
  clientMutationId: String
}
```

### Examples

#### UpdateManyUsers

```graphql
mutation {
  updateManyCities(input: {
    where: {
      exists: {
        name: true
      }
    },
    data: {
      name: "Everywhere is Earth"
    }
  }) {
    count
  }
}
```

will return

```json
{
  "data": {
    "updateManyCities": {
      "count": 2
    }
  }
}
```

#### Delete Every User

```graphql
mutation { deleteManyUsers (
  input: {
    where: {
      exists: {
        id: true
      }
    }
  }
) {
  count
}
}
```

will return

```json
{
  "data": {
    "deleteManyUsers": {
      "count": 200
    }
  }
}
```

## Import Data

If `generateMigrations` is true in the generatorOptions (defaults to true) a mutation will be created called `importData`. This is used to import/merge data into the database. See the [importRawData function](https://github.com/genie-team/graphql-genie/blob/master/docs/GraphQLGenieAPI.md#importrawdata) function of GraphQL Genie for more details as this mutation calls that function
