import { GraphQLError } from '../../error/GraphQLError'; import { Kind } from '../../language/kinds'; import { specifiedDirectives } from '../../type/directives'; export function duplicateDirectiveMessage(directiveName) { return "The directive \"".concat(directiveName, "\" can only be used once at this location."); } /** * 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 UniqueDirectivesPerLocation(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; } } 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) { // Flow can't refine that node.directives will only contain directives, // so we cast so the rest of the code is well typed. var directives = node.directives; if (directives) { var knownDirectives = Object.create(null); for (var _i6 = 0; _i6 < directives.length; _i6++) { var _directive = directives[_i6]; var directiveName = _directive.name.value; if (uniqueDirectiveMap[directiveName]) { if (knownDirectives[directiveName]) { context.reportError(new GraphQLError(duplicateDirectiveMessage(directiveName), [knownDirectives[directiveName], _directive])); } else { knownDirectives[directiveName] = _directive; } } } } } }; }