diff --git a/.changeset/green-chairs-nail.md b/.changeset/green-chairs-nail.md new file mode 100644 index 000000000..06b387ef5 --- /dev/null +++ b/.changeset/green-chairs-nail.md @@ -0,0 +1,10 @@ +--- +"@apollo/composition": patch +"@apollo/federation-internals": patch +--- + +Include default deprecation reason in the composed supergraph + +`@deprecated` reason used to be optional so if a subgraph does not specify the reason, it is omitted from the supergraph +schema. [Reason is no longer optional](https://github.com/graphql/graphql-spec/pull/1040) so we should always include it +(even if it has a default value). \ No newline at end of file diff --git a/composition-js/src/__tests__/compose.test.ts b/composition-js/src/__tests__/compose.test.ts index c07e2e394..c7d26ae10 100644 --- a/composition-js/src/__tests__/compose.test.ts +++ b/composition-js/src/__tests__/compose.test.ts @@ -1939,7 +1939,7 @@ describe('composition', () => { const [_, api] = schemas(result); expect(printSchema(api)).toMatchString(` type Query { - a: String @deprecated + a: String @deprecated(reason: "No longer supported") b: String } `); diff --git a/internals-js/src/definitions.ts b/internals-js/src/definitions.ts index 2c1b82558..442a849c6 100644 --- a/internals-js/src/definitions.ts +++ b/internals-js/src/definitions.ts @@ -3260,6 +3260,12 @@ export class Directive< const args = entries.length == 0 ? '' : '(' + entries.map(([n, v]) => `${n}: ${valueToString(v, this.argumentType(n))}`).join(', ') + ')'; return `@${this.name}${args}`; } + + toStringWithDefaultValues(): string { + const entries = Object.entries(this.arguments(true)).filter(([_, v]) => v !== undefined); + const args = entries.length == 0 ? '' : '(' + entries.map(([n, v]) => `${n}: ${valueToString(v, this.argumentType(n))}`).join(', ') + ')'; + return `@${this.name}${args}`; + } } /** diff --git a/internals-js/src/print.ts b/internals-js/src/print.ts index b49803a81..42c31298d 100644 --- a/internals-js/src/print.ts +++ b/internals-js/src/print.ts @@ -24,6 +24,7 @@ import { } from "./definitions"; import { assert } from "./utils"; import { valueToString } from "./values"; +import { GraphQLDeprecatedDirective } from 'graphql/type'; export type PrintOptions = { indentString: string; @@ -235,7 +236,13 @@ function printAppliedDirectives( return ""; } const joinStr = onNewLines ? '\n' + options.indentString : ' '; - const directives = appliedDirectives.map(d => d.toString()).join(joinStr); + const directives = appliedDirectives.map(d => { + if (GraphQLDeprecatedDirective.name === d.name) { + return d.toStringWithDefaultValues(); + } else { + return d.toString(); + } + }).join(joinStr); return onNewLines ? '\n' + options.indentString + directives + (endWithNewLine ? '\n' : '') : ' ' + directives; }