The ability to do mutations is one of the primary features of a GraphQL client. A mutation looks like this:
mutation {
createAuthor(
_id: "john",
name: "John Carter",
twitterHandle: "@john"
) {
_id
name
}
}
You can pass multiple mutations in the same query, as well. If you want to pass the arguments as variables, you have to specify them after the mutation
keyword, and then also indicate where those variables should be used:
mutation createAuthor($_id: String, $name: String, $twitterHandle: String) {
createAuthor(
_id: $_id,
name: $name,
twitterHandle: $twitterHandle
) {
_id
name
}
}
// Need to send these variables
{
_id: "john",
name: "John Carter",
twitterHandle: "@john"
}
As you can see, this is quite verbose, with the names of the variables repeated roughly four times. There are a couple ways to solve this:
1. Relay adopts a mutation spec
https://facebook.github.io/relay/graphql/mutations.htm
mutation createAuthor {
createAuthor(input: $input) {
clientMutationId,
status {
_id
name
}
}
}
// Need to send these variables
{
input: {
_id: "john",
name: "John Carter",
twitterHandle: "@john"
}
}
This is simpler because the names of the arguments are only listed once. However, you need a specific input type for every mutation.
But the spec is another restriction on your GraphQL server.
2. Lokka has a mutation wrapper that adds the boilerplate for you
client.mutate(`
newFilm: createMovie(
title: "Star Wars: The Force Awakens",
director: "J.J. Abrams",
producers: [
"J.J. Abrams", "Bryan Burk", "Kathleen Kennedy"
],
releaseDate: "December 14, 2015"
) {
...${filmInfo}
}
`).then(response => {
console.log(response.newFilm);
});
They save you from writing the mutation X
thing. It works with any GraphQL server. The downside is, you can't actually pass variables because you would need to know the types.
Proposed API
I don't think we need to impose a spec on the server for mutations. For a low-level API, let's just implement the standard mutation API from GraphQL itself, with all of the boilerplate. To eliminate it, we probably need to know the types of the variables, which is not optimal.
This is exactly what Jonas ended up with in his example todos app:
client.mutation( {
mutation: `mutation makeListPrivate($listId: ID!){
makeListPrivate(id: $listId)
}`,
args: { 'listId': listId }
});
Let's explore additional features for this in the future, there's probably some nice stuff we can do to reduce boilerplate. And maybe we want a switch to support the Relay mutation spec.