Skip to content
This repository has been archived by the owner on Oct 2, 2024. It is now read-only.

How to handle generic Error interface in Union result #235

Open
danilofuchs opened this issue Oct 30, 2020 · 1 comment
Open

How to handle generic Error interface in Union result #235

danilofuchs opened this issue Oct 30, 2020 · 1 comment
Labels
bug Something isn't working

Comments

@danilofuchs
Copy link

danilofuchs commented Oct 30, 2020

Our schema looks like this:

type Query {
  courier(code: String!): CourierResult!
}

union CourierResult = Courier | CourierNotFoundError | InternalServerError

type Courier {
  name: String!
  code: String!
  picture: String!
}

interface Error {
  message: String!
}

type InternalServerError implements Error {
  message: String!
}

type CourierNotFoundError implements Error {
  message: String!
}

This schema was inspired by this blog post: https://blog.logrocket.com/handling-graphql-errors-like-a-champ-with-unions-and-interfaces/

When consuming this schema, we use the following query:

query courier($code: String!) {
  courier(code: $code) {
    __typename
    ... on Courier {
      name
      code
      picture
    }
    ... on CourierNotFoundError {
      message
    }
    ... on Error {
      message
    }
  }
}

This way, ... on Error is a catch-all for errors. If we add a new error in the future, backend will return it and even an outdated frontend should be able to handle it as a generic Error until we implement a specific logic for it. For instance, InternalServerError should be treated as Error as the query does not know it in advance, but the API returned it.

What Artemis currently does is the following:

class Courier$Query$CourierResult with EquatableMixin {
  Courier$Query$CourierResult();

  factory Courier$Query$CourierResult.fromJson(Map<String, dynamic> json) {
    switch (json['__typename'].toString()) {
      case r'Courier':
        return Courier$Query$CourierResult$Courier.fromJson(json);
      case r'CourierNotFoundError':
        return Courier$Query$CourierResult$CourierNotFoundError.fromJson(json);
      case r'Error':
        return Courier$Query$CourierResult$Error.fromJson(json);
      default:
    }
    return _$Courier$Query$CourierResultFromJson(json);
  }
  // ...
}

When receiving a __typename: InternalServerError, no case will be matched and it will return a generic Courier$Query$CourierResult which is not convertible to Courier$Query$CourierResult$Error and does not have the message property. This way, we may lose valuable information

What I propose is to add some kind of logic for detecting types which extend an interface, and queries which use interfaces.

I suppose I can manually create a custom parser for this.

Specs
Artemis version: 6.15.1-beta.1

build.yaml:
targets:
  $default:
    builders:
      artemis:
        options:
          schema_mapping:
            - output: lib/modules/graphql/api.graphql.dart
              schema: lib/modules/graphql/schema.graphql
              queries_glob: lib/modules/graphql/queries/**.graphql
Artemis output:
# Please paste the output of
$ flutter pub run build_runner build --verbose
#or
$ pub run build_runner build --verbose
GraphQL schema:
type Query {
  courier(code: String!): CourierResult!
}

union CourierResult = Courier | CourierNotFoundError | InternalServerError

type Courier {
  name: String!
  code: String!
  picture: String!
}

interface Error {
  message: String!
}

type InternalServerError implements Error {
  message: String!
}

type CourierNotFoundError implements Error {
  message: String!
}
GraphQL query:
query courier($code: String!) {
  courier(code: $code) {
    __typename
    ... on Courier {
      name
      code
      picture
    }
    ... on CourierNotFoundError {
      message
    }
    ... on Error {
      message
    }
  }
}
@danilofuchs danilofuchs added the bug Something isn't working label Oct 30, 2020
@vasilich6107
Copy link
Collaborator

Hi. Interesting case.
May be this could be handled by utilizing default: case...
I'll try to create reproduction and think about the fix

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants