apollo-kotlin: ErrorPath meta in data fields
Use case
Hi!
We need to be able to find graphql errors that are the reason for the absence of a particular field. There is some explicit logic in this binding, but apollo itself provides data only in the form in which they come - this is not enough.
Example:
Field data.some.value.subvalue.meta
is null, In errors there is a reason for the field data.some.value
.
Obviously, there will be an obvious reason for the null field in the form of a graph error that can be returned as a result of mapping.
But how can this be done at the code level automatically for all fields? This rule has some non-obvious backend rules that you need to know about (we tested).
I am attaching a clipping from our code to solve this problem as an example. But the main pain is manual work and the danger of typos, as well as strict compliance with implicit rules.
Start with TestApiClient
, GraphQLResponseProvider
and GraphQLValueProvider
.
Examples mappings and valid rules (from our internal wiki):
To correctly search for errors and generate the message for exception, you must explicitly specify the path to the received field in the form of a string.
Example: provider.valueOrThrow("some.data") { some?.data }
We are tied to the rules of the backend for the formation of the path of fields - it is on the path that the backend will return in the graph error if the field cannot be obtained. If we make a mistake in at least one character, if necessary, the error search for this field will stop working.
query GetSomeMovies(firstId: Int!, secondId: Int!) {
some {
... someFragment
}
# The `firstMovie` label is used instead of `movie`
firstMovie: movie(id: $firstId) {
... movieFragment
}
# The `secondMovie` label is used instead of `movie`
secondMovie: movie(id: $secondId) {
... movieFragment
}
content(contentId: $firstId) {
... on Movie {
downloadId
}
}
}
fragment someFragment on SomeData {
data {
value
}
}
fragment movieFragment on BlockData {
title
}
In code:
// There is no fragment in the path, i.e. we allegedly make the path without a fragment
val someValue = provider.valueOrThrow("some.data.value") { some?.someFragment?.data?.value }
// There is no type indication in the path, i.e. we allegedly do the path without it
val downloadId = provider.valueOrThrow("content.downloadId") { content?.onMovie?.downloadId }
// Labels are used - they replace the original name of the field/query with our
val firstMovieTitle = provider.valueOrThrow("firstMovie.title") { firstMovie?.movieFragment?.title }
val secondMovieTitle = provider.valueOrThrow("secondMovie.title") { secondMovie?.movieFragment?.title }
Describe the solution you’d like
What I would like from Apollo There is an understanding that at the level of kotlin model generation there is knowledge about how to correctly form these paths automatically.
Is it possible to somehow come up with logic so that we can get these paths from apollo itself? Perhaps there will be an analogue of ValueProvider as we did.
About this issue
- Original URL
- State: open
- Created a year ago
- Reactions: 1
- Comments: 24 (24 by maintainers)
Hi đź‘‹
Sorry I can’t give estimates at this point. It’s not being worked on actively by the Apollo team right now but if you or the community would like to help, it is very welcome.
There’s a lot of discussion in this thread already so before someone starts working on this, I would suggest creating a document in design-docs summarizing the latest state of the proposal including directive definitions for the proposed directives (if any) and samples of GraphQL operations and matching Kotlin models. That will make sure everyone is aligned with the implementation.
It seems that the path and error are generally sufficient basic meta, in this form, allowing you to configure a set of fields will not give almost any gain. Even if you leave only an error, you will need to know the correct path in this place to look for it, so I don’t see much gain in hiding the path.
I have already mentioned that we need a path not only for errors from the graphql backend, but also for creating our own errors based on incoming data. The data came - and we, based on our business logic, considered them incorrect.
There may also be other logging cases (there are plans) that are not related to the return of errors and it will also be more convenient for us to pledge the correct path. When reusing fragment mapping, the final path is unknown and we want to know it in such places.
Yes