enter()

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