99designs / gqlgen

go generate based graphql server library
https://gqlgen.com
MIT License
9.94k stars 1.17k forks source link

Support for nested selection sets on _FieldSet (on @requires annotation) #1138

Open bartcpostma opened 4 years ago

bartcpostma commented 4 years ago

What happened?

We started using federation for our graphql solution. In our setup we have two graphql services, one providing items, another extending the item with breadcrumb information. In order to be able to resolve the breadcrumb information we need the id of a nested type on Item, i.e., the Variant of the Item.

According to the apollo federation specifications on the Scalar _FieldSet, it supports nested selection sets as in "variant { id }" (https://www.apollographql.com/docs/apollo-server/federation/federation-spec/#scalar-_fieldset). This does not seem to be supported by gqlgen.

I observed that gqlgen is parsing the @requires annotation argument as being 4 fields, i.e., variant, {, id and } thereby ignoring that variant has a nested selection set defined. gqlgen execution crashes at some point with: federation: federation.gotpl: template: federation.gotpl:53:50: executing "federation.gotpl" at <.TypeReference.UnmarshalFunc>: error calling UnmarshalFunc: runtime error: invalid memory address or nil pointer dereference%

What did you expect?

That gqlgen generation works for a federation setup when having the schema setup as below.

Minimal graphql.schema

service 1:

type Item @key(fields: "id") {
     id: ID!
     variant: Variant
}
type Variant {
     id: ID!
}

service 2:

extend type Item @key(fields: "id") {
     id: ID! @external
     variant: Variant @external 
     breadcrumbs: [String!]! @requires(field: "variant { id }")
}
extend type Variant {
     id: ID! @external
}

versions

pepusz commented 4 years ago

I have the same issue

We have a service where we store simple entities

#Service 1
type BlogEntry  @key(fields: "id"){
   id: ID!
   date: Date!
   chapters: [Chapter]
}

type Chapter @key(fields: "id"){
    id: ID!
    category: Category!
    title: String!
    body: String
    score: Int
}

#Service 2 - extend blog entry with a recommendation. to be able to achieve this we need content from the entry 
extend type BlogEntry @key(fields: "id") {
    id: ID! @external
    chapters: [Chapter] @external
    suggestedSomethings [Something] @requires(fields: "chapters { id body }")
}

extend type Chapter @key(fields: "id"){
    id: ID! @external
    category: Category! @external
    body: String @external
}

the error is the following:

federation: federation.gotpl: template: federation.gotpl:53:50: executing "federation.gotpl" at <.TypeReference.UnmarshalFunc>: error calling UnmarshalFunc: runtime error: invalid memory address or nil pointer dereference%

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

frederikhors commented 4 years ago

Nope.

lyueyang commented 3 years ago

Hello! I'm faced with a similar situation where I need to implement a 2nd service which extends a type from another service but I'm not able to get to the error that you guys have reached. The generator is providing me with an error stating that I'm not able to use an object as a valid type. Just wondering if there's anything you did to help prevent this issue, thank you!

extend type ShoppingCart @key(fields: "items"){
    items: [Item] @external
    totalCost: Int! @requires(fields: "items { name }")
}

extend type Item @key(fields: "name") {
    name: String! @external
}

Error I'm provided failed to load schema: federation/entity.graphql:7: cannot use [Item] as argument items because OBJECT is not a valid input typeexit status 1

versions:

oz-r commented 3 years ago

I'll throw my hat in here too:

Service 1

type Team @key(fields:"id"){
    id: String!
    members: [User]!
}

type User @key(fields:"id"){
    id: String!
    email: String!
}

Service 2

extend type Team @key(fields:"id"){
  id: String! @external
  members: [User]! @external
  things: [Thing!]! @requires(fields:"members { email }")
}

extend type User @key(fields:"id"){
  id: String! @external
  email: String! @external
}

I'm also seeing the same output as @bartcpostma and @pepusz

federation: federation.gotpl: template: federation.gotpl:54:51: executing "federation.gotpl" at <.TypeReference.UnmarshalFunc>: error calling UnmarshalFunc: runtime error: invalid memory address or nil pointer dereferenceexit status 1
bluejay9676 commented 3 years ago

Can some of the original commentors share how they worked around this?

lyueyang commented 3 years ago

Can some of the original commentors share how they worked around this?

Hello! I'm not longer working on the project as I've left my position since but I had worked around it by changing to another library instead.

After various business considerations and a pressing deadline, we favoured using another library which better supported our cases.

Apologies that this answer probably isn't as helpful as you'd hope it'd be.

bluejay9676 commented 3 years ago

@lyueyang Thanks for the reply. What was the library that you guys ended up using?

lyueyang commented 3 years ago

@lyueyang Thanks for the reply. What was the library that you guys ended up using?

We ended up choosing to go for the graph-gophers/graphql-go library along with the nautilus gateway.

The 99designs developers here have done a great job and this library is still great if you're looking to support Apollo's spec. However, as I was working from a clean slate, we could decide that the Apollo support was not necessary which is why we decided to go for this stack instead.

Hope this helps :)

carldunham commented 3 years ago

Should be fixed with https://github.com/99designs/gqlgen/pull/1669. Enjoy!

lyueyang commented 3 years ago

Should be fixed with #1669. Enjoy!

no longer working on a project with GraphQL but nonetheless, thank you for the great work!

vvakame commented 3 years ago

wow! really cool!

dariuszkuc commented 8 months ago

fixed in https://github.com/99designs/gqlgen/pull/2884