GraphQL 17 Compatibility - #8346
Conversation
Fix GraphQL v17 executor type breaks: add getAbortSignal/getAsyncHelpers to buildResolveInfo and version-gate coerceInputValue via validateInputValue.
Pin test-v17-temp to 17.0.2, enable build, include executor in the gradual package filter, and rename Full Check to match the lockfile.
Replace the temporary v17 job with full Unit/Leak coverage for GraphQL 15/16/17, add a GraphQL v16 typecheck job, and exclude Node 18 × GraphQL 17.
Keep Yoga-compatible fire-and-forget work alive via the runtime waitUntil hook, with a Yoga integration test and GraphQL 17 typecheck fixes. Co-authored-by: Cursor <cursoragent@cursor.com>
🦋 Changeset detectedLatest commit: 2b605a1 The changes in this PR will be included in the next version bump. This PR includes changesets to release 26 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughSummary by CodeRabbit
WalkthroughGraphQL v17 support now spans executor variable coercion, async resolver helpers, schema scalar mapping, utility types, version-aware tests, CI, package peer dependencies, and release metadata. ChangesGraphQL v17 support
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
🚀 Snapshot Release (
|
| Package | Version | Info |
|---|---|---|
@graphql-tools/executor |
2.0.0-alpha-20260805135823-2b605a13cbe8d17f20f5375db421c5b4e56a2f6c |
npm ↗︎ unpkg ↗︎ |
@graphql-tools/executor-apollo-link |
2.0.13-alpha-20260805135823-2b605a13cbe8d17f20f5375db421c5b4e56a2f6c |
npm ↗︎ unpkg ↗︎ |
@graphql-tools/executor-envelop |
4.0.13-alpha-20260805135823-2b605a13cbe8d17f20f5375db421c5b4e56a2f6c |
npm ↗︎ unpkg ↗︎ |
@graphql-tools/executor-legacy-ws |
1.1.33-alpha-20260805135823-2b605a13cbe8d17f20f5375db421c5b4e56a2f6c |
npm ↗︎ unpkg ↗︎ |
@graphql-tools/executor-urql-exchange |
1.0.35-alpha-20260805135823-2b605a13cbe8d17f20f5375db421c5b4e56a2f6c |
npm ↗︎ unpkg ↗︎ |
@graphql-tools/executor-yoga |
3.0.43-alpha-20260805135823-2b605a13cbe8d17f20f5375db421c5b4e56a2f6c |
npm ↗︎ unpkg ↗︎ |
@graphql-tools/graphql-tag-pluck |
8.3.36-alpha-20260805135823-2b605a13cbe8d17f20f5375db421c5b4e56a2f6c |
npm ↗︎ unpkg ↗︎ |
graphql-tools |
9.0.34-alpha-20260805135823-2b605a13cbe8d17f20f5375db421c5b4e56a2f6c |
npm ↗︎ unpkg ↗︎ |
@graphql-tools/import |
7.1.19-alpha-20260805135823-2b605a13cbe8d17f20f5375db421c5b4e56a2f6c |
npm ↗︎ unpkg ↗︎ |
@graphql-tools/links |
10.0.13-alpha-20260805135823-2b605a13cbe8d17f20f5375db421c5b4e56a2f6c |
npm ↗︎ unpkg ↗︎ |
@graphql-tools/load |
8.1.16-alpha-20260805135823-2b605a13cbe8d17f20f5375db421c5b4e56a2f6c |
npm ↗︎ unpkg ↗︎ |
@graphql-tools/apollo-engine-loader |
8.0.35-alpha-20260805135823-2b605a13cbe8d17f20f5375db421c5b4e56a2f6c |
npm ↗︎ unpkg ↗︎ |
@graphql-tools/code-file-loader |
8.1.37-alpha-20260805135823-2b605a13cbe8d17f20f5375db421c5b4e56a2f6c |
npm ↗︎ unpkg ↗︎ |
@graphql-tools/git-loader |
8.0.41-alpha-20260805135823-2b605a13cbe8d17f20f5375db421c5b4e56a2f6c |
npm ↗︎ unpkg ↗︎ |
@graphql-tools/github-loader |
9.1.7-alpha-20260805135823-2b605a13cbe8d17f20f5375db421c5b4e56a2f6c |
npm ↗︎ unpkg ↗︎ |
@graphql-tools/graphql-file-loader |
8.1.19-alpha-20260805135823-2b605a13cbe8d17f20f5375db421c5b4e56a2f6c |
npm ↗︎ unpkg ↗︎ |
@graphql-tools/json-file-loader |
8.0.33-alpha-20260805135823-2b605a13cbe8d17f20f5375db421c5b4e56a2f6c |
npm ↗︎ unpkg ↗︎ |
@graphql-tools/module-loader |
8.0.33-alpha-20260805135823-2b605a13cbe8d17f20f5375db421c5b4e56a2f6c |
npm ↗︎ unpkg ↗︎ |
@graphql-tools/url-loader |
9.1.7-alpha-20260805135823-2b605a13cbe8d17f20f5375db421c5b4e56a2f6c |
npm ↗︎ unpkg ↗︎ |
@graphql-tools/merge |
9.2.3-alpha-20260805135823-2b605a13cbe8d17f20f5375db421c5b4e56a2f6c |
npm ↗︎ unpkg ↗︎ |
@graphql-tools/mock |
9.1.13-alpha-20260805135823-2b605a13cbe8d17f20f5375db421c5b4e56a2f6c |
npm ↗︎ unpkg ↗︎ |
@graphql-tools/node-require |
7.0.45-alpha-20260805135823-2b605a13cbe8d17f20f5375db421c5b4e56a2f6c |
npm ↗︎ unpkg ↗︎ |
@graphql-tools/relay-operation-optimizer |
7.1.9-alpha-20260805135823-2b605a13cbe8d17f20f5375db421c5b4e56a2f6c |
npm ↗︎ unpkg ↗︎ |
@graphql-tools/resolvers-composition |
7.0.36-alpha-20260805135823-2b605a13cbe8d17f20f5375db421c5b4e56a2f6c |
npm ↗︎ unpkg ↗︎ |
@graphql-tools/schema |
10.1.0-alpha-20260805135823-2b605a13cbe8d17f20f5375db421c5b4e56a2f6c |
npm ↗︎ unpkg ↗︎ |
@graphql-tools/utils |
12.0.0-alpha-20260805135823-2b605a13cbe8d17f20f5375db421c5b4e56a2f6c |
npm ↗︎ unpkg ↗︎ |
💻 Website PreviewThe latest changes are available as preview in: https://pr-8346.graphql-tools-8ja.pages.dev |
There was a problem hiding this comment.
🟡 Changes recommended
VariableValues.sources is returned but not populated (and a related optional-chaining access can throw), which can break GraphQL v17 variable scoping/compat behavior at runtime.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.
Pull request overview
This PR updates the @graphql-tools/* ecosystem to support GraphQL.js v17 while maintaining compatibility with v15/v16, aligning executor behavior and utility APIs with GraphQL v17’s new execution/variable semantics and adding CI coverage for v17.
Changes:
- Introduces a v17-compatible
VariableValuesshape ({ coerced, sources }) across executor + utils, and updates execution/field collection paths accordingly. - Adds v17-compatible wrappers/utilities (
getDirectiveValues, input validation helpers, async helpers onGraphQLResolveInfo) and adjusts tests for AST/output differences in v17. - Expands peer/dev dependency ranges and CI matrices to include GraphQL v17 (and adds a dedicated v16 typecheck job).
File summaries
| File | Description |
|---|---|
| tsconfig.json | Enables skipLibCheck for the repo TS build. |
| packages/utils/tests/mapSchema.test.ts | Updates test fixture to include extensions on a field config. |
| packages/utils/src/visitResult.ts | Updates variableValues typing to the new VariableValues shape. |
| packages/utils/src/types.ts | Adds VariableValues/VariableValueSource types for v17 compatibility. |
| packages/utils/src/Interfaces.ts | Extends GraphQLResolveInfo with v17-required helper APIs. |
| packages/utils/src/index.ts | Re-exports new compatibility utilities. |
| packages/utils/src/getDirectiveValues.ts | Adds v15–v17 compatible getDirectiveValues wrapper. |
| packages/utils/src/collectFields.ts | Migrates field collection APIs to accept VariableValues. |
| packages/schema/tests/schemaGenerator.test.ts | Adjusts parsing options based on GraphQL major version. |
| packages/schema/src/addResolversToSchema.ts | Updates scalar override handling for v17 coerce* methods + resolver typing. |
| packages/optimize/tests/remove-loc.spec.ts | Updates expectations for v17 AST shape changes. |
| packages/optimize/tests/remove-empty-nodes.spec.ts | Updates expectations for v17 AST shape changes. |
| packages/loaders/git/tests/loader.spec.ts | Adjusts expected parsed AST shape differences for v17. |
| packages/executors/yoga/package.json | Expands GraphQL peer range to include v17. |
| packages/executors/urql-exchange/package.json | Expands GraphQL peer range to include v17. |
| packages/executors/apollo-link/package.json | Expands GraphQL peer range to include v17. |
| packages/executor/src/execution/values.ts | Changes getVariableValues to return v17-style VariableValues. |
| packages/executor/src/execution/validateInputValue.ts | Adds v17-aligned input validation utilities. |
| packages/executor/src/execution/suggestionList.ts | Adds suggestion list helper (ported behavior). |
| packages/executor/src/execution/naturalCompare.ts | Adds natural compare helper (ported behavior). |
| packages/executor/src/execution/formatList.ts | Adds list formatting helper for error messages. |
| packages/executor/src/execution/execute.ts | Aligns execution context + resolve info shape for v17. |
| packages/executor/src/execution/didYouMean.ts | Adds didYouMean helper for improved errors. |
| packages/executor/src/execution/tests/variables-test.ts | Updates variable/error expectations across v16 vs v17. |
| packages/executor/src/execution/tests/oneOf-test.ts | Updates OneOf-related expectations for v17 behavior. |
| packages/executor/src/execution/tests/executor-test.ts | Updates resolve info expectations for v17 additions. |
| packages/executor/src/execution/tests/async-helpers.test.ts | Adds Yoga integration test for getAsyncHelpers().track. |
| packages/executor/package.json | Updates devDependencies for GraphQL v17 + Yoga for new tests. |
| package.json | Updates lockfile GraphQL version to v17.0.2. |
| .github/workflows/tests.yml | Adds GraphQL v17 to test matrix + v16 typecheck job. |
| .changeset/graphql-v17-support.md | Documents v17 support and breaking API changes. |
| .changeset/@graphql-tools_executor-yoga-8346-dependencies.md | Changeset for executor-yoga peer range expansion. |
| .changeset/@graphql-tools_executor-yoga-8281-dependencies.md | Changeset for executor-yoga peer range expansion. |
| .changeset/@graphql-tools_executor-urql-exchange-8346-dependencies.md | Changeset for urql-exchange peer range expansion. |
| .changeset/@graphql-tools_executor-urql-exchange-8281-dependencies.md | Changeset for urql-exchange peer range expansion. |
| .changeset/@graphql-tools_executor-apollo-link-8346-dependencies.md | Changeset for apollo-link peer range expansion. |
| .changeset/@graphql-tools_executor-apollo-link-8281-dependencies.md | Changeset for apollo-link peer range expansion. |
Review details
Suppressed comments (1)
packages/executor/src/execution/validateInputValue.ts:89
- The second
validateInputValueJSDoc example callback should accept(path, invalidValue, error)per the actualonErrorsignature; currently it only takes(error).
* (error) => {
* errors.push(error.message);
* },
- Files reviewed: 36/38 changed files
- Comments generated: 4
- Review effort level: Lite
We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.
There was a problem hiding this comment.
Actionable comments posted: 7
🧹 Nitpick comments (1)
packages/executor/src/execution/formatList.ts (1)
19-30: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueHandle the empty-list case.
formatListdoes not handleitems.length === 0.items.slice(0, -1)yields[]anditems.at(-1)yieldsundefined, so the function returns", or undefined".The current single caller is safe:
didYouMeanreturns early at Line 22 ofpackages/executor/src/execution/didYouMean.tswhensuggestions.length === 0. HoweverorListandandListare both exported, andandListhas no caller yet. The graphql-js source this file mirrors guards the empty case with an invariant.♻️ Proposed guard
function formatList(conjunction: string, items: ReadonlyArray<string>): string { switch (items.length) { + case 0: + throw new Error('Expected non-empty list of items to format.'); case 1: return items[0]; case 2: return items[0] + ' ' + conjunction + ' ' + items[1]; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/executor/src/execution/formatList.ts` around lines 19 - 30, Update formatList to explicitly handle an empty items array before the existing one-, two-, and multi-item formatting paths. Add the same invariant-style guard used by the mirrored graphql-js implementation, preserving the current formatting behavior for non-empty lists and ensuring exported orList and andList cannot return an invalid string.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.changeset/graphql-v17-support.md:
- Line 16: Correct the scalar method mappings in the GraphQL v17 support
guidance: map __serialize to coerceOutputValue and __parseValue to
coerceInputValue, preserving the existing migration note structure.
In `@packages/executor/src/execution/validateInputValue.ts`:
- Around line 248-259: Update the reportInvalidValue call in the result ===
undefined branch to pass inputValue as the invalidValue argument and caughtError
as the optional originalError argument. Preserve the existing message, path, and
caught-error handling while matching the argument order used by
reportInvalidValue and other calls in validateInputValue.
- Around line 214-229: Update the OneOf validation branch in validateInputValue
so the fields.length !== 1 error exits immediately after reportInvalidValue,
matching the literal-path handling already used later in the same file. Keep the
existing error message and path generation via getOneOfInputObjectErrorMessage
and addPath unchanged for the valid single-field case, but prevent the code from
reading fields[0] or checking inputValue[field] when the field-count guard
fails.
- Around line 46-94: Update both validateInputValue JSDoc examples to follow the
local OnErrorCB signature `(path, invalidValue, error)`, not graphql-js’s
`(error, path)` ordering. In the first callback, use the third parameter for
error and the first for path; in the second, accept the callback parameters in
local order and read the third parameter’s message.
In `@packages/executor/src/execution/values.ts`:
- Around line 69-71: Populate the `sources` record in the variable-processing
function alongside `coercedValues`, recording the appropriate `{ signature,
value }` source entry for every variable definition, including default-value and
not-provided branches. Ensure `getScopedVariableValues` can use
`VariableValues.sources` to resolve fragment-scoped variables while preserving
the existing `VariableValues` return shape.
In `@packages/utils/src/types.ts`:
- Around line 161-182: Update coerceVariableValues to assign
VariableValues.sources[varName] for every coerced variable and default using the
corresponding GraphQLVariableSignature metadata, so getScopedVariableValues
selects the correct fragment scope when names overlap. Add a regression test
covering overlapping operation and fragment variable names and verify fragment
arguments use their fragment-specific source metadata.
In `@packages/utils/src/visitResult.ts`:
- Line 176: Normalize the request variables before entering visitResult’s
traversal path: update the visitResult/visitingRoot flow so
ExecutionRequest.variables is wrapped into a VariableValues shape with coerced
and sources populated before collectFields and directive evaluation use it. Keep
the existing traversal logic in visitingRoot unchanged, but ensure callers
passing request.variables no longer forward raw TVariables where VariableValues
is required.
---
Nitpick comments:
In `@packages/executor/src/execution/formatList.ts`:
- Around line 19-30: Update formatList to explicitly handle an empty items array
before the existing one-, two-, and multi-item formatting paths. Add the same
invariant-style guard used by the mirrored graphql-js implementation, preserving
the current formatting behavior for non-empty lists and ensuring exported orList
and andList cannot return an invalid string.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 02d8df5e-38fc-4a4e-9736-2767313bdb25
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (37)
.changeset/@graphql-tools_executor-apollo-link-8281-dependencies.md.changeset/@graphql-tools_executor-apollo-link-8346-dependencies.md.changeset/@graphql-tools_executor-urql-exchange-8281-dependencies.md.changeset/@graphql-tools_executor-urql-exchange-8346-dependencies.md.changeset/@graphql-tools_executor-yoga-8281-dependencies.md.changeset/@graphql-tools_executor-yoga-8346-dependencies.md.changeset/graphql-v17-support.md.github/workflows/tests.ymlpackage.jsonpackages/executor/package.jsonpackages/executor/src/execution/__tests__/async-helpers.test.tspackages/executor/src/execution/__tests__/executor-test.tspackages/executor/src/execution/__tests__/oneOf-test.tspackages/executor/src/execution/__tests__/variables-test.tspackages/executor/src/execution/didYouMean.tspackages/executor/src/execution/execute.tspackages/executor/src/execution/formatList.tspackages/executor/src/execution/naturalCompare.tspackages/executor/src/execution/suggestionList.tspackages/executor/src/execution/validateInputValue.tspackages/executor/src/execution/values.tspackages/executors/apollo-link/package.jsonpackages/executors/urql-exchange/package.jsonpackages/executors/yoga/package.jsonpackages/loaders/git/tests/loader.spec.tspackages/optimize/tests/remove-empty-nodes.spec.tspackages/optimize/tests/remove-loc.spec.tspackages/schema/src/addResolversToSchema.tspackages/schema/tests/schemaGenerator.test.tspackages/utils/src/Interfaces.tspackages/utils/src/collectFields.tspackages/utils/src/getDirectiveValues.tspackages/utils/src/index.tspackages/utils/src/types.tspackages/utils/src/visitResult.tspackages/utils/tests/mapSchema.test.tstsconfig.json
Adds support for GraphQL v17 by aligning the executor implementation, and rest of the utilities with the new API changes while keeping the backwards compatibility.
Closes #8313
Closes #8281
This PR doesn't use conditional imports with
import * as GraphQLjsetc like before, because we want to avoid incompatibilities between environments, bundlers etc. Importing the entire package can be risky, so instead copying the code from the latest version to share the behavior between different GraphQLjs versions would be better.Compared to other PRs, this PR doesn't mock
info.getAsyncHelpers().track, and it uses what we have before in Yoga which iscontext.waitUntil, and the feature is called Explicit Resource Management.Same goes to the abort signal helpers, it uses the existing implementation for Execution Cancellation, and aligns the user-facing API with the original GraphQL v17.
So for those two, the behavior of GraphQL Yoga will be the same.
For the rest of the detailed API changes, you can refer to the changeset.