ardatan / ardatan/graphql-tools
Schema stitching bug when multiple versions of delegate in workspace
- 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
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