Currently when you do a mutation, you just have createPost(field1, field2, ... , fieldN), which means it's quite difficult to use variables on complex mutations.
A better route would be to allow a input type, for instance: createPost(post: Post) — in this case just using the Post type.
A further extension on this would be to allow using "Input Types", which are effectively subsets of the entity's Type, for instance: createPost(post: CreatePostInput)
Where Post is defined as:
type Post {
id: ID!
createdAt: DateTime
updatedAt: DateTime
title: String!
body: String!
poster: User!
}
And CreatePostInput is defined as:
type CreatePostInput {
title: String!
body: String!
}
By allowing these "Input Types", we can effectively achieve finer grain creation. It also prevents code like the following (taken from graphql-training/graphql-training.github.io)
// You can also use `graphql` for GraphQL mutations
export default graphql(gql`
mutation createTrainingRequest(
$name: String!
$email: String!
$companyName: String
$attendees: Int!
$modules: [TRAINING_REQUEST_MODULES!]!
$additionalDetails: String
$city: String!
$country: String!
$diversityRequested: Boolean!
$onsiteRequested: Boolean!
) {
createTrainingRequest(
name: $name
email: $email
companyName: $companyName
attendees: $attendees
modules: $modules
additionalDetails: $additionalDetails
city: $city
country: $country
diversityRequested: $diversityRequested
onsiteRequested: $onsiteRequested
) {
id
}
}
`)(RequestForm);
Instead, I could've just done:
// You can also use `graphql` for GraphQL mutations
export default graphql(gql`
mutation createTrainingRequest(
$trainingRequest: CreateTrainingRequestInput!
) {
createTrainingRequest(trainingRequest: $trainingRequest) {
id
}
}
`)(RequestForm);
This is inspired by this example in the GraphQL Documentation:

Would be using the Relay API an option for you as well?
Maybe, but it greatly complicates things. I'd say using Input Types is a general great practice that should be encouraged.
There are a couple of alternatives from the top of my head:
1) Embed the input type into existing mutations. The upside would be that you could choose between providing a "combined object" matching input type vs spreading out all fields directly. The big downside of this approach is that all arguments would need to be optional (non-required). That means we'd lose a lot of the type system's power along the way.
2) An alternative approach would be to generate additional mutations like createPostWrapped(post: { ... }. The upside of this would be that it preserves the expressiveness of the typesystem. But obviously this approach would clutter the query namespace quite a lot. (This could be solve though by selectively configuring which queries should be exposed in the schema at all).
3) A third approach would be to make it a configuration option on a project basis which "layout" of mutations you'd prefer. This could however confuse people quite a bit.
Would be interested to hear what your thoughts are on this and especially if you'd see any other viable options?
I'd say a configuration option, perhaps per model, would be best.
But also, new projects should be created in the input type mode, and allow you to switch if you want.
👍 to being able to select which mutations and queries are exposed. This would be a great feature
We're looking to enhance the Simple API with an object input argument as described in this feature request. This would be a great opportunity to work on other feature requests that require an input object, like #45.
This is happening :-) Thanks for the great suggestion! https://github.com/graphcool/framework/issues/353
Most helpful comment
This is happening :-) Thanks for the great suggestion! https://github.com/graphcool/framework/issues/353