-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy patherror_formatting.rb
More file actions
118 lines (95 loc) · 3.8 KB
/
error_formatting.rb
File metadata and controls
118 lines (95 loc) · 3.8 KB
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# typed: false
# frozen_string_literal: true
module GraphQL::Cardinal
class Executor
module ErrorFormatting
private
def format_inline_errors(data, _errors)
# todo: make this smarter to only traverse down actual error paths
@path = []
propagate_object_scope_errors(
data,
@query.root_type_for_operation(@query.selected_operation.operation_type),
@query.selected_operation.selections,
)
end
def propagate_object_scope_errors(raw_object, parent_type, selections)
return nil if raw_object.nil?
selections.each do |node|
case node
when GraphQL::Language::Nodes::Field
field_name = node.alias || node.name
@path << field_name
begin
node_type = @query.get_field(parent_type, node.name).type
named_type = node_type.unwrap
raw_value = raw_object[field_name]
raw_object[field_name] = if raw_value.is_a?(ExecutionError)
raw_value.replace_path(@path.dup) unless raw_value.base_error?
nil
elsif node_type.list?
node_type = node_type.of_type while node_type.non_null?
propagate_list_scope_errors(raw_value, node_type, node.selections)
elsif named_type.kind.leaf?
raw_value
else
propagate_object_scope_errors(raw_value, named_type, node.selections)
end
return nil if node_type.non_null? && raw_object[field_name].nil?
ensure
@path.pop
end
when GraphQL::Language::Nodes::InlineFragment
fragment_type = node.type ? @query.get_type(node.type.name) : parent_type
next unless typename_in_type?(raw_object.typename, fragment_type)
result = propagate_object_scope_errors(raw_object, fragment_type, node.selections)
return nil if result.nil?
when GraphQL::Language::Nodes::FragmentSpread
fragment = @request.fragment_definitions[node.name]
fragment_type = @query.get_type(fragment.type.name)
next unless typename_in_type?(raw_object.typename, fragment_type)
result = propagate_object_scope_errors(raw_object, fragment_type, fragment.selections)
return nil if result.nil?
else
raise DocumentError.new("Invalid selection node type")
end
end
raw_object
end
def propagate_list_scope_errors(raw_list, current_node_type, selections)
return nil if raw_list.nil?
current_node_type = current_node_type.of_type while current_node_type.non_null?
next_node_type = current_node_type.of_type
named_type = next_node_type.unwrap
contains_null = false
resolved_list = raw_list.map!.with_index do |raw_list_element, index|
@path << index
begin
result = if next_node_type.list?
propagate_list_scope_errors(raw_list_element, next_node_type, selections)
elsif named_type.kind.leaf?
raw_list_element
else
propagate_object_scope_errors(raw_list_element, named_type, selections)
end
if result.nil?
contains_null = true
return nil if current_node_type.non_null?
end
result
ensure
@path.pop
end
end
return nil if contains_null && next_node_type.non_null?
resolved_list
end
def typename_in_type?(typename, type)
return true if type.graphql_name == typename
type.kind.abstract? && @query.possible_types(type).any? do |t|
t.graphql_name == typename
end
end
end
end
end