24
votes

I want to send graphql mutation request without sub section

mutation _ {
    updateCurrentUser(fullName: "Syava", email: "[email protected]")
}

and I am getting

{
  "errors": [
    {
      "message": "Field \"updateCurrentUser\" of type \"User\" must have a sub selection.",
      ... 
    }
  ]
}

add { id } to request works fine but I don't want

Also Schema code

const userType = new GraphQLObjectType({
  name: 'User',
  fields: () => ({
    id: { type: new GraphQLNonNull(GraphQLString) },
    fullName: { type: GraphQLString },
    email: { type: GraphQLString },
  }),
});

type: userType,
  args: {
    fullName: { type: GraphQLString },
    email: { type: new GraphQLNonNull(emailType) },
    password: { type: GraphQLString },
  },
  resolve: async (root, { fullName, email, password }, { rootValue }) => {
    const user = await User.findById(rootValue.req.user.id);

    ...

    return user;
  },
1

1 Answers

14
votes

You define the type of the field to be UserType. Even though it's a mutation, it still follows the same rules and behavior as a query. Because UserType is an object type, it requires nested fields.

mutation _ {
  updateCurrentUser(fullName: "Syava", email: "[email protected]") {
    fullName
    email
  }
}
// would respond with { fullName: 'Syava', email: '[email protected]' }

If you don't want the mutation to return a User, you can declare its type to GraphQLBoolean for example -- that's a scalar and doesn't have any nested fields.

{
  type: GraphQLBoolean,
  args: {
    fullName: { type: GraphQLString },
    email: { type: new GraphQLNonNull(emailType) },
    password: { type: GraphQLString },
  },
  resolve: async (root, { fullName, email, password }, { rootValue }) => {
    const user = await User.findById(rootValue.req.user.id);
    user.fullName = fullName;
    user.password = password; // or hashed to not store plain text passwords
    return user.save(); // assuming save returns boolean; depends on the library you use
  }
}