Class: GraphQL::Stitching::Composer::ValidateInterfaces
- Inherits:
-
BaseValidator
- Object
- BaseValidator
- GraphQL::Stitching::Composer::ValidateInterfaces
- Defined in:
- lib/graphql/stitching/composer/validate_interfaces.rb
Instance Method Summary collapse
-
#perform(supergraph, composer) ⇒ Object
For each composed interface, check the interface against each possible type to assure that intersecting fields have compatible types, structures, and nullability.
Instance Method Details
#perform(supergraph, composer) ⇒ Object
For each composed interface, check the interface against each possible type to assure that intersecting fields have compatible types, structures, and nullability. Verifies compatibility of types that inherit interface contracts through merging.
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/graphql/stitching/composer/validate_interfaces.rb', line 10 def perform(supergraph, composer) supergraph.schema.types.each do |type_name, interface_type| next unless interface_type.kind.interface? supergraph.schema.possible_types(interface_type).each do |possible_type| interface_type.fields.each do |field_name, interface_field| # graphql-ruby will dynamically apply interface fields on a type implementation, # so check the delegation map to assure that all materialized fields have resolver locations. unless supergraph.locations_by_type_and_field[possible_type.graphql_name][field_name]&.any? raise Composer::ValidationError, "Type #{possible_type.graphql_name} does not implement a `#{field_name}` field in any location, "\ "which is required by interface #{interface_type.graphql_name}." end intersecting_field = possible_type.fields[field_name] interface_type_structure = Util.flatten_type_structure(interface_field.type) possible_type_structure = Util.flatten_type_structure(intersecting_field.type) if possible_type_structure.length != interface_type_structure.length raise Composer::ValidationError, "Incompatible list structures between field #{possible_type.graphql_name}.#{field_name} of type "\ "#{intersecting_field.type.to_type_signature} and interface #{interface_type.graphql_name}.#{field_name} of type #{interface_field.type.to_type_signature}." end interface_type_structure.each_with_index do |interface_struct, index| possible_struct = possible_type_structure[index] if possible_struct[:name] != interface_struct[:name] raise Composer::ValidationError, "Incompatible named types between field #{possible_type.graphql_name}.#{field_name} of type "\ "#{intersecting_field.type.to_type_signature} and interface #{interface_type.graphql_name}.#{field_name} of type #{interface_field.type.to_type_signature}." end if possible_struct[:null] && !interface_struct[:null] raise Composer::ValidationError, "Incompatible nullability between field #{possible_type.graphql_name}.#{field_name} of type "\ "#{intersecting_field.type.to_type_signature} and interface #{interface_type.graphql_name}.#{field_name} of type #{interface_field.type.to_type_signature}." end end end end end end |