Open leebenson opened 2 years ago
I did already some attempts to implement this approach, but where are a lot of edge cases(e.g. multiple inputs, error types):
If you want to use domain errors you can try HC 12 Mutation conventions https://chillicream.com/docs/hotchocolate/defining-a-schema/mutations#input-and-payload
If you have an idea how to implement this without breaking existing codebases, please share with me :)
Thanks for the update 👍🏻
The implementation I was thinking of if I did this myself was something like:
public ISomeReturnType ResolverMethod([Validation(typeof(SomeAbstractValidator))] CreateUserInput input) {}
The idea being, an AbstractValidator<T>
could be provided to the attribute. Whenever input
was created on a new query, it would run something akin to:
var validation = await input.ValidateAsync(input);
if (!validation.IsValid)
{
return validation.ToGraphQLFormErrors()
}
The ISomeReturnType
would need to be a union that contains a FormErrors
type to compile.
I'm still trying to parse the internals of Hot Chocolate and understand how its event API works for input. It seems like it should be simple to do validation and short-circuit by returning a FormErrors
type if validation fails, in much the same way that you're currently raising an error... but I'm still following code paths to understand how that works.
Is your feature request related to a problem? Please describe.
Instead of returning an
errors
object when validation fails with the typical 'extensions' key, I'd like to convert a mutation return type into a union ofTSuccess | FormError[]
, where FormError contains a strongly typed{ field: String!, error: String! }
.Describe the solution you'd like
Parsing
errors
in a front-end client is difficult, because its shape is unknown. It could be a form error, an authentication issue, an internal server error or something else. Many web GraphQL clients treat it as a 'hard' error by default.I'd like to validate user input, converting 'errors' into a new
FormError
type. Where validation on user input is relevant, the return type should be modified to include a union accommodating both the 'success' type(s) and the potential for a user error.i.e. I'd like to wind up with something like this:
... so that if an
errors
does occur, it generally means something more severe than user input is off!Describe alternatives you've considered
I could alternatively create a wrapper for a GraphQL client (I'm using React Query, FWIW) that looks for
400
responses, parses theerrors
key, and determines the type of error.But this has two drawbacks:
TError: unknown
by default.Another alternative is to write a helper in C# that validates in the function, and converts errors into a standard
FormError
type. This is fine, but it requires modifying the signature of a mutation to accommodate every use-case where input is used... which is a little repetitive.Additional context
User input errors are common, and IMO relying on the
errors
key with a dynamic/untypedextensions
meta to determine the kind of error makes it difficult to parse what is a normal part of users interacting with the API.Rather than creating a wrapper that catches errors and handles them at the top-level, I'd rather make form errors a first-class feature of my graph. Fluent Validation is ideal for that, but I'm unsure whether there's a simple way to have this library modify the graph to allow for a union of a 'success' and FormError[] response where it's used, or I should focus instead on creating a wrapper.
In any case, thanks for a great 'glue' library! It's very useful indeed.