apollographql / apollographql/federation
Router should support resolving interface implementations across subgraph
- Dominant language
- TypeScript
- Stars
- 725
- Forks
- 276
- Avg merge
- 1h 47m
- Merged PRs (30d)
- 1
Description
GraphQL abstract types (Union, Interface) could be extended or implemented by various concrete types so a field declared to return a single instance or an array of abstract types can return any of those concrete types.
This works well when all implementation or component types reside within the same subgraph.
In the federated case any subgraph could extend union type defined in the other subgraphs or implement an interface defined in the other subgraph. Unfortunately, the router does not resolve all of the components/concrete types across multiple subgraphs, it only resolves the abstract types against the declaring subgraph.
Hence we are requesting to make the router to resolve abstract types against all subgraphs that register extensions or implementations of those.
Here is an example, let's say the interface `Book` has two implementations `TextBook` and `ColoringBook`.
# Single Graph
If these interfaces were implemented in the same (sub)graph, a query on `books` would get results from both implementations.
Single Graph Schema
```
interface Book {
title: String!
author: String!
}
type Textbook implements Book {
title: String!
author: String!
courses: [String!]!
}
type ColoringBook implements Book {
title: String!
author: String!
colors: [String!]!
}
type Query {
books: [Book!]!
}
```
Single Graph Query
```
query BookSupergraph {
books {
title
author
author
... on Textbook {
courses
}
... on ColoringBook {
colors
}
}
}
```
Single Graph Query Response
```
{
"data": {
"books": [
{
"title": "Algorithms",
"author": "Author Algos",
"courses": [
"CS-101"
]
},
{
"title": "KG Coloring",
"author": "Author Color",
"colors": [
"White"
]
}
]
}
}
```
# Interface Implementations across subgraphs
## Schema
TextBook Schema
```
extend schema
@link(url: "https://specs.apollo.dev/federation/v2.0",
import: ["@key", "@shareable"])
interface Sub_Book {
title: String!
author: String!
}
type Sub_Textbook implements Sub_Book {
title: String!
author: String!
courses: [String!]!
}
type Query {
sub_books: [Sub_Book!]!
}
```
ColoringBook Schema
```
extend schema
@link(url: "https://specs.apollo.dev/federation/v2.0",
import: ["@key", "@shareable"])
interface Sub_Book {
title: String!
author: String!
}
type Sub_ColoringBook implements Sub_Book {
title: String!
author: String!
colors: [String!]!
}
`);
// Having sub_books in query will not compose as it is defined by Textbook subgraph.
// type Query {
// sub_books: [Sub_Book!]!
// }
```
## Query
```
query BookSupergraph {
sub_books {
title
author
author
... on Sub_Textbook {
courses
}
... on Sub_ColoringBook {
colors
}
}
}
```
## Response
```
{
"data": {
"sub_books": [
{
"title": "Algorithms",
"author": "Author Algos",
"courses": [
"CS-101"
]
}
]
}
}
```
Asks
1. ColoringBook subgraph should have the ability to say that it could resolve interface `Sub_Book`
2. Router will have access to all implementations of the interfaces across subgraphs and can query these subgraphs separately and merge(flatten) the contents.
A working example is available here: https://stackblitz.com/edit/basic-federation-2-hsrxlr?file=two.js,three.js,one.js (Use Chrome)

Contributor guide
Research direction
Start with the linked StackBlitz example and compare the single-graph and cross-subgraph schemas and queries described in this issue. Done means the router discovers abstract-type implementations registered by multiple subgraphs, queries the relevant subgraphs, and merges the resulting concrete types as requested.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- graphql, typescript
- Domain
- api, distributed-systems
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 30/100