in composition/src/v1/normalization/normalization-factory.ts [1697:1840]
enter(node) {
const parentData = parentDatas[currentDepth];
const parentTypeName = parentData.name;
if (parentData.kind === Kind.UNION_TYPE_DEFINITION) {
errorMessages.push(invalidSelectionOnUnionErrorMessage(fieldSet, fieldCoordsPath, parentTypeName));
return BREAK;
}
const fieldName = node.name.value;
const currentFieldCoords = `${parentTypeName}.${fieldName}`;
nf.unvalidatedExternalFieldCoords.delete(currentFieldCoords);
// If an object-like was just visited, a selection set should have been entered
if (shouldDefineSelectionSet) {
errorMessages.push(
invalidSelectionSetErrorMessage(
fieldSet,
fieldCoordsPath,
parentTypeName,
kindToTypeString(parentData.kind),
),
);
return BREAK;
}
fieldCoordsPath.push(currentFieldCoords);
fieldPath.push(fieldName);
lastFieldName = fieldName;
const fieldData = parentData.fieldDataByFieldName.get(fieldName);
// undefined if the field does not exist on the parent
if (!fieldData) {
errorMessages.push(undefinedFieldInFieldSetErrorMessage(fieldSet, parentTypeName, fieldName));
return BREAK;
}
if (definedFields[currentDepth].has(fieldName)) {
errorMessages.push(duplicateFieldInFieldSetErrorMessage(fieldSet, currentFieldCoords));
return BREAK;
}
definedFields[currentDepth].add(fieldName);
const { isDefinedExternal, isUnconditionallyProvided } = getOrThrowError(
fieldData.externalFieldDataBySubgraphName,
nf.subgraphName,
`${currentFieldCoords}.externalFieldDataBySubgraphName`,
);
const isFieldConditional = isDefinedExternal && !isUnconditionallyProvided;
if (!isUnconditionallyProvided) {
hasConditionalField = true;
}
const namedTypeName = getTypeNodeNamedTypeName(fieldData.node.type);
// The child could itself be a parent
const namedTypeData = nf.parentDefinitionDataByTypeName.get(namedTypeName);
// The base scalars are not in the parents map
if (
BASE_SCALARS.has(namedTypeName) ||
namedTypeData?.kind === Kind.SCALAR_TYPE_DEFINITION ||
namedTypeData?.kind === Kind.ENUM_TYPE_DEFINITION
) {
if (externalAncestors.size < 1 && !isDefinedExternal) {
if (nf.isSubgraphVersionTwo) {
nf.errors.push(
nonExternalConditionalFieldError(
directiveCoords,
nf.subgraphName,
currentFieldCoords,
fieldSet,
directiveName,
),
);
return;
}
/* In V1, @requires and @provides do not need to declare any part of the field set @external.
* It would appear that any such non-external fields are treated as if they are non-conditionally provided.
* */
nf.warnings.push(
nonExternalConditionalFieldWarning(
directiveCoords,
nf.subgraphName,
currentFieldCoords,
fieldSet,
directiveName,
),
);
return;
}
if (externalAncestors.size < 1 && isUnconditionallyProvided) {
// V2 subgraphs return an error when an external key field on an entity extension is provided.
if (nf.isSubgraphVersionTwo) {
errorMessages.push(
fieldAlreadyProvidedErrorMessage(currentFieldCoords, nf.subgraphName, directiveName),
);
} else {
nf.warnings.push(
fieldAlreadyProvidedWarning(currentFieldCoords, directiveName, directiveCoords, nf.subgraphName),
);
}
return;
}
// @TODO re-assess in v2 because this would be breaking for @provides in v1
if (!isFieldConditional && !isProvides) {
// Do not add unnecessary @requires configurations
return;
}
const conditionalFieldData = getValueOrDefault(
nf.conditionalFieldDataByCoords,
currentFieldCoords,
newConditionalFieldData,
);
const fieldSetCondition = newFieldSetConditionData({
fieldCoordinatesPath: [...fieldCoordsPath],
fieldPath: [...fieldPath],
});
isProvides
? conditionalFieldData.providedBy.push(fieldSetCondition)
: conditionalFieldData.requiredBy.push(fieldSetCondition);
return;
}
if (!namedTypeData) {
// Should not be possible to receive this error
errorMessages.push(unknownTypeInFieldSetErrorMessage(fieldSet, currentFieldCoords, namedTypeName));
return BREAK;
}
// TODO isFieldConditional
if (isDefinedExternal) {
if (isProvides) {
getValueOrDefault(
nf.conditionalFieldDataByCoords,
currentFieldCoords,
newConditionalFieldData,
).providedBy.push(
newFieldSetConditionData({
fieldCoordinatesPath: [...fieldCoordsPath],
fieldPath: [...fieldPath],
}),
);
}
externalAncestors.add(currentFieldCoords);
}
if (
namedTypeData.kind === Kind.OBJECT_TYPE_DEFINITION ||
namedTypeData.kind === Kind.INTERFACE_TYPE_DEFINITION ||
namedTypeData.kind === Kind.UNION_TYPE_DEFINITION
) {
shouldDefineSelectionSet = true;
parentDatas.push(namedTypeData);
return;
}
},