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; } } } } }; }