Skip to content

ErrorPath meta in data fields #4733

@ProVir

Description

@ProVir

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.

ApolloExampleClient.zip

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions