These design principles also take heavy inspiration from the Relay Input Object Mutations Specification. There were teams where the API was pre-designed for me, projects where I built a custom API, my work on PostGraphQL designing a general purpose GraphQL API for anyone, and conversations with Facebook and other production GraphQL users. This article represents how I currently think about designing mutations for GraphQL APIs as informed by my experience working on several kinds of projects. With these design principles you should be equipped to design an effective GraphQL mutation system for your API. In other words, your mutations should look like: updatePost(input: Conclusion That argument should be named input and should have a non-null unique input object type. Mutations should only ever have one input argument. If you want to pick a different naming convention that’s fine, but stick to it! The above suggestion is the naming convention that I find works best for the largest range of use cases. Naming conventions vary on a team-by-team basis. This is because specific mutations are easier for a UI developer to write, they can be optimized by a backend developer, and only providing a specific subset of mutations makes it much harder for an attacker to exploit your API. Specific mutations that correspond to semantic user actions are more powerful than general mutations. If you start with a general “catch-all” mutation, adding extra inputs is much more difficult.ĭon’t be afraid of super specific mutations that correspond exactly to an update that your UI can make. For example, in the future you might want to send a new input argument with one of your emails. This is not a good design because it will be much more difficult to enforce the correct input in the GraphQL type system and understand what operations are available in GraphiQL. You may be tempted to create a mutation like sendEmail(type: PASSWORD_RESET) and call this mutation with all the different email types you may have. The password reset email case is also a good use case for illustrating why you want specific mutations over general mutations. This mutation is more like an RPC call then a simple CRUD action on a data type. To actually send that email you may have a mutation named: sendPasswordResetEmail. For instance, say you were building a password reset feature into your app. However, many applications have mutations that do not map directly to actions that can be performed on objects in your data model. When all your mutations are centered around a handful of object types this convention makes sense. This is useful for schemas where you want to order the mutations alphabetically (the Ruby GraphQL gem always orders fields alphabetically) and your data model is mostly object-oriented with CRUD methods (create, read, update, and delete). Some teams, like the GraphQL team at Shopify, prefer to write names the other way around - userCreate over createUser. Names like createUser, likePost, updateComment, and reloadUserFeed are preferable to names like userCreate, postLike, commentUpdate, and userFeedReload. Your mutation represents an action so start with an action word that best describes what the mutation does. In short, try to name your mutation verb first. ![]() This article will explain the rationale behind each of these points and equip you to design an effective GraphQL mutation system for your API. Nesting. Use nesting to your advantage wherever it makes sense. ![]() Unique payload type. Use a unique payload type for each mutation and add the mutation’s output as a field to that payload type.Input object. Use a single, required, unique, input object type as an argument for easier mutation execution on the client.Mutations should represent semantic actions that might be taken by the user whenever possible. Specificity. Make mutations as specific as possible.Then the object, or “noun,” if applicable. Naming. Name your mutations verb first.The main points to consider when designing your GraphQL mutations are: Designing a good GraphQL API is tricky, because you always want to balance utility and convenience with a consideration around how the API may evolve in the future.
0 Comments
Leave a Reply. |