diff --git a/__tests__/__snapshots__/integration.test.ts.snap b/__tests__/__snapshots__/integration.test.ts.snap index ebc089e..d3af5cf 100644 --- a/__tests__/__snapshots__/integration.test.ts.snap +++ b/__tests__/__snapshots__/integration.test.ts.snap @@ -58,23 +58,6 @@ interface Node { } type Query { - """ - Exposes the root query type nested one level down. This is helpful for Relay 1 - which can only query top level fields if they are in a particular form. - """ - query: Query! - - """ - The root query type must be a \`Node\` to work well with Relay 1 mutations. This just resolves to \`query\`. - """ - nodeId: ID! - - """Fetches an object given its globally unique \`ID\`.""" - node( - """The globally unique \`ID\`.""" - nodeId: ID! - ): Node - """Reads a set of \`Email\`.""" allEmailsList( """Only read the first \`n\` values of the set.""" diff --git a/__tests__/__snapshots__/schema.test.ts.snap b/__tests__/__snapshots__/schema.test.ts.snap index f0f9c54..7b0f8be 100644 --- a/__tests__/__snapshots__/schema.test.ts.snap +++ b/__tests__/__snapshots__/schema.test.ts.snap @@ -59,23 +59,6 @@ interface Node { \\"\\"\\"The root query type which gives access points into the data universe.\\"\\"\\" type Query { - \\"\\"\\" - Exposes the root query type nested one level down. This is helpful for Relay 1 - which can only query top level fields if they are in a particular form. - \\"\\"\\" - query: Query! - - \\"\\"\\" - The root query type must be a \`Node\` to work well with Relay 1 mutations. This just resolves to \`query\`. - \\"\\"\\" - nodeId: ID! - - \\"\\"\\"Fetches an object given its globally unique \`ID\`.\\"\\"\\" - node( - \\"\\"\\"The globally unique \`ID\`.\\"\\"\\" - nodeId: ID! - ): Node - \\"\\"\\"Reads a set of \`Email\`.\\"\\"\\" allEmailsList( \\"\\"\\"Only read the first \`n\` values of the set.\\"\\"\\" @@ -255,24 +238,7 @@ directive @provides(fields: _FieldSet!) on FIELD_DEFINITION directive @key(fields: _FieldSet!) on OBJECT | INTERFACE """The root query type which gives access points into the data universe.""" -type Query implements Node { - """ - Exposes the root query type nested one level down. This is helpful for Relay 1 - which can only query top level fields if they are in a particular form. - """ - query: Query! - - """ - The root query type must be a \`Node\` to work well with Relay 1 mutations. This just resolves to \`query\`. - """ - nodeId: ID! - - """Fetches an object given its globally unique \`ID\`.""" - node( - """The globally unique \`ID\`.""" - nodeId: ID! - ): Node - +type Query { """Reads a set of \`Email\`.""" allEmailsList( """Only read the first \`n\` values of the set.""" @@ -360,14 +326,6 @@ type Query implements Node { _service: _Service! @deprecated(reason: "Only Apollo Federation should use this") } -"""An object with a globally unique \`ID\`.""" -interface Node { - """ - A globally unique identifier. Can be used in various places throughout the system to identify this single value. - """ - nodeId: ID! -} - type Email implements Node { """ A globally unique identifier. Can be used in various places throughout the system to identify this single value. @@ -394,6 +352,14 @@ type Email implements Node { ): [UsersEmail!]! } +"""An object with a globally unique \`ID\`.""" +interface Node { + """ + A globally unique identifier. Can be used in various places throughout the system to identify this single value. + """ + nodeId: ID! +} + type UsersEmail implements Node { """ A globally unique identifier. Can be used in various places throughout the system to identify this single value. diff --git a/src/index.ts b/src/index.ts index a95ece0..dfbb01e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -202,8 +202,41 @@ const AddKeyPlugin: Plugin = builder => { }); }; -// Our federation implementation combines these two plugins: +/* + * This plugin remove query/node/nodeId fields and Node interface from Query type to + * fix `GraphQLSchemaValidationError: There can be only one type named "query/node/nodeId"` error. + * This helps Apollo Gateway to consume two or more PostGraphile services. + */ + +const RemoveQueryLegacyFeaturesPlugin: Plugin = builder => { + builder.hook('GraphQLObjectType:fields', (fields, _, context) => { + const { + scope: { isRootQuery }, + } = context; + + // Deleting the query, node, nodeId fields from the Query type that are used by + // the old relay specification which are not needed for modern GraphQL clients + if (isRootQuery) { + delete fields.query; + delete fields.node; + delete fields.nodeId; + } + + return fields; + }); + + builder.hook('GraphQLObjectType:interfaces', (interfaces, _, context) => { + if (!context.scope.isRootQuery) { + return interfaces; + } + // Delete all interfaces (i.e. the Node interface) from Query. + return []; + }); +}; + +// Our federation implementation combines these plugins: export default makePluginByCombiningPlugins( SchemaExtensionPlugin, - AddKeyPlugin + AddKeyPlugin, + RemoveQueryLegacyFeaturesPlugin, );