Skip to content

Commit

Permalink
Relax external field requirements (#3142)
Browse files Browse the repository at this point in the history
Relax error for detecting whether `@external` field matches. If the
external field has extra optional parameters, allow it to pass
composition as being able to pass the parameter is not necessary for a
required field.
  • Loading branch information
clenfest authored Sep 16, 2024
1 parent e6c05b6 commit fc55ac9
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/slow-cups-exist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@apollo/composition": patch
---

Relax error for detecting whether `@external` field matches. If the external field has extra optional parameters, allow it to pass composition as being able to pass the parameter is not necessary for a required field.
34 changes: 33 additions & 1 deletion composition-js/src/__tests__/compose.external.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ describe('tests related to @external', () => {
typeDefs: gql`
type T @key(fields: "id") {
id: ID!
f(x: Int): String @shareable
f(x: Int!): String @shareable
}
`,
};
Expand All @@ -73,6 +73,38 @@ describe('tests related to @external', () => {
['EXTERNAL_ARGUMENT_MISSING', 'Field "T.f" is missing argument "T.f(x:)" in some subgraphs where it is marked @external: argument "T.f(x:)" is declared in subgraph "subgraphB" but not in subgraph "subgraphA" (where "T.f" is @external).'],
]);
});

it('succeeds on @external definition where difference between definitions is an optional argument', () => {
const subgraphA = {
name: 'subgraphA',
typeDefs: gql`
type Query {
locations: [Location]
}
type Location @key(fields: "id") {
id: ID!
name: String!
photo(smallVersion: Boolean): String! # New optional arg shouldn't break existing clients
}
`,
};

const subgraphB = {
name: 'subgraphB',
typeDefs: gql`
type Location @key(fields: "id") {
id: ID!
photo: String! @external
banner: String @requires(fields: "photo")
}
`,
};

const result = composeAsFed2Subgraphs([subgraphA, subgraphB]);
assertCompositionSuccess(result);
});


it('errors on incompatible argument types in @external declaration', () => {
const subgraphA = {
Expand Down
4 changes: 3 additions & 1 deletion composition-js/src/merging/merge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1864,7 +1864,9 @@ class Merger {
const name = destArg.name;
const arg = source.argument(name);
if (!arg) {
invalidArgsPresence.add(name);
if (!destArg.type || destArg.type.kind === 'NonNullType') {
invalidArgsPresence.add(name);
}
continue;
}
if (!sameType(destArg.type!, arg.type!) && !this.isStrictSubtype(arg.type!, destArg.type!)) {
Expand Down

0 comments on commit fc55ac9

Please sign in to comment.