ardatan / ardatan/graphql-tools

Delegate removes selection sets when nesting Top-Level Abstract Fields in a Mutation response

Open
#4,945 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
5.4k
Forks
830
Avg merge
10h 59m
Merged PRs (30d)
45

Description

Hi, we have a graphql API with the following structure
```GraphQL
interface Foo {
pk: ID
}
type Bar implements Foo {
pk: ID
bar: String
}

type Nested {
foo: Foo
}

type Query {
foo: Foo
nested: Nested
}

type MutationResponseType {
query: Query
}

type Mutation {
someMutation(pk: ID!): MutationResponseType
}
```

**Describe the bug**

When using the mutation with a Fragment on Query, fields of the Interface are removed when used on top level. I.e.
```graphQL
mutation SomeMutation {
someMutation(id: "234") {
query {
...MyFragment
}
}
}

fragment MyFragment on Query {
foo {
... on Bar {
pk
}
}
}
```
gets transformed to
```graphQL
mutation SomeMutation {
someMutation(id: "234") {
__typename
query {
__typename
...MyFragment
}
}
}

fragment MyFragment on Query {
foo {
__typename
}
}
```
This does not happen when either the Fragment is not on top level or the Interface is nested. I.e. the following work:
```graphQL
mutation SomeMutation {
someMutation(id: "234") {
query {
foo {
...NotTopLevel
}
...MyFragment
}
}
}

fragment NotTopLevel on Foo {
... on Bar {
pk
}
}

fragment Nested on Query {
nested {
foo {
... on Bar {
pk
}
}
}
}
```

**To Reproduce**
Steps to reproduce the behavior:

I tried to write a test in the repo but did not succeed with providing the right test-input.

However, with a working client on our actual production code I was able to debug into it and find out where it goes wrong for us:
In `wrapConcreteTypes` in `prepareGatewayDocument.ts`, you create new selections and set the type conditions. However, this type gets set to `MutationReturnType`.
![grafik](https://user-images.githubusercontent.com/6051501/210559275-fd8a325e-4e8a-4d39-9731-c0e1f52d4f16.png)

This causes problems later down the line in `finalizeSelectionSet` where the fields are discarded, as the types do not match (sorry for the ugly screenshot, had to wipe our internal names). I _think_ , there should be the implementing type instead of the second Type, i.e. `Bar`.
![grafik](https://user-images.githubusercontent.com/6051501/210560684-feeb2f4c-f662-48c4-8a09-569323499200.png)

When I comment out the `FIELD` visitor in `wrapConcreteTypes`, everything works as expected (well, for our small case).

Hope that helps even if I could not provide a minimum reproducible version.

**Expected behavior**

Valid attributes should not be discarded

**Environment:**

- `@graphql-tools/delegate`: 9.0.21
- NodeJS: LTS Gallium

Contributor guide

Open the contributing guide

Research direction

Start in prepareGatewayDocument.ts, particularly wrapConcreteTypes and its FIELD visitor, then trace how the resulting selections are handled by finalizeSelectionSet. Reproduce the mutation and fragment shape from the issue, verify where the implementing type condition is lost, and confirm that valid fields such as Bar.pk are preserved without breaking the working nested cases.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
api, backend-api-design
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.