| import { GraphQLError } from "../../error/GraphQLError.mjs"; |
| import { Kind } from "../../language/kinds.mjs"; |
| import { isTypeDefinitionNode, isTypeExtensionNode } from "../../language/predicates.mjs"; |
| import { specifiedDirectives } from "../../type/directives.mjs"; |
| |
| /** |
| * Unique directive names per location |
| * |
| * A GraphQL document is only valid if all non-repeatable directives at |
| * a given location are uniquely named. |
| */ |
| export function UniqueDirectivesPerLocationRule(context) { |
| var uniqueDirectiveMap = Object.create(null); |
| var schema = context.getSchema(); |
| var definedDirectives = schema ? schema.getDirectives() : specifiedDirectives; |
| |
| for (var _i2 = 0; _i2 < definedDirectives.length; _i2++) { |
| var directive = definedDirectives[_i2]; |
| uniqueDirectiveMap[directive.name] = !directive.isRepeatable; |
| } |
| |
| var astDefinitions = context.getDocument().definitions; |
| |
| for (var _i4 = 0; _i4 < astDefinitions.length; _i4++) { |
| var def = astDefinitions[_i4]; |
| |
| if (def.kind === Kind.DIRECTIVE_DEFINITION) { |
| uniqueDirectiveMap[def.name.value] = !def.repeatable; |
| } |
| } |
| |
| var schemaDirectives = Object.create(null); |
| var typeDirectivesMap = Object.create(null); |
| return { |
| // Many different AST nodes may contain directives. Rather than listing |
| // them all, just listen for entering any node, and check to see if it |
| // defines any directives. |
| enter: function enter(node) { |
| if (node.directives == null) { |
| return; |
| } |
| |
| var seenDirectives; |
| |
| if (node.kind === Kind.SCHEMA_DEFINITION || node.kind === Kind.SCHEMA_EXTENSION) { |
| seenDirectives = schemaDirectives; |
| } else if (isTypeDefinitionNode(node) || isTypeExtensionNode(node)) { |
| var typeName = node.name.value; |
| seenDirectives = typeDirectivesMap[typeName]; |
| |
| if (seenDirectives === undefined) { |
| typeDirectivesMap[typeName] = seenDirectives = Object.create(null); |
| } |
| } else { |
| seenDirectives = Object.create(null); |
| } |
| |
| for (var _i6 = 0, _node$directives2 = node.directives; _i6 < _node$directives2.length; _i6++) { |
| var _directive = _node$directives2[_i6]; |
| var directiveName = _directive.name.value; |
| |
| if (uniqueDirectiveMap[directiveName]) { |
| if (seenDirectives[directiveName]) { |
| context.reportError(new GraphQLError("The directive \"@".concat(directiveName, "\" can only be used once at this location."), [seenDirectives[directiveName], _directive])); |
| } else { |
| seenDirectives[directiveName] = _directive; |
| } |
| } |
| } |
| } |
| }; |
| } |