diff --git a/lib/graphql/schema/build_from_definition.rb b/lib/graphql/schema/build_from_definition.rb index 264647da9f..1295af1bbe 100644 --- a/lib/graphql/schema/build_from_definition.rb +++ b/lib/graphql/schema/build_from_definition.rb @@ -99,6 +99,16 @@ def build(schema_superclass, document, default_resolve:, using: {}, base_types: # It's possible that this was already loaded by the directives prev_type = types[definition.name] if prev_type.nil? || prev_type.is_a?(Schema::LateBoundType) + if definition.is_a?(GraphQL::Language::Nodes::ObjectTypeDefinition) || definition.is_a?(Language::Nodes::InterfaceTypeDefinition) + interface_names = definition.interfaces.map(&:name) + transitive_names = interface_names.map { |n| document.definitions.find { |d| d.respond_to?(:name) && d.name == n }&.interfaces&.map(&:name) } + transitive_names.flatten! + transitive_names.compact! + if !(missing_transitive_interfaces = transitive_names - interface_names).empty? + raise GraphQL::Schema::InvalidDocumentError, "type #{definition.name} is missing one or more transitive interface names: #{missing_transitive_interfaces.join(", ")}. Add them to the type's `implements` list and try again." + end + end + types[definition.name] = build_definition_from_node(definition, type_resolver, default_resolve, base_types) end end diff --git a/spec/graphql/schema/build_from_definition_spec.rb b/spec/graphql/schema/build_from_definition_spec.rb index 66d15d3d68..4c3c02f4d2 100644 --- a/spec/graphql/schema/build_from_definition_spec.rb +++ b/spec/graphql/schema/build_from_definition_spec.rb @@ -539,6 +539,29 @@ def assert_schema_and_compare_output(definition) assert_schema_and_compare_output(schema) end + it "requires transitive dependencies to be named" do + schema_str = <<~GRAPHQL + interface A implements B { + s: String + } + + interface B { + s: String + } + + type Query implements A & B { + s: String + } + GRAPHQL + + assert_schema_and_compare_output(schema_str) + + invalid_schema_str = schema_str.sub("A & B", "A") + assert_raises GraphQL::Schema::InvalidDocumentError do + GraphQL::Schema.from_definition(invalid_schema_str) + end + end + it "supports interfaces that implement interfaces" do schema = <<-SCHEMA interface Named implements Node { @@ -1542,13 +1565,13 @@ def self.parse(string) person: Person } - type Person implements NamedEntity { + type Person implements NamedEntity & Entity { id: ID! name: String nationality: String } - type Product implements NamedEntity { + type Product implements NamedEntity & Entity { id: ID! name: String amount: Int