1 2 3 4 5 6 7 8 9 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 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
|
# frozen_string_literal: true
module GraphQL
module StaticValidation
# Scalars _can't_ have selections
# Objects _must_ have selections
module FieldsHaveAppropriateSelections
include GraphQL::StaticValidation::Error::ErrorHelper
def on_field(node, parent)
field_defn = field_definition
if validate_field_selections(node, field_defn.type.unwrap)
super
end
end
def on_operation_definition(node, _parent)
if validate_field_selections(node, type_definition)
super
end
end
private
def validate_field_selections(ast_node, resolved_type)
msg = if resolved_type.nil?
nil
elsif resolved_type.kind.scalar? && ast_node.selections.any?
selection_strs = ast_node.selections.map do |n|
case n
when GraphQL::Language::Nodes::InlineFragment
"\"... on #{n.type.name} { ... }\""
when GraphQL::Language::Nodes::Field
"\"#{n.name}\""
when GraphQL::Language::Nodes::FragmentSpread
"\"#{n.name}\""
else
raise "Invariant: unexpected selection node: #{n}"
end
end
"Selections can't be made on scalars (%{node_name} returns #{resolved_type.graphql_name} but has selections [#{selection_strs.join(", ")}])"
elsif resolved_type.kind.fields? && ast_node.selections.empty?
"Field must have selections (%{node_name} returns #{resolved_type.graphql_name} but has no selections. Did you mean '#{ast_node.name} { ... }'?)"
else
nil
end
if msg
node_name = case ast_node
when GraphQL::Language::Nodes::Field
"field '#{ast_node.name}'"
when GraphQL::Language::Nodes::OperationDefinition
if ast_node.name.nil?
"anonymous query"
else
"#{ast_node.operation_type} '#{ast_node.name}'"
end
else
raise("Unexpected node #{ast_node}")
end
extensions = {
"rule": "StaticValidation::FieldsHaveAppropriateSelections",
"name": node_name.to_s
}
unless resolved_type.nil?
extensions["type"] = resolved_type.to_type_signature
end
add_error(GraphQL::StaticValidation::FieldsHaveAppropriateSelectionsError.new(
msg % { node_name: node_name },
nodes: ast_node,
node_name: node_name.to_s,
type: resolved_type.nil? ? nil : resolved_type.graphql_name,
))
false
else
true
end
end
end
end
end
|