| import { GraphQLError } from '../../error/GraphQLError.mjs'; |
| import { |
| isInputObjectType, |
| isInterfaceType, |
| isObjectType, |
| } from '../../type/definition.mjs'; |
|
|
| /** |
| * Unique field definition names |
| * |
| * A GraphQL complex type is only valid if all its fields are uniquely named. |
| */ |
| export function UniqueFieldDefinitionNamesRule(context) { |
| const schema = context.getSchema(); |
| const existingTypeMap = schema ? schema.getTypeMap() : Object.create(null); |
| const knownFieldNames = Object.create(null); |
| return { |
| InputObjectTypeDefinition: checkFieldUniqueness, |
| InputObjectTypeExtension: checkFieldUniqueness, |
| InterfaceTypeDefinition: checkFieldUniqueness, |
| InterfaceTypeExtension: checkFieldUniqueness, |
| ObjectTypeDefinition: checkFieldUniqueness, |
| ObjectTypeExtension: checkFieldUniqueness, |
| }; |
|
|
| function checkFieldUniqueness(node) { |
| var _node$fields; |
|
|
| const typeName = node.name.value; |
|
|
| if (!knownFieldNames[typeName]) { |
| knownFieldNames[typeName] = Object.create(null); |
| } // FIXME: https://github.com/graphql/graphql-js/issues/2203 |
|
|
| /* c8 ignore next */ |
|
|
| const fieldNodes = |
| (_node$fields = node.fields) !== null && _node$fields !== void 0 |
| ? _node$fields |
| : []; |
| const fieldNames = knownFieldNames[typeName]; |
|
|
| for (const fieldDef of fieldNodes) { |
| const fieldName = fieldDef.name.value; |
|
|
| if (hasField(existingTypeMap[typeName], fieldName)) { |
| context.reportError( |
| new GraphQLError( |
| `Field "${typeName}.${fieldName}" already exists in the schema. It cannot also be defined in this type extension.`, |
| { |
| nodes: fieldDef.name, |
| }, |
| ), |
| ); |
| } else if (fieldNames[fieldName]) { |
| context.reportError( |
| new GraphQLError( |
| `Field "${typeName}.${fieldName}" can only be defined once.`, |
| { |
| nodes: [fieldNames[fieldName], fieldDef.name], |
| }, |
| ), |
| ); |
| } else { |
| fieldNames[fieldName] = fieldDef.name; |
| } |
| } |
|
|
| return false; |
| } |
| } |
|
|
| function hasField(type, fieldName) { |
| if (isObjectType(type) || isInterfaceType(type) || isInputObjectType(type)) { |
| return type.getFields()[fieldName] != null; |
| } |
|
|
| return false; |
| } |