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
|
# File 'lib/better_graphql/detect_invalid_id_field.rb', line 13
def trace(key, data)
@cache = {} if key == 'parse'
return yield if key != 'execute_field'
yield.tap do |resolved_value|
next unless comparable?(resolved_value)
if data[:context]
parent_type = data[:context].parent_type
field = data[:context].field
path = data[:context].path
else
parent_type = data[:owner]
field = data[:field]
path = data[:path]
end
cache_by_type = cache[parent_type] ||= {}
nodes_by_path = cache_by_type[:nodes_by_path] ||= {}
nodes_by_id = cache_by_type[:nodes_by_id] ||= {}
field_name = field.name.to_sym
parent_path = path[0..-2]
resolving_object = nodes_by_path[parent_path] ||= {
__metadata__: { parent_path: parent_path },
}
resolving_object[field_name] = resolved_value
if field_name == :id
nodes_by_id[resolved_value] ||= []
nodes_by_id[resolved_value] << resolving_object
next
end
if resolving_object.key?(:id)
all_nodes_with_same_id = nodes_by_id[resolving_object[:id]]
other_nodes_with_same_id = all_nodes_with_same_id - [resolving_object]
other_nodes_with_same_id.each do |another_node|
next unless another_node[field_name] != resolved_value
raise StandardError,
"The field #{parent_type.graphql_name}#id must be unique across the graph." \
' You have two nodes representing the same object in the graph, but they are returning different values for the same field.' \
" #{parent_type.graphql_name}#id = #{resolving_object[:id]}." \
" Divergence: #{(another_node[:__metadata__][:parent_path] + [field_name]).join('.')} = #{another_node[field_name].to_json} and #{path.join('.')} = #{resolved_value.to_json}"
end
end
end
end
|