in composition/src/v1/normalization/normalization-factory.ts [795:869]
validateDirectives(data: NodeData | SchemaData, directiveCoords: string) {
const undefinedDirectiveNames = new Set<string>();
for (const [directiveName, directiveNodes] of data.directivesByDirectiveName) {
const definitionData = this.directiveDefinitionDataByDirectiveName.get(directiveName);
if (!definitionData) {
if (!undefinedDirectiveNames.has(directiveName)) {
this.errors.push(undefinedDirectiveError(directiveName, directiveCoords));
undefinedDirectiveNames.add(directiveName);
}
continue;
}
const definitionErrorMessages: Array<string> = [];
const directiveLocation = nodeKindToDirectiveLocation(data.kind);
if (!definitionData.locations.has(directiveLocation)) {
definitionErrorMessages.push(invalidDirectiveLocationErrorMessage(directiveName, directiveLocation));
}
if (directiveNodes.length > 1 && !definitionData.isRepeatable) {
const handledDirectiveNames = getValueOrDefault(
this.invalidRepeatedDirectiveNameByCoords,
directiveCoords,
() => new Set<string>(),
);
if (!handledDirectiveNames.has(directiveName)) {
handledDirectiveNames.add(directiveName);
definitionErrorMessages.push(invalidRepeatedDirectiveErrorMessage(directiveName));
}
}
const requiredArgumentNames = [...definitionData.requiredArgumentNames];
for (let i = 0; i < directiveNodes.length; i++) {
const errorMessages = this.validateDirective({
data,
directiveNode: directiveNodes[i],
definitionData,
directiveCoords,
errorMessages: i < 1 ? definitionErrorMessages : [],
requiredArgumentNames,
});
if (errorMessages.length > 0) {
this.errors.push(
invalidDirectiveError(directiveName, directiveCoords, numberToOrdinal(i + 1), errorMessages),
);
}
}
}
switch (data.kind) {
case Kind.ENUM_TYPE_DEFINITION: {
for (const [enumValueName, enumValueData] of data.enumValueDataByValueName) {
this.validateDirectives(enumValueData, `${data.name}.${enumValueName}`);
}
return;
}
case Kind.FIELD_DEFINITION: {
for (const [argumentName, argumentData] of data.argumentDataByArgumentName) {
this.validateDirectives(argumentData, `${data.originalParentTypeName}.${data.name}(${argumentName}: ...)`);
}
return;
}
case Kind.INPUT_OBJECT_TYPE_DEFINITION: {
for (const [inputValueName, inputValueData] of data.inputValueDataByValueName) {
this.validateDirectives(inputValueData, `${data.name}.${inputValueName}`);
}
return;
}
case Kind.INTERFACE_TYPE_DEFINITION:
// intentional fallthrough
case Kind.OBJECT_TYPE_DEFINITION: {
for (const [fieldName, fieldData] of data.fieldDataByFieldName) {
this.validateDirectives(fieldData, `${data.name}.${fieldName}`);
}
return;
}
default:
return;
}
}