genqlient icon indicating copy to clipboard operation
genqlient copied to clipboard

Interfaces that implement other interfaces

Open jmatichard opened this issue 2 years ago • 9 comments

Hello genqlient team !

We are trying to generate queries from a GraphQL schema that contains interfaces that implements other interfaces.

According to the GraphQL specs, this should be valid (cf. issue #373 in the GQL repository).

Here is our (simplified) schema:

scalar DateTime

interface BaseEntity {
  id: String!
  createdAt: DateTime!
  updatedAt: DateTime!
}

interface Transaction implements BaseEntity {
  id: String!
  createdAt: DateTime!
  updatedAt: DateTime!
  userId: String!
  productId: String!
}

and the genclient.yaml config:

schema: schema.graphql
operations:
  - genqlient.graphql
generated: generated.go
package: main
bindings:
  DateTime:
    type: time.Time

When we the run the go run github.com/Khan/genqlient command, we get the following error message:

schema.graphql:9: invalid schema file schema.graphql: Unexpected Name "implements"

Can you please confirm that genqlient doesn't currently support this feature ?

Do you have some hints so we can help implement this in the codebase ?

Thank you very much for your hard work on this Go library !

jmatichard avatar Jan 19 '22 16:01 jmatichard

Thanks for reporting! This is blocked by the GraphQL parser not supporting interfaces which implement interfaces (vektah/gqlparser#166). In theory genqlient should be more or less ready to support this once gqlparser does, although it's hard to be sure without being able to test it!

benjaminjkraft avatar Jan 21 '22 04:01 benjaminjkraft

PRs to vektah/gqlparser#166 are very welcome in that repository btw! See some initial work here: https://github.com/vektah/gqlparser/pull/169

StevenACoffman avatar Jan 26 '22 21:01 StevenACoffman

This is no longer blocked on gqlparser. I have some work in progress to support it on the genqlient side, but I ran into a few snags. I'll hopefully have more time to work on it soon!

benjaminjkraft avatar Mar 23 '22 18:03 benjaminjkraft

@benjaminjkraft, did the snags go away? :)

The thing is that I would love to use genqlient for next project (which has just started) but since schema is full of "implements", I would have to use something else.

stiray avatar May 17 '22 12:05 stiray

@benjaminjkraft similar situation to stiray. starting a new project and would like to use this, but the schema I'm referencing is full of implements. any updates?

edit. got this working, view my comment below

cameronbrill avatar Jun 11 '22 17:06 cameronbrill

I also have full of implements when trying to use linear graphql API @benchristel 🙏

alfaindia avatar Jun 11 '22 17:06 alfaindia

Actually, I just ran go get -u github.com/Khan/genqlient instead of go get github.com/Khan/genqlient, and I think it updated gqlparser to the working version, because I don't get that error anymore.

cameronbrill avatar Jun 11 '22 17:06 cameronbrill

Unfortunately the snags won't go away on their own! But I may have some time in the next few weeks to take another look.

Or, yes, you can try simply using the latest gqlparser; if you need to do anything significant with interfaces implementing other interfaces (e.g. embed one fragment in another) it may not work quite right but it will at least let you use the rest of the schema!

benjaminjkraft avatar Jun 13 '22 18:06 benjaminjkraft

@benjaminjkraft

I got a different error output with the same scenario of interfaces implementing other interfaces

schema.graphql:14: interface ContactInfo had non-object implementation ElectronicContact

The problem is reproducible in v0.6 & v0.7

Here a simplified version of our case

genqlient.yaml

schema: schema.graphql
operations: get-customer-details.graphql
generated: generated.go

schema.graphql :

schema {
  query: Query
}

type Query {
  customer(id: String!): Customer
}

type Customer {
  id: String!
  contactInfo: ContactInfo!
}

interface ContactInfo {
    active: Boolean!  
}

interface ElectronicContact implements ContactInfo{
  active: Boolean!
}

type ElectronicContactEmail implements ElectronicContact & ContactInfo {
  active: Boolean!
  personalEmail: String
  workEmail: String
}

type ElectronicContactTwitter implements ElectronicContact & ContactInfo {
  active: Boolean!
  personalUsername: String
  workUsername: String
}

type Phone implements ContactInfo {
  active: Boolean!
  phoneNumber: String
  countryCode: String
}

type Mail implements ContactInfo {
  active: Boolean!
  name: String
  addressLine1: String
  addressLine2: String
  zipCode: String
  country: String
}

get-customer-details.graphql

query GetAllCustomerDetails {
  customer(id: "someCustomerId") {
    id    
    contactInfo {
      ... on ElectronicContactEmail {
        personalEmail
        workEmail
      }
      ... on ElectronicContactTwitter {
        personalUsername
        workUsername
      }
      ... on Phone {
        phoneNumber
        countryCode
      }
      ... on Mail {
        name
        addressLine1
        addressLine2
        zipCode
        country
      }
    }
  }
}

rilopez avatar Mar 07 '24 18:03 rilopez