Skip to content

Commit

Permalink
fix(stitch): respect interface types as computed field types
Browse files Browse the repository at this point in the history
  • Loading branch information
ardatan committed Apr 24, 2024
1 parent ee853ed commit 6d26702
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 30 deletions.
5 changes: 5 additions & 0 deletions .changeset/purple-monkeys-vanish.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@graphql-tools/stitch": patch
---

Respect interface types as computed field types
16 changes: 10 additions & 6 deletions packages/federation/test/__snapshots__/supergraphs.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,11 @@ exports[`Supergraphs d.graphql matches: d.graphql - stitchedSchema 1`] = `
}
type Query {
getAuthor: ReactionAuthor
node(id: ID!): Node
}
interface Node {
id: ID!
}
type Mutation {
Expand Down Expand Up @@ -556,10 +560,6 @@ type ConcreteBoard implements Board & Node & SomeBoard {
scalar Url @specifiedBy(url: "https://datatracker.ietf.org/doc/html/rfc1738")
interface Node {
id: ID!
}
union Mentionable = ReactionAuthor | OwnerChangedNotification
type OwnerChangedNotification implements AppNotification {
Expand Down Expand Up @@ -594,9 +594,14 @@ exports[`Supergraphs d.graphql subgraphs: d.graphql - NODERESOLVER 1`] = `
}
type Query {
node(id: ID!): Node
_entities(representations: [_Any!]!): _Entity
}
interface Node {
id: ID!
}
union _Entity
scalar _Any"
Expand All @@ -613,7 +618,6 @@ type Mutation {
}
type Query {
getAuthor: ReactionAuthor
_entities(representations: [_Any!]!): _Entity
}
Expand Down
4 changes: 4 additions & 0 deletions packages/federation/test/fixtures/supergraphs/d.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ interface Board {
isVisible: Boolean!
}

type Query {
node(id: ID!): Node @join__field(graph: NODERESOLVER)
}

interface SomeBoard {
# introducing this interface and field causes:
# Mesh - Supergraph 💥 Failed to generate the schema Error: Unknown type: "SomeEntity".
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,16 +227,11 @@ type IsolatedSubschemaInput = Exclude<SubschemaConfig, 'merge'> & {
function filterIsolatedSubschema(subschemaConfig: IsolatedSubschemaInput): SubschemaConfig {
const rootFields: Record<string, boolean> = {};
const computedFieldTypes: Record<string, boolean> = {}; // contains types of computed fields that have no root field
const visitedTypes = new WeakSet<GraphQLNamedOutputType>();
function listReachableTypesToIsolate(
subschemaConfig: SubschemaConfig,
type: GraphQLNamedOutputType,
typeNames: string[] = [],
typeNames = new Set<string>(),
) {
if (visitedTypes.has(type)) {
return typeNames;
}
visitedTypes.add(type);
if (isScalarType(type)) {
return typeNames;
} else if (
Expand All @@ -246,38 +241,30 @@ function filterIsolatedSubschema(subschemaConfig: IsolatedSubschemaInput): Subsc
subschemaConfig.merge[type.name].selectionSet
) {
// this is a merged type, no need to descend further
if (!typeNames.includes(type.name)) {
typeNames.push(type.name);
}
typeNames.add(type.name);
return typeNames;
} else if (isCompositeType(type)) {
if (!typeNames.includes(type.name)) {
typeNames.push(type.name);
}
typeNames.add(type.name);

// descent into all field types potentially via interfaces implementations/unions members
const types: GraphQLObjectType[] = [];
const types = new Set<GraphQLObjectType>();
if (isObjectType(type)) {
types.push(type);
types.add(type);
} else if (isInterfaceType(type)) {
types.push(
...getImplementingTypes(type.name, subschemaConfig.schema).map(
name => subschemaConfig.schema.getType(name)! as GraphQLObjectType,
),
getImplementingTypes(type.name, subschemaConfig.schema).forEach(name =>
types.add(subschemaConfig.schema.getType(name)! as GraphQLObjectType),
);
} else if (isUnionType(type)) {
types.push(...type.getTypes());
type.getTypes().forEach(t => types.add(t));
}

for (const type of types) {
if (!typeNames.includes(type.name)) {
typeNames.push(type.name);
}
typeNames.add(type.name);

for (const f of Object.values(type.getFields())) {
const fieldType = getNamedType(f.type);
if (!typeNames.includes(fieldType.name) && isCompositeType(fieldType)) {
typeNames.push(...listReachableTypesToIsolate(subschemaConfig, fieldType));
if (!typeNames.has(fieldType.name) && isCompositeType(fieldType)) {
listReachableTypesToIsolate(subschemaConfig, fieldType, typeNames);
}
}
}
Expand Down Expand Up @@ -310,6 +297,7 @@ function filterIsolatedSubschema(subschemaConfig: IsolatedSubschemaInput): Subsc

for (const fieldName of computedFields) {
const fieldType = getNamedType(type.getFields()[fieldName!].type);
computedFieldTypes[fieldType.name] = true;
listReachableTypesToIsolate(subschemaConfig, fieldType).forEach(tn => {
computedFieldTypes[tn] = true;
});
Expand Down

0 comments on commit 6d26702

Please sign in to comment.