Skip to content

Commit

Permalink
Allow @interfaceObject to stand in for all runtime types (#3087)
Browse files Browse the repository at this point in the history
Rather than relying on the fact that one filteredPaths is reached, allow
@interfaceObject types to intersect with all runtime types
  • Loading branch information
clenfest authored Jul 19, 2024
1 parent 0cad761 commit 4d9e0f6
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/curvy-papayas-sit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@apollo/composition": patch
---

When doing interface type intersection detection, allow @interfaceObject to stand in for any type
69 changes: 69 additions & 0 deletions composition-js/src/__tests__/compose.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5220,4 +5220,73 @@ describe('@source* directives', () => {
);
});
});

it('fed-354 repro @interfaceObject failure', () => {
const subgraph1 = {
name: 'Subgraph1',
url: 'https://Subgraph1',
typeDefs: gql`
type Query {
error_query: TicketField!
}
type User @interfaceObject @key(fields: "id") {
id: ID!
}
interface TicketField {
id: ID!
createdBy: User
}
type TextTicketField implements TicketField @key(fields: "id") @shareable {
id: ID!
createdBy: User
}
`
};

const subgraph2 = {
name: 'Subgraph2',
url: 'https://Subgraph2',
typeDefs: gql`
interface Ticket @key(fields : "id", resolvable : true) {
id: ID!
}
interface User @key(fields : "id", resolvable : true) {
id: ID!
requestedTickets: [Ticket!]!
}
interface TicketField {
createdBy: User
id: ID!
}
type TextTicketField implements TicketField @shareable {
createdBy: User
id: ID!
}
type Customer implements User @key(fields : "id", resolvable : true) @shareable {
id: ID!
requestedTickets: [Ticket!]!
}
type Agent implements User @key(fields : "id", resolvable : true) @shareable {
id: ID!
requestedTickets: [Ticket!]!
}
type Question implements Ticket @key(fields : "id", resolvable : true) {
fields: [TicketField!]!
id: ID!
}
`
};

const result = composeAsFed2Subgraphs([subgraph1, subgraph2]);
assertCompositionSuccess(result);
});
});
8 changes: 8 additions & 0 deletions composition-js/src/validate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,14 @@ export class ValidationState {
for (const { path } of newSubgraphPathInfos) {
const subgraph = path.path.tail.source;
const typeNames = possibleRuntimeTypeNamesSorted(path.path);

// if we see a type here that is not included in the list of all
// runtime types, it is safe to assume that it is an interface
// behaving like a runtime type (i.e. an @interfaceObject) and
// we should allow it to stand in for any runtime type
if (typeNames.length === 1 && !allRuntimeTypes.includes(typeNames[0])) {
continue;
}
runtimeTypesPerSubgraphs.set(subgraph, typeNames);
// Note: we're formatting the elements in `runtimeTYpesToSubgraphs` because we're going to use it if we display an error. This doesn't
// impact our set equality though since the formatting is consistent betweeen elements and type names syntax is sufficiently restricted
Expand Down

0 comments on commit 4d9e0f6

Please sign in to comment.