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

Schema extracting does not complete when input and result use the same type that has nested data types #543

Closed
oofp opened this issue Oct 7, 2020 · 6 comments · Fixed by #561
Labels
bug Something isn't working scope/server morpheus-graphql

Comments

@oofp
Copy link

oofp commented Oct 7, 2020

Here as an example:

data UserType = UserManager | UserTechLead | UserDev | UserQA deriving (Generic, GQLType)
data UserName = UserName 
  { firstName :: Text
  , lastName :: Text
  } deriving (Generic, GQLType)
data User = User
  { userName :: UserName
  , userType :: UserType
  , userDsc :: Text
  } deriving (Generic, GQLType)   
data Query m = Query
  { user :: User -> m User
  } deriving (Generic, GQLType)
resolveUserQ :: User -> ResolverQ e IO User
resolveUserQ usr = return usr  

UserName is nested inside User. It compiles successfully but schema retrieval stuck

@kamek-pf
Copy link
Contributor

I think Morpheus is currently lacking support for nested input types.
I can reproduce this just by having nested input types, regardless of what the return type is.

@oco-adam
Copy link

I can also reproduce this just by having nested input object types. Is there a suggested workaround for this other than flattening everything to remove nesting?

@kamek-pf
Copy link
Contributor

I found solution.
If you need to use a record as a nested input, instead of deriving GQLType, you can write the instance manually and set the proper kind:

data MainThing = MainThing
   { input :: NestedThing
   }
   deriving (Generic, Show, GQLType)

-- Nested fields, requires manually deriving GQLType to set the INPUT kind
data NestedThing = NestedThing
   { field1 :: Text
   , field2 :: Text
   }
   deriving (Generic, Show)

instance GQLType NestedThing where
   type KIND NestedThing = INPUT
   description _ = Just "Nested thing docs"

Maybe we could send a PR to update the docs and make this more obvious ?

@oco-adam
Copy link

@kamek-pf I can confirm that your solution worked for me - thank you! :)

I'm a Haskell beginner and it definitely would have helped me if this was included in the docs, so I think a PR to update the docs would be a good idea.

@nalchevanidze
Copy link
Member

@kamek-pf @oco-adam it is not nesting, problem is that you use Output Type as Input Type. that is not allowed in GraphQL.

currently the library does not report an error message about this violation, which will be fixed in the future

@nalchevanidze nalchevanidze added bug Something isn't working scope/server morpheus-graphql labels Nov 25, 2020
@nalchevanidze
Copy link
Member

now you can fix it with GQLTypeOptions supports new option prefixInputType.

it will fix your problem, if you derive them with it (like in this example)

data UserType = UserManager | UserTechLead | UserDev | UserQA deriving (Generic, GQLType)

data UserName = UserName 
  { firstName :: Text
  , lastName :: Text
  } deriving (Generic)

instance GQLType UserName where
    typeOptions _ opt = opt {prefixInputType = True}

data User = User
  { userName :: UserName
  , userType :: UserType
  , userDsc :: Text
  } deriving (Generic, GQLType)   

data Query m = Query
  { user :: User -> m User
  } deriving (Generic, GQLType)


resolveUserQ :: User -> ResolverQ e IO User
resolveUserQ usr = return usr  

so will graphql generate following schema.

enum UserType {
  UserManager 
  UserTechLead 
  UserDev 
  UserQA
} 

input InputUserName { 
  firstName : String!
  lastName : String!
} 

type UserName { 
  firstName : String!
  lastName : String!
} 

type User { 
  userName : UserName!
  userType : UserType!
  userDsc : String!
}   

type Query {
  user ( 
    userName : InputUserName!
    userType : UserType!
    userDsc : String!
  ): User
} 

notice:

  1. argument userNameuses input type InputUserName
  2. we don't have to generate input type for type User since its fields are represented as arguments

otherwise you will get error message :

{
  "errors": [
    {
      "message": "It appears that the Haskell type \"UserName\" was used as both input and output type, which is not allowed by GraphQL specifications.\n\n If you enable \"{ prefixInputType = True }\" in \"GQLType.typeOptions\", the compiler can generate a new input type \"InputUserName\" to solve this problem.",
      "locations": []
    }
  ]
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working scope/server morpheus-graphql
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants