Skip to content

feat(federation): add FieldSet type for selections with inline fragments - #1644

Merged
hayes merged 2 commits into
mainfrom
claude/pothos-issue-1643-3lzy0x
Jul 23, 2026
Merged

feat(federation): add FieldSet type for selections with inline fragments#1644
hayes merged 2 commits into
mainfrom
claude/pothos-issue-1643-3lzy0x

Conversation

@hayes

@hayes hayes commented Jul 23, 2026

Copy link
Copy Markdown
Owner

Fixes #1643

Problem

SelectionFromShape can't express selections that need inline fragments to select through a union or interface field, so @key/@requires/@provides field sets like media { ... on Image { url } ... on Video { url } } only compile with an as unknown as SelectionFromShape<...> cast, which turns checking off entirely and reads as a hack.

Solution

Add a branded string type, FieldSet<Shape>, accepted anywhere a checked selection string is — builder.selection and ref.provides. A single plain as cast replaces the generic argument entirely (the shape is inferred from the brand and still drives resolver parent typing):

requires: builder.selection(
  'media { ... on Image { url } ... on Video { url } }' as FieldSet<{ media: Media[] }>,
),

SelectionFromShape is untouched, so existing checked strings, autocompletion, and type-check performance are unchanged. Un-branded plain strings are still rejected, and a FieldSet branded with one shape doesn't satisfy a selection for a different shape. The brand uses a declare const unique symbol, so there is no runtime change anywhere.

Fully checked fragment-aware selection types (template-literal and object-based forms) were prototyped and work, but were set aside as not worth the added type complexity; they could be layered on later without breaking this API.

Changes

  • src/types.ts: new exported FieldSet<Shape> type
  • src/schema-builder.ts, src/global-types.ts, src/external-ref.ts: builder.selection and provides accept FieldSet<Shape> | SelectionFromShape<Shape>
  • tests/example/media/schema.ts: new example subgraph reproducing the issue's scenario; snapshot shows @requires(fields: "media { ... on Image { url } ... on Video { url } }") in the subgraph SDL
  • tests/field-set-types.ts: type-level assertions (cast-only inference, plain strings still rejected, wrong-shape brands rejected, existing checking unchanged)
  • Docs site (federation.mdx) and plugin README: new "Selections with inline fragments" section
  • Changeset: minor bump for @pothos/plugin-federation

Verification

  • pnpm turbo run type test --filter='@pothos/plugin-federation': 8/8 tests pass, no type errors (TS 7.0.2)
  • Type assertions also verified against TS 5.9 during prototyping
  • biome check clean

🤖 Generated with Claude Code

https://claude.ai/code/session_01DHyy8T9rZry73H64Dxj42L


Generated by Claude Code

claude added 2 commits July 23, 2026 16:08
SelectionFromShape can't express selections that need inline fragments to
select through a union or interface field, forcing an 'as unknown as' cast
that disables checking entirely. FieldSet<Shape> is a branded string that
builder.selection and ref.provides accept alongside checked selection
strings, so complex selections need only a single explicit cast while
keeping the shape for resolver parent typing.

Fixes #1643

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DHyy8T9rZry73H64Dxj42L
The shape is inferred from the FieldSet brand, so builder.selection no
longer needs an explicit generic argument when a cast is used. Update the
example schema, type tests, docs site, and plugin README to show cast-only
usage.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DHyy8T9rZry73H64Dxj42L
@vercel

vercel Bot commented Jul 23, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
pothos Ready Ready Preview, Comment Jul 23, 2026 5:30pm

@changeset-bot

changeset-bot Bot commented Jul 23, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 0234f36

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@pothos/plugin-federation Minor
@pothos-examples/federation Patch
@pothos-examples/prisma-federation Patch

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

@pkg-pr-new

pkg-pr-new Bot commented Jul 23, 2026

Copy link
Copy Markdown

Open in StackBlitz

@pothos/core

npm i https://pkg.pr.new/@pothos/core@1644

@pothos/plugin-add-graphql

npm i https://pkg.pr.new/@pothos/plugin-add-graphql@1644

@pothos/plugin-complexity

npm i https://pkg.pr.new/@pothos/plugin-complexity@1644

@pothos/plugin-dataloader

npm i https://pkg.pr.new/@pothos/plugin-dataloader@1644

@pothos/plugin-directives

npm i https://pkg.pr.new/@pothos/plugin-directives@1644

@pothos/plugin-drizzle

npm i https://pkg.pr.new/@pothos/plugin-drizzle@1644

@pothos/plugin-errors

npm i https://pkg.pr.new/@pothos/plugin-errors@1644

@pothos/plugin-example

npm i https://pkg.pr.new/@pothos/plugin-example@1644

@pothos/plugin-federation

npm i https://pkg.pr.new/@pothos/plugin-federation@1644

@pothos/plugin-grafast

npm i https://pkg.pr.new/@pothos/plugin-grafast@1644

@pothos/plugin-mocks

npm i https://pkg.pr.new/@pothos/plugin-mocks@1644

@pothos/plugin-prisma

npm i https://pkg.pr.new/@pothos/plugin-prisma@1644

@pothos/plugin-prisma-utils

npm i https://pkg.pr.new/@pothos/plugin-prisma-utils@1644

@pothos/plugin-relay

npm i https://pkg.pr.new/@pothos/plugin-relay@1644

@pothos/plugin-scope-auth

npm i https://pkg.pr.new/@pothos/plugin-scope-auth@1644

@pothos/plugin-simple-objects

npm i https://pkg.pr.new/@pothos/plugin-simple-objects@1644

@pothos/plugin-smart-subscriptions

npm i https://pkg.pr.new/@pothos/plugin-smart-subscriptions@1644

@pothos/plugin-sub-graph

npm i https://pkg.pr.new/@pothos/plugin-sub-graph@1644

@pothos/plugin-tracing

npm i https://pkg.pr.new/@pothos/plugin-tracing@1644

@pothos/plugin-validation

npm i https://pkg.pr.new/@pothos/plugin-validation@1644

@pothos/plugin-with-input

npm i https://pkg.pr.new/@pothos/plugin-with-input@1644

@pothos/plugin-zod

npm i https://pkg.pr.new/@pothos/plugin-zod@1644

@pothos/tracing-newrelic

npm i https://pkg.pr.new/@pothos/tracing-newrelic@1644

@pothos/tracing-opentelemetry

npm i https://pkg.pr.new/@pothos/tracing-opentelemetry@1644

@pothos/tracing-sentry

npm i https://pkg.pr.new/@pothos/tracing-sentry@1644

@pothos/tracing-xray

npm i https://pkg.pr.new/@pothos/tracing-xray@1644

commit: 0234f36

@hayes
hayes merged commit 8c44de8 into main Jul 23, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

plugin-federation: builder.selection can't select through a union or interface field

2 participants