UNPKG

@theguild/federation-composition

Version:
64 lines (63 loc) 2.44 kB
import { GraphQLError, Kind, } from 'graphql'; export function OnlyInterfaceImplementationRule(context) { const { definitions } = context.getDocument(); let filled = false; const typeNameToKind = new Map(); function fillTypeNameToKindMap() { for (const node of definitions) { switch (node.kind) { case Kind.OBJECT_TYPE_DEFINITION: case Kind.OBJECT_TYPE_EXTENSION: typeNameToKind.set(node.name.value, 'ObjectType'); break; case Kind.INTERFACE_TYPE_DEFINITION: case Kind.INTERFACE_TYPE_EXTENSION: typeNameToKind.set(node.name.value, 'InterfaceType'); break; case Kind.UNION_TYPE_DEFINITION: case Kind.UNION_TYPE_EXTENSION: typeNameToKind.set(node.name.value, 'UnionType'); break; case Kind.ENUM_TYPE_DEFINITION: case Kind.ENUM_TYPE_EXTENSION: typeNameToKind.set(node.name.value, 'EnumType'); break; case Kind.SCALAR_TYPE_DEFINITION: case Kind.SCALAR_TYPE_EXTENSION: typeNameToKind.set(node.name.value, 'ScalarType'); break; case Kind.INPUT_OBJECT_TYPE_DEFINITION: case Kind.INPUT_OBJECT_TYPE_EXTENSION: typeNameToKind.set(node.name.value, 'InputObjectType'); break; } } filled = true; } function findKindByName(typeName) { if (!filled) { fillTypeNameToKindMap(); } return typeNameToKind.get(typeName); } function check(node) { if (!node.interfaces) { return; } for (const interfaceNode of node.interfaces) { const interfaceName = interfaceNode.name.value; const kind = findKindByName(interfaceName); if (kind && kind !== 'InterfaceType') { context.reportError(new GraphQLError(`Cannot implement non-interface type ${interfaceName} (of type ObjectType)`, { extensions: { code: 'INVALID_GRAPHQL', }, })); } } } return { ObjectTypeDefinition: check, ObjectTypeExtension: check, }; }