Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Morpheus inserts __typename to disambiguate unions. #687

Closed
nicuveo opened this issue Mar 4, 2022 · 3 comments · Fixed by #773 or #777
Closed

Morpheus inserts __typename to disambiguate unions. #687

nicuveo opened this issue Mar 4, 2022 · 3 comments · Fixed by #773 or #777
Labels
scope/core morpheus-graphql-core

Comments

@nicuveo
Copy link

nicuveo commented Mar 4, 2022

Description

When selecting fragments on a union, Morpheus inserts a __typename field in the answer. If I have the following schema:

union Test = Foo | Bar

type Foo {
  foo: Int!
}

type Bar {
  bar: Int!
}

type Query {
  getFooOrBar(id: Int!): Test
}

and I send the following query:

query {
  getFooOrBar(id: 1) {
    ... on Foo {
      foo
    }
    ... on Bar {
      bar
    }
  }
}

I am expecting to receive (in the case of Foo):

data:
  getFooOrBar:
    foo: 1

but instead I receive:

data:
  getFooOrBar:
    __typename: Foo
    foo: 1

Minimal program

import Data.Aeson (encode)
import Data.ByteString.Lazy as B (putStr)
import Data.Morpheus.Document
import Data.Morpheus.Types
import Data.Morpheus

[gqlDocument|
union Test = Foo | Bar

type Foo {
  foo: Int!
}

type Bar {
  bar: Int!
}

type Query {
  getFooOrBar(id: Int!): Test
}
|]

queryRoot :: Query (Resolver QUERY () IO)
queryRoot = Query {getFooOrBar}
  where
    getFooOrBar (Arg i) = pure $ case i of
      1 -> Just $ TestFoo $ Foo $ pure 1
      2 -> Just $ TestBar $ Bar $ pure 2
      _ -> Nothing

main = do
  let
    service :: GQLRequest -> IO GQLResponse
    service = interpreter $ RootResolver queryRoot Undefined Undefined
    send q = service $ GQLRequest
      { operationName = Nothing
      , variables = Nothing
      , query = q
      }
  B.putStr . encode =<< send "\
\query {\
\  getFooOrBar(id: 1) {\
\    ... on Foo {\
\      foo\
\    }\
\    ... on Bar {\
\      bar\
\    }\
\  }\
\}"
@nalchevanidze
Copy link
Member

thanks @nicuveo, why is it a problem?

@nicuveo
Copy link
Author

nicuveo commented Mar 8, 2022

It's not a huge problem, but it technically goes against the spec; this is a very pedantic issue, I'm sorry. ^^

The spec says it explicitly in § 2.4:

An operation selects the set of information it needs, and will receive exactly that information and nothing more, avoiding over‐fetching and under‐fetching data.

Additionally, there are two parts of the spec that describe how selection sets are to be handled, and they explicitly mention starting with an empty mapping and adding one entry per requested field:

  • § 6.3.2 gives the instructions on how to create the set of "grouped fields"
  • § 6.3 then explains how to construct the answer from the grouped fields

@nalchevanidze
Copy link
Member

@nicuveo all right. then how can we fix the problem with client? probably some kind of config disambigueTypes:: Boolean

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
scope/core morpheus-graphql-core
Projects
None yet
2 participants