diff --git a/.changeset/fine-jobs-love.md b/.changeset/fine-jobs-love.md new file mode 100644 index 00000000000..15d60eee244 --- /dev/null +++ b/.changeset/fine-jobs-love.md @@ -0,0 +1,26 @@ +--- +'@graphql-tools/utils': major +--- + +Support "federation/subgraph style" schemas in `astFromSchema` and `printSchemaWithDirectives` + +If a `GraphQLSchema` doesn't have any defined operation types, we should print the schema definition as an extension rather than omitting it entirely. +They are not a valid schema on their own, but they are valid subgraph schemas in a federation setup, and it is possible to build such schemas with `assumeValid` options. + +```ts +// A schema without defined root types +buildSchema( + /* GraphQL */ ` + extend schema @link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@key"]) + + type User @key(fields: "id") { + id: ID! + username: String + } + `, + { assumeValid: true, assumeValidSDL: true } +) +``` + +**POTENTIAL BREAKING CHANGE**: +This can be a breaking change because now the schema above will be printed as the input, previously `extend schema` was converted to `schema {}`. diff --git a/packages/utils/src/print-schema-with-directives.ts b/packages/utils/src/print-schema-with-directives.ts index 2ab8b2230aa..91c7f6b292c 100644 --- a/packages/utils/src/print-schema-with-directives.ts +++ b/packages/utils/src/print-schema-with-directives.ts @@ -179,7 +179,7 @@ export function astFromSchema( } const schemaNode: SchemaDefinitionNode | SchemaExtensionNode = { - kind: operationTypes != null ? Kind.SCHEMA_DEFINITION : Kind.SCHEMA_EXTENSION, + kind: operationTypes.length ? Kind.SCHEMA_DEFINITION : Kind.SCHEMA_EXTENSION, operationTypes, // ConstXNode has been introduced in v16 but it is not compatible with XNode so we do `as any` for backwards compatibility directives: directives as any, diff --git a/packages/utils/tests/print-schema-with-directives.spec.ts b/packages/utils/tests/print-schema-with-directives.spec.ts index f2d53d05f3d..0eec5094c12 100644 --- a/packages/utils/tests/print-schema-with-directives.spec.ts +++ b/packages/utils/tests/print-schema-with-directives.spec.ts @@ -13,6 +13,7 @@ import { GraphQLString, printSchema, specifiedDirectives, + stripIgnoredCharacters, } from 'graphql'; import { GraphQLJSON } from 'graphql-scalars'; import { makeExecutableSchema } from '@graphql-tools/schema'; @@ -402,4 +403,17 @@ describe('printSchemaWithDirectives', () => { expect(output).toContain('input OneOfInput @oneOf'); } }); + it('prints a federation-style subgraph schema correctly', () => { + const sdl = stripIgnoredCharacters(/* GraphQL */ ` + extend schema @link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@key"]) + + type User @key(fields: "id") { + id: ID! + username: String + } + `); + const userSubgraph = buildSchema(sdl, { assumeValid: true, assumeValidSDL: true }); + const printedSchema = stripIgnoredCharacters(printSchemaWithDirectives(userSubgraph)); + expect(printedSchema).toBe(sdl); + }); });