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

Using Fragment on an interface is not working properly #263

Closed
akrejczinger opened this issue Jan 15, 2024 · 3 comments
Closed

Using Fragment on an interface is not working properly #263

akrejczinger opened this issue Jan 15, 2024 · 3 comments

Comments

@akrejczinger
Copy link

akrejczinger commented Jan 15, 2024

Ariadne-codegen version: 0.11.0

I'm trying to define a fragment on the "Error" interface. In the actual code we have multiple different error classes implementing this same interface, here I have included a minimal example. I'm not allowed to share the actual code.
The query below works from the graphql UI but ariadne-codegen doesn't generate the right code.

Inputs that don't work

pyproject.toml configuration:

[tool.ariadne-codegen]
schema_path = "schema.graphql"
queries_path = "queries.graphql"
target_package_name = "gql_client"
async_client = false

Contents of schema.graphql:

interface Error {
  type: String
  title: String
  status: Int
  detail: String
  instance: String
}

type DeletionError implements Error {
  type: String
  title: String
  status: Int
  detail: String
  instance: String
}

type DeleteThingPayload {
  thing: Thing
  errors: [DeletionError!]
}

type Thing {
  id: ID!
  name: String
}

input DeleteThingInput {
  id: ID!
}

type Mutation {
  deleteThing(input: DeleteThingInput!): DeleteThingPayload!
}

Contents of queries.graphql:

fragment DefaultError on Error {
  ... on Error {
    type
    title
    status
    detail
    instance
  }
}

mutation MyDeleteThing($id: ID!) {
  deleteThing (input: {id: $id}) {
    thing {
      id
      name
    }
    errors {
      __typename
      ... DefaultError
    }
  }
}

When running ariadne-codegen, I expect to see all the error fields (type, title etc.) defined for the deleteThing query.
But instead only __typename is defined. Here's the relevant part of the generated code:

class MyDeleteThingDeleteThingErrors(BaseModel):
    typename__: Literal["DeletionError"] = Field(alias="__typename")

Inputs that work

Modifying the fragment to use the specific error type (DeletionError) works:

fragment DefaultError on DeletionError {
  ... on DeletionError {
    type
    title
    status
    detail
    instance
  }
}

Resulting code:

class MyDeleteThingDeleteThingErrors(BaseModel):
    typename__: Literal["DeletionError"] = Field(alias="__typename")
    type: Optional[str]
    title: Optional[str]
    status: Optional[int]
    detail: Optional[str]
    instance: Optional[str]
@bombsimon
Copy link
Contributor

To me the changed working version looks like the way to do it but maybe I'm wrong given that it works in the UI. See the examples here f.ex. that has the title from the interface outside the spread and only spreads on concrete specific fields. Same here in the GraphQL docs where you only need spreading to get fields from the concrete types. So I usually do:

fragment <Fragment> on <Interface> {
  interfaceField
  anotherInterfaceField

  ... on <ConcreteType> {
    customFieldOnlyOnInterfaceImpl
  }

  ... on <AnotherConcreteType> {
    anotherCustomFieldOnlyOnAnotherInterfaceImpl
  }
}

By doing this it should still work in the UI and generate the proper code, right?

So imagining DeletionError had a specific field not on the interface called deleteFailReason I would write something like this and then just add more spreads for the other custom fields:

fragment DefaultError on Error {
  type
  title
  status
  detail
  instance

  ... on DeletionError {
    deleteFailReason
  }
}

@akrejczinger
Copy link
Author

I'm actually new to GraphQL so it's possible I messed up something. I'll try your solution and see if it works.

@akrejczinger
Copy link
Author

The modified DefaultError fragment works, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants