ardatan / ardatan/graphql-tools

Schema stitching bug when multiple versions of delegate in workspace

Open
#5,130 0 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

_Progress of the issue based on the [Contributor Workflow](https://github.com/the-guild-org/Stack/blob/master/CONTRIBUTING.md#a-typical-contributor-workflow)_

- [ ] 1. The issue provides a reproduction available on Github, Stackblitz or CodeSandbox
> Make sure to fork this template and run `yarn generate` in the terminal.
>
> Please make sure the GraphQL Tools package versions under `package.json` matches yours.
- [ ] 2. A failing test has been provided
- [x] 3. A local solution has been provided
- [x] 4. A pull request is pending review

---

**Describe the bug**

When multiple copies of `@graphql-tools/delegate` are available in a workspace (eg: because `stitch` and `wrap` depend on different versions), creating symbols with `Symbol()` can lead to bugs when one version of `delegate` sets an object property using its version of the symbol which the other `delegate` instance will not be able to access.

The problem occurs in [`executeDelegationStage`](https://github.com/neumark/graphql-tools/blob/2d0f64d6d564bad2617aaa5e8bc44684bb29232a/packages/delegate/src/mergeFields.ts#L114), when the selectionSet fields returned by the stitched subschema are merged with the existing fields. Due to multiple versions of `delegate`, each with it's own instance of `OBJECT_SUBSCHEMA_SYMBOL`, the subschema information associated with symbols set in `annotateExternalObject()` by one `delegate` instance cannot be accessed by `executeDelegationStage()` within another instance.

Using `Symbol.for()` fixes this: as long as both versions of delegate use the same string description, they will refer to the same symbol.

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

Our dependency tree:
```
└─ @cloud/unified@workspace:cloud/unified
├─ @graphql-tools/delegate@npm:8.4.2 [55f8a] (via npm:8.4.2 [55f8a])
├─ @graphql-tools/stitch@npm:8.4.2 [55f8a] (via npm:8.4.2 [55f8a])
│ ├─ @graphql-tools/batch-delegate@npm:8.2.2 [bfa3d] (via npm:8.2.2 [bfa3d])
│ │ └─ @graphql-tools/delegate@npm:8.4.2 [55f8a] (via npm:8.4.2 [55f8a])
│ ├─ @graphql-tools/delegate@npm:8.4.2 [55f8a] (via npm:8.4.2 [55f8a])
│ └─ @graphql-tools/wrap@npm:8.5.1 [bfa3d] (via npm:^8.3.1 [bfa3d])
│ └─ @graphql-tools/delegate@npm:8.8.1 [ccd30] (via npm:8.8.1 [ccd30])
```

**Expected behavior**

**Environment:**

- OS: linux
- `@graphql-tools/...`:
- NodeJS: 16.10.0

**Additional context**

Contributor guide

Open the contributing guide

Research direction

Start in packages/delegate/src/mergeFields.ts at executeDelegationStage and trace the symbol metadata set by annotateExternalObject(). Compare how OBJECT_SUBSCHEMA_SYMBOL is created and accessed when multiple delegate versions are installed. Done means the two delegate instances can access the same subschema metadata; a pending pull request is already noted in the issue.

Written by the indexing model from the issue text.

Assessment

Tech stack
node.js, typescript
Domain
api, backend-api-design
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.