I like being able to define custom scalar types with GraphQL and exposing the types to the end user of the API.
A bit of controversy -> is there any reason why I should have usual changeset validation, if everything is going through GraphQL?
In theory the exposed GraphQL-schema and how your database actually looks like can be fundamentally different.
And having this opportunity is a good thing. Your GraphQL API can stay as it is, while your database actually changes as necessary to handle all those requests as efficient as possible.
In those scenarios of course you need two fold validation of incomming data.
I can see some advantages for the custom scalar approach
- you get documentation for the scalar types built in
- your graphQL is the single source of truth for how inputs are structured/validated
- Mutation responses only need to contain the record, without the need for a wrapper to return messages/status
However, I prefer to return validation errors as Data, not errors. Here’s a good blog post on the topic.
There are a several advantages:
- Changeset validations are more powerful
- Keeps all validation code in one place
- Separates “Developer Errors” from “Validations”, so they can be handled differently.
- Allows you to customize validation error messages
- Easy to test
- Decouples your GraphQL from your Database, as @NobbZ pointed out.
In practice, it’s not quite this simple.
You could, in theory, have a GraphQL mutation with no non_null fields, and string inputs, and then handle all validations - including required checks and casting to the appropriate types - in Ecto. But then you’re removing all of the introspection that is so useful. Expressing which fields are required and what types they are is important information for people developing your app. With GraphQL, documentation of field types is coupled to validation of field types - you really can’t have one without the other. So for simple types and required validations, I don’t obscure this information.