feat: support graphql 17 (alongside 16)#1636
Conversation
Widen graphql peer dependency ranges to `^16.10.0 || ^17.0.0` and make the
library source compile against both majors.
graphql 17 tightened/changed several types Pothos touches:
- `GraphQLNonNull<T>` now requires `T extends GraphQLNullable*Type` — narrow the
build-cache type accessors and the sub-graph type replacer to nullable unions.
- `GraphQLResolveInfo['variableValues']` became `{ sources, coerced }` (read by the
complexity plugin through `getArgumentValues`) — add a runtime version branch that
builds the shape the installed graphql version expects.
- `GraphQLArgument` is no longer assignable to `GraphQLField` — widen the converter's
`writeDescription` parameter union.
All 32 packages build and typecheck (src) against graphql 17, and the changes remain
valid on graphql 16. Default dev/test install is pinned to 17 on this branch to
exercise the new path.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🦋 Changeset detectedLatest commit: 6c45f12 The changes in this PR will be included in the next version bump. This PR includes changesets to release 19 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 |
graphql 17 moved `@defer`/`@stream` out of the stable `execute`, which now throws on any schema that declares those directives — breaking ~167 prisma/drizzle tests whose example schemas declare `@defer` for the plugins' defer-aware query planning. Add a version-aware `execute` helper to `@pothos/test-utils` that calls graphql 16's `execute` as before, and on 17 routes through `experimentalExecuteIncrementally` and collapses the incremental payloads back into a single result (mapping pending ids to paths, deep-merging defer data, appending stream items). Existing single-result snapshots therefore pass unchanged on both majors. Repoint the 28 prisma/drizzle test files from graphql's `execute` to the helper. Verified: drizzle 90/90 and prisma 89/89 on graphql 17, and drizzle 90/90 on graphql 16 (helper falls back to stable execute). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
graphql 17's schema printer adds spaces inside object literals
(`{someField: "abc"}` -> `{ someField: "abc" }`, `{id: Asc}` -> `{ id: Asc }`).
Regenerate the affected SDL snapshots (relay, prisma-utils, directives) against
graphql 17, which is now the test baseline for this branch.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
graphql 17 ships dual ESM/CJS builds. The directives and federation suites mix the Pothos schema (loaded one way) with @graphql-tools/@envelop/@apollo (loaded another), so two graphql module instances were live at once and graphql 17's stricter cross-realm check threw ("Cannot use GraphQLType from another module or realm"). Alias graphql to its single resolved entry (absolute path), dedupe it, and inline the graphql-touching deps so the alias reaches them too. The previous `graphql/index.js` (CJS) alias no longer sufficed once those deps loaded graphql's ESM build. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Bump @typescript/native-preview (tsgo) to 7.0.0-dev.20260616.1. The pinned April beta mis-resolved graphql 17's types through built .d.ts files, reporting ~743 spurious `implicitly any` errors in plugin test schemas (stable tsc6 and the build were always clean). The newer snapshot resolves them. - Point vitest's typecheck at `tsgo` (it defaults to spawning `tsc`, which isn't installed — typescript ships `tsc6`). Fixes the dataloader test task and runs the *.test-d.ts assertions. - Switch examples' `type` script from `tsc --noEmit` to `tsgo --noEmit` to match the packages, which already migrated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
graphql-codegen does not support graphql 17 (its latest stable peers `graphql` at `^16`), which broke the nextjs example's `generate` step. gql.tada works on graphql 17 — it has no `graphql` peer (parses via @0no-co/graphql.web) and @0no-co/graphqlsp explicitly supports `^17`. - Replace @graphql-codegen/cli + client-preset with gql.tada + @0no-co/graphqlsp. - Configure graphqlsp in tsconfig (schema.graphql -> graphql-env.d.ts); add a `graphql/tada.ts` exporting the typed `graphql()`; point Posts.tsx at it. - `generate` now runs build-schema then `gql.tada generate-output`. Per-document types are inferred in the type system; only the schema env regenerates on change. - Pipe stdin into the gql.tada CLI so its cleanup (process.stdin.unref()) exits 0 under Node 24 after writing the file. - Drop components/__generated__/; register graphql-env.d.ts as a turbo output. Verified generate + type + build green on graphql 17. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
complex-app's `codegen` script only emitted schema.graphql via the schema-ast plugin, which scripts/build-schema.ts already does with printSchema. The client preset was commented out and the page uses urql's runtime `gql`, so nothing consumed generated types. graphql-codegen also doesn't support graphql 17. Remove the four @graphql-codegen/* devDeps, the `codegen` script, and codegen.ts. The `generate` task (prisma generate + build-schema) is unchanged and green on 17. This removes the last graphql-codegen usage in the repo. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Generated file (like __generated__/ and schema.graphql, already ignored). Exclude it from lint/format so the nextjs example's committed gql.tada output doesn't trip CI. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@pothos/core
@pothos/plugin-add-graphql
@pothos/plugin-complexity
@pothos/plugin-dataloader
@pothos/plugin-directives
@pothos/plugin-drizzle
@pothos/plugin-errors
@pothos/plugin-example
@pothos/plugin-federation
@pothos/plugin-grafast
@pothos/plugin-mocks
@pothos/plugin-prisma
@pothos/plugin-prisma-utils
@pothos/plugin-relay
@pothos/plugin-scope-auth
@pothos/plugin-simple-objects
@pothos/plugin-smart-subscriptions
@pothos/plugin-sub-graph
@pothos/plugin-tracing
@pothos/plugin-validation
@pothos/plugin-with-input
@pothos/plugin-zod
@pothos/tracing-newrelic
@pothos/tracing-opentelemetry
@pothos/tracing-sentry
@pothos/tracing-xray
commit: |
This snapshot was dropped by an earlier -u run while the test was still throwing the cross-realm error, then regenerated locally but never committed — so CI ran against the missing/old snapshot and failed. Commit the graphql 17 output. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CI lint (biome check, no autofix) flagged useConsistentArrayType (ReadonlyArray<T> -> readonly T[]) and import sorting in the new execute helper. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Left unsorted when splitting the graphql/test-utils execute import. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…cute helper Add graphql 17's modern scalar coercion hooks to `scalarType` — `coerceOutputValue`, `coerceInputValue`, `coerceInputLiteral`, and `valueToLiteral` — alongside the existing serialize/parseValue/parseLiteral. They are consulted only on graphql 17+ (16 keeps using the legacy hooks). `serialize` is now optional when `coerceOutputValue` is provided, and `coerceInputLiteral` must be paired with `coerceInputValue` per graphql's constructor. Spread through so the keys don't trip graphql 16's narrower GraphQLScalarTypeConfig. Also fix two bugs in the test-utils incremental `execute` helper: collect errors from graphql 17's `completed[].errors` (a throwing @defer/@stream group reports there, not in `incremental[].errors`), and preserve a `null` root result instead of coercing it to `{}`, matching graphql 16's `execute` output. Tracked follow-up for the graphql 18 deprecation cliff: #1637 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
d7ce524 to
e0c8bd5
Compare
There was a problem hiding this comment.
Pull request overview
This PR updates the Pothos monorepo to support GraphQL.js 17 alongside 16, widening peer dependency ranges across packages while keeping the repo’s dev/test toolchain and examples compatible with GraphQL 17 changes (types, incremental execution, and cross-realm module resolution).
Changes:
- Widen
graphqlpeerDependency ranges across packages to^16.10.0 || ^17.0.0, while pinning the repo’s dev graph to GraphQL 17 via overrides. - Add a GraphQL-17-aware
executehelper in@pothos/test-utilsto preserve single-result snapshots for@defer/@stream. - Update complexity plugin variable-values shape, scalar coercion typing/hooks, vitest typecheck checker, and migrate the Next.js example from graphql-codegen to
gql.tada.
Reviewed changes
Copilot reviewed 91 out of 101 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| vitest.config.mjs | Configure vitest typecheck to use tsgo instead of default tsc. |
| turbo.json | Add schema.graphql / graphql-env.d.ts as global dependencies for caching. |
| packages/tracing-xray/package.json | Widen graphql peerDependency range to include v17. |
| packages/tracing-sentry/package.json | Widen graphql peerDependency range to include v17. |
| packages/tracing-opentelemetry/package.json | Widen graphql peerDependency range to include v17. |
| packages/tracing-newrelic/package.json | Widen graphql peerDependency range to include v17. |
| packages/test-utils/src/index.ts | Re-export the new execute helper from test-utils. |
| packages/test-utils/src/execute.ts | Add version-aware execute wrapper for GraphQL 17 incremental execution. |
| packages/test-utils/package.json | Widen graphql dependency range to include v17. |
| packages/plugin-zod/package.json | Widen graphql peerDependency range to include v17. |
| packages/plugin-with-input/package.json | Widen graphql peerDependency range to include v17. |
| packages/plugin-validation/package.json | Widen graphql peerDependency range; devDep pinned to GraphQL 17 for CI. |
| packages/plugin-tracing/package.json | Widen graphql peerDependency range to include v17. |
| packages/plugin-sub-graph/src/util.ts | Adjust GraphQLNonNull handling for GraphQL 17 generic constraint changes. |
| packages/plugin-sub-graph/package.json | Widen graphql peerDependency range to include v17. |
| packages/plugin-smart-subscriptions/package.json | Widen graphql peerDependency range to include v17. |
| packages/plugin-simple-objects/package.json | Widen graphql peerDependency range to include v17. |
| packages/plugin-scope-auth/package.json | Widen graphql peerDependency range to include v17. |
| packages/plugin-relay/tests/snapshots/index.test.ts.snap | Snapshot updates due to GraphQL 17 printer formatting differences. |
| packages/plugin-relay/package.json | Widen graphql peerDependency range to include v17. |
| packages/plugin-prisma/tests/variants.test.ts | Switch tests to use @pothos/test-utils execute helper. |
| packages/plugin-prisma/tests/type-include.test.ts | Switch tests to use @pothos/test-utils execute helper. |
| packages/plugin-prisma/tests/select-mode.test.ts | Switch tests to use @pothos/test-utils execute helper. |
| packages/plugin-prisma/tests/relation-query.test.ts | Switch tests to use @pothos/test-utils execute helper. |
| packages/plugin-prisma/tests/nodes.test.ts | Switch tests to use @pothos/test-utils execute helper. |
| packages/plugin-prisma/tests/nested-query.test.ts | Switch tests to use @pothos/test-utils execute helper. |
| packages/plugin-prisma/tests/index.test.ts | Switch execute import to test-utils helper; keep printSchema from graphql. |
| packages/plugin-prisma/tests/fragment-alias-composite-cursor.test.ts | Switch tests to use @pothos/test-utils execute helper. |
| packages/plugin-prisma/tests/findUnique.test.ts | Switch tests to use @pothos/test-utils execute helper. |
| packages/plugin-prisma/tests/defer.test.ts | Switch tests to use @pothos/test-utils execute helper. |
| packages/plugin-prisma/tests/counts.test.ts | Switch tests to use @pothos/test-utils execute helper. |
| packages/plugin-prisma/tests/connections.test.ts | Switch tests to use @pothos/test-utils execute helper. |
| packages/plugin-prisma/tests/abstract-types.test.ts | Switch tests to use @pothos/test-utils execute helper. |
| packages/plugin-prisma/package.json | Widen graphql peerDependency range to include v17. |
| packages/plugin-prisma-utils/tests/examples/codegen/schema.graphql | Snapshot/schema formatting updates for GraphQL 17 printer output. |
| packages/plugin-prisma-utils/tests/snapshots/codegen.test.ts.snap | Snapshot updates due to GraphQL 17 printer formatting differences. |
| packages/plugin-prisma-utils/package.json | Widen graphql peerDependency range to include v17. |
| packages/plugin-mocks/package.json | Widen graphql peerDependency range to include v17. |
| packages/plugin-grafast/package.json | Widen graphql peerDependency range to include v17. |
| packages/plugin-federation/vitest.config.js | Force single GraphQL module instance + inline deps; set tsgo checker. |
| packages/plugin-federation/package.json | Widen graphql peerDependency range to include v17. |
| packages/plugin-example/package.json | Widen graphql peerDependency range to include v17. |
| packages/plugin-errors/package.json | Widen graphql peerDependency range to include v17. |
| packages/plugin-drizzle/tests/variants.test.ts | Switch tests to use @pothos/test-utils execute helper. |
| packages/plugin-drizzle/tests/skip.test.ts | Switch tests to use @pothos/test-utils execute helper. |
| packages/plugin-drizzle/tests/related.test.ts | Switch tests to use @pothos/test-utils execute helper. |
| packages/plugin-drizzle/tests/related-field.test.ts | Switch tests to use @pothos/test-utils execute helper. |
| packages/plugin-drizzle/tests/related-connection.test.ts | Switch tests to use @pothos/test-utils execute helper. |
| packages/plugin-drizzle/tests/query-path.test.ts | Switch tests to use @pothos/test-utils execute helper. |
| packages/plugin-drizzle/tests/node.test.ts | Switch tests to use @pothos/test-utils execute helper. |
| packages/plugin-drizzle/tests/interfaces.test.ts | Switch tests to use @pothos/test-utils execute helper. |
| packages/plugin-drizzle/tests/incompatible.test.ts | Switch tests to use @pothos/test-utils execute helper. |
| packages/plugin-drizzle/tests/fragment-alias-different-fields.test.ts | Switch tests to use @pothos/test-utils execute helper. |
| packages/plugin-drizzle/tests/drizzle-field.test.ts | Switch tests to use @pothos/test-utils execute helper. |
| packages/plugin-drizzle/tests/drizzle-connections.test.ts | Switch tests to use @pothos/test-utils execute helper. |
| packages/plugin-drizzle/tests/defer.test.ts | Switch tests to use @pothos/test-utils execute helper. |
| packages/plugin-drizzle/tests/connection-helpers.test.ts | Switch tests to use @pothos/test-utils execute helper. |
| packages/plugin-drizzle/tests/compatible.test.ts | Switch tests to use @pothos/test-utils execute helper. |
| packages/plugin-drizzle/package.json | Widen graphql peerDependency range to include v17. |
| packages/plugin-directives/vitest.config.js | Force single GraphQL module instance + inline deps; set tsgo checker. |
| packages/plugin-directives/tests/snapshots/index.test.ts.snap | Snapshot updates due to GraphQL 17 printer formatting differences. |
| packages/plugin-directives/package.json | Widen graphql peerDependency range to include v17. |
| packages/plugin-dataloader/package.json | Widen graphql peerDependency range to include v17. |
| packages/plugin-complexity/src/variable-values.ts | Add helper to adapt variableValues shape across GraphQL 16/17. |
| packages/plugin-complexity/src/validator.ts | Use variable-values adapter when building synthetic resolve info. |
| packages/plugin-complexity/src/util.ts | Use variable-values adapter when building synthetic resolve info. |
| packages/plugin-complexity/package.json | Widen graphql peerDependency range to include v17. |
| packages/plugin-add-graphql/package.json | Widen graphql peerDependency range to include v17. |
| packages/core/tests/scalar-coercion.test.ts | Add tests covering GraphQL 17 scalar coercion hook wiring. |
| packages/core/src/types/global/type-options.ts | Extend scalar type options to include GraphQL 17 coercion hooks. |
| packages/core/src/builder.ts | Pass through GraphQL 17 scalar coercion hooks when building scalars. |
| packages/core/src/build-cache.ts | Adjust internal type accessors for GraphQL 17 GraphQLNonNull<T> constraints. |
| packages/core/package.json | Widen graphql peerDependency range to include v17. |
| packages/converter/src/index.ts | Include GraphQLArgument in writeDescription union for GraphQL 17 typing change. |
| package.json | Pin dev GraphQL to 17 and update @typescript/native-preview version; add override. |
| examples/simple-interfaces/package.json | Use tsgo --noEmit for example typechecking. |
| examples/simple-classes/package.json | Use tsgo --noEmit for example typechecking. |
| examples/relay-windowed-pagination/package.json | Use tsgo --noEmit for example typechecking. |
| examples/prisma/package.json | Use tsgo --noEmit for example typechecking. |
| examples/prisma-subscriptions/package.json | Use tsgo --noEmit for example typechecking. |
| examples/prisma-smart-subscriptions/package.json | Use tsgo --noEmit for example typechecking. |
| examples/prisma-relay/package.json | Use tsgo --noEmit for example typechecking. |
| examples/prisma-federation/package.json | Use tsgo --noEmit for example typechecking. |
| examples/open-telemetry/package.json | Use tsgo --noEmit for example typechecking. |
| examples/nextjs/tsconfig.json | Configure GraphQLSP plugin output for gql.tada schema typing. |
| examples/nextjs/package.json | Replace graphql-codegen with gql.tada + GraphQLSP; use tsgo for types. |
| examples/nextjs/graphql/tada.ts | Add typed graphql() helper via initGraphQLTada. |
| examples/nextjs/graphql-env.d.ts | Add generated introspection typing for gql.tada. |
| examples/nextjs/components/Posts.tsx | Switch document typing import from codegen output to gql.tada helper. |
| examples/nextjs/components/generated/index.ts | Remove graphql-codegen generated entrypoint (no longer used). |
| examples/nextjs/components/generated/graphql.ts | Remove graphql-codegen generated types (replaced by gql.tada). |
| examples/nextjs/components/generated/gql.ts | Remove graphql-codegen generated graphql() helper (replaced by gql.tada). |
| examples/nextjs/components/generated/fragment-masking.ts | Remove graphql-codegen fragment masking helper (no longer used). |
| examples/nextjs/codegen.yml | Remove graphql-codegen config (migration to gql.tada). |
| examples/federation/package.json | Use tsgo --noEmit for example typechecking. |
| examples/fastify-mercurius/package.json | Use tsgo --noEmit for example typechecking. |
| examples/complex-app/package.json | Drop graphql-codegen script/deps; use tsgo --noEmit for types. |
| examples/complex-app/codegen.ts | Remove graphql-codegen config (no longer used). |
| biome.json | Ignore generated graphql-env.d.ts alongside existing schema ignores. |
| .changeset/graphql-17-support.md | Add changeset documenting GraphQL 17 support and key compatibility work. |
Files not reviewed (4)
- examples/nextjs/components/generated/fragment-masking.ts: Generated file
- examples/nextjs/components/generated/gql.ts: Generated file
- examples/nextjs/components/generated/graphql.ts: Generated file
- examples/nextjs/components/generated/index.ts: Generated file
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| import { | ||
| type ExecutionArgs, | ||
| type ExecutionResult, | ||
| execute as stableExecute, | ||
| versionInfo, | ||
| } from 'graphql'; |
| if (versionInfo.major < 17) { | ||
| return stableExecute(args) as Promise<ExecutionResult>; | ||
| } | ||
|
|
||
| // `experimentalExecuteIncrementally` only exists on graphql 17; load it off the namespace so the | ||
| // module still resolves on 16 (where the named export is absent), and cast through `unknown` | ||
| // since graphql 16's types don't declare it. | ||
| const graphql = (await import('graphql')) as unknown as { | ||
| experimentalExecuteIncrementally: ( | ||
| args: ExecutionArgs, | ||
| ) => Promise<ExecutionResult | Incrementalish>; | ||
| }; | ||
|
|
||
| const result = await graphql.experimentalExecuteIncrementally(args); | ||
|
|
Address review feedback on the incremental execute helper: replace
`await import('graphql')` with the statically imported namespace so the
helper shares the single graphql module instance the rest of the suite
resolves (a dynamic import can load graphql's ESM build in the CJS output,
reintroducing cross-realm errors on graphql 17), and drop the incorrect
`as Promise<ExecutionResult>` cast on `execute` (which returns PromiseOrValue).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Support graphql 16 and 17 in parallel — peer deps keep accepting 16 — while making the source forward-compatible with 17 and getting the full suite + CI green on 17. Replaces the stale #1348 (built against
17.0.0-alpha.7, whose APIs were dropped before 17.0.0 stable).Status: all 107 build/generate/test/type tasks pass on graphql 17; lint is clean on every tracked file.
Dependencies
^16.10.0→^16.10.0 || ^17.0.0across all plugins/packages. 16 stays supported.pnpm.overridespinned to graphql^17.0.1so CI/local exercises the new path (the test-matrix knob, not a peer constraint).@typescript/native-preview(tsgo) pinned to7.0.0-dev.20260616.1— see CI section.Source compatibility decisions
Each is the smallest change correct on both majors. Inline comments only where there's actual 16/17 branching; the rest is here for review.
core/build-cache.tsGraphQLNonNull<T>now requiresT extends GraphQLNullableTypeplugin-sub-graph/util.ts.ofType(always nullable) toGraphQLNullableType(exported in both)plugin-complexity(+variable-values.ts)variableValues→{ sources, coerced }(read viagetArgumentValues)asVariableValues()builds the version's shape (versionInfo.major >= 17); commented inlineconverter/index.tsGraphQLArgumentno longer assignable toGraphQLFieldwriteDescriptionunion (only.descriptionis read)Runtime / test fixes (graphql 17)
@defer/@streamexecution (drizzle + prisma, ~167 tests). graphql 17 moved incremental delivery out of stableexecute, which now throws on any schema declaring those directives. The drizzle/prisma example schemas declare@deferfor the plugins' defer-aware query planning, and the tests calledexecute()directly. Added a version-awareexecutehelper to@pothos/test-utils: 16 path unchanged; on 17 it routes throughexperimentalExecuteIncrementallyand collapses incremental payloads back into one result (maps pendingid→path, deep-merges deferdata, appends streamitems). The 28 test files use the helper; single-result snapshots pass unchanged. Verified drizzle 90/90 + prisma 89/89 on 17, and drizzle 90/90 on 16.@graphql-tools/@envelop/@apollo(another), tripping 17's stricter cross-realm check. Pin each suite's vitest config to a single resolved graphql (absolute-path alias +dedupe+ inline the graphql-touching deps).CI fixes
@typescript/native-previewmis-resolved graphql 17's types through built.d.tsfiles, reporting ~743 spuriousimplicitly anyerrors in plugin test schemas (stabletsc6and the build were always clean). The June snapshot resolves them.tsgo(it defaults totsc, which isn't installed — typescript shipstsc6). Fixes the dataloader test task and runs the*.test-d.tsassertions.typescripttsc --noEmit→tsgo --noEmit, matching the packages.Examples: graphql-codegen → gql.tada
graphql-codegen doesn't support graphql 17 (latest stable peers
graphql@^16), which broke the nextjs example's codegen. gql.tada works on 17 (nographqlpeer;@0no-co/graphqlspsupports^17).schema.graphql→graphql-env.d.ts), a typedgraphql()helper,Posts.tsxrepointed. Per-document types infer in the type system; only the schema env regenerates on change. (Worked around a gql.tada CLIstdin.unref()crash on Node 24 by piping stdin.)build-schema.tsalready emits the SDL; the page uses urql's runtimegql) — removed the deps + script.Remaining (not graphql 17)
Lint reports 52 errors only in the untracked
website/public/playground-examples/*.jsonWIP — pre-existing, out of scope for this PR.Commits
feat: support graphql 17·test: incremental delivery helper·test: SDL snapshots·test: single graphql instance·build: tsgo + vitest checker·example(nextjs): gql.tada·example(complex-app): drop codegen·chore: biome ignore graphql-env🤖 Generated with Claude Code