UNPKG

@apollo/federation

Version:
83 lines (74 loc) 2.6 kB
import { GraphQLError, visit, ObjectTypeDefinitionNode, ObjectTypeExtensionNode, } from 'graphql'; import { ServiceDefinition, DefaultRootOperationTypeName } from '../../types'; import { logServiceAndType, errorWithCode, defaultRootOperationNameLookup } from '../../utils'; /** * - When a schema definition or extension is provided, warn user against using * default root operation type names for types or extensions * (Query, Mutation, Subscription) */ export const rootFieldUsed = ({ name: serviceName, typeDefs, }: ServiceDefinition) => { const errors: GraphQLError[] = []; // Array of default root operation names const defaultRootOperationNames = Object.values( defaultRootOperationNameLookup, ); const disallowedTypeNames: { [key in DefaultRootOperationTypeName]?: boolean; } = {}; let hasSchemaDefinitionOrExtension = false; visit(typeDefs, { OperationTypeDefinition(node) { // If we find at least one root operation type definition, we know the user has // specified either a schema definition or extension. hasSchemaDefinitionOrExtension = true; if ( !defaultRootOperationNames.includes(node.type.name .value as DefaultRootOperationTypeName) ) { disallowedTypeNames[ defaultRootOperationNameLookup[node.operation] ] = true; } }, }); // If a schema or schema extension is defined, we need to warn for each improper // usage of default root operation names. The conditions for an improper usage are: // 1. root operation type is defined as a non-default name (i.e. query: RootQuery) // 2. the respective default operation type name is used as a regular type if (hasSchemaDefinitionOrExtension) { visit(typeDefs, { ObjectTypeDefinition: visitType, ObjectTypeExtension: visitType, }); function visitType( node: ObjectTypeDefinitionNode | ObjectTypeExtensionNode, ) { if ( disallowedTypeNames[node.name.value as DefaultRootOperationTypeName] ) { const rootOperationName = node.name.value; errors.push( errorWithCode( `ROOT_${rootOperationName.toUpperCase()}_USED`, logServiceAndType(serviceName, rootOperationName) + `Found invalid use of default root operation name \`${rootOperationName}\`. \`${rootOperationName}\` is disallowed when \`Schema.${rootOperationName.toLowerCase()}\` is set to a type other than \`${rootOperationName}\`.`, node, ), ); } } } return errors; };