@@ -18,7 +18,7 @@ class Partial
18
18
# @param object [Object] A starting object for execution
19
19
# @param query [GraphQL::Query] A full query instance that this partial is based on. Caches are shared.
20
20
# @param context [Hash] Extra context values to merge into `query.context`, if provided
21
- def initialize ( path :, object :, query :, context : nil )
21
+ def initialize ( path :, object :, query :, context : nil , node : nil )
22
22
@path = path
23
23
@object = object
24
24
@query = query
@@ -31,65 +31,31 @@ def initialize(path:, object:, query:, context: nil)
31
31
@multiplex = nil
32
32
@result_values = nil
33
33
@result = nil
34
- selections = [ @query . selected_operation ]
35
- type = @query . root_type
36
- parent_type = nil
37
- field_defn = nil
38
- @path . each do |name_in_doc |
39
- if name_in_doc . is_a? ( Integer )
40
- if type . list?
41
- type = type . unwrap
42
- next
43
- else
44
- raise ArgumentError , "Received path with index `#{ name_in_doc } `, but type wasn't a list. Type: #{ type . to_type_signature } , path: #{ @path } "
45
- end
46
- end
47
-
48
- next_selections = [ ]
49
- selections . each do |selection |
50
- selections_to_check = [ ]
51
- selections_to_check . concat ( selection . selections )
52
- while ( sel = selections_to_check . shift )
53
- case sel
54
- when GraphQL ::Language ::Nodes ::InlineFragment
55
- selections_to_check . concat ( sel . selections )
56
- when GraphQL ::Language ::Nodes ::FragmentSpread
57
- fragment = @query . fragments [ sel . name ]
58
- selections_to_check . concat ( fragment . selections )
59
- when GraphQL ::Language ::Nodes ::Field
60
- if sel . alias == name_in_doc || sel . name == name_in_doc
61
- next_selections << sel
62
- end
63
- else
64
- raise "Unexpected selection in partial path: #{ sel . class } , #{ sel . inspect } "
65
- end
66
- end
67
- end
68
34
69
- if next_selections . empty?
70
- raise ArgumentError , "Path `#{ @path . inspect } ` is not present in this query. `#{ name_in_doc . inspect } ` was not found. Try a different path or rewrite the query to include it."
71
- end
72
- field_name = next_selections . first . name
73
- field_defn = @schema . get_field ( type , field_name , @query . context ) || raise ( "Invariant: no field called #{ field_name } on #{ type . graphql_name } " )
74
- parent_type = type
75
- type = field_defn . type
76
- if type . non_null?
77
- type = type . of_type
35
+ if node && type
36
+ @ast_nodes = case node
37
+ when GraphQL ::Language ::Nodes ::Field
38
+ [ node ]
39
+ when GraphQL ::Language ::Nodes ::InlineFragment , GraphQL ::Language ::Nodes ::FragmentDefinition
40
+ node . selections
41
+ else
42
+ raise ArgumentError , "AST node not supported by Query::Partial"
78
43
end
79
- selections = next_selections
44
+ @root_type = type
45
+ # This is only used when `@leaf` -- probably could be based on `node`
46
+ @field_definition = nil
47
+ else
48
+ set_type_info_from_path
80
49
end
81
- @parent_type = parent_type
82
- @ast_nodes = selections
83
- @root_type = type
84
- @field_definition = field_defn
50
+
85
51
@leaf = @root_type . unwrap . kind . leaf?
86
52
end
87
53
88
54
def leaf?
89
55
@leaf
90
56
end
91
57
92
- attr_reader :context , :query , :ast_nodes , :root_type , :object , :field_definition , :path , :parent_type , : schema
58
+ attr_reader :context , :query , :ast_nodes , :root_type , :object , :field_definition , :path , :schema
93
59
94
60
attr_accessor :multiplex , :result_values
95
61
@@ -155,6 +121,63 @@ def static_errors
155
121
def selected_operation_name
156
122
@query . selected_operation_name
157
123
end
124
+
125
+ private
126
+
127
+ def set_type_info_from_path
128
+ selections = [ @query . selected_operation ]
129
+ type = @query . root_type
130
+ parent_type = nil
131
+ field_defn = nil
132
+
133
+ @path . each do |name_in_doc |
134
+ if name_in_doc . is_a? ( Integer )
135
+ if type . list?
136
+ type = type . unwrap
137
+ next
138
+ else
139
+ raise ArgumentError , "Received path with index `#{ name_in_doc } `, but type wasn't a list. Type: #{ type . to_type_signature } , path: #{ @path } "
140
+ end
141
+ end
142
+
143
+ next_selections = [ ]
144
+ selections . each do |selection |
145
+ selections_to_check = [ ]
146
+ selections_to_check . concat ( selection . selections )
147
+ while ( sel = selections_to_check . shift )
148
+ case sel
149
+ when GraphQL ::Language ::Nodes ::InlineFragment
150
+ selections_to_check . concat ( sel . selections )
151
+ when GraphQL ::Language ::Nodes ::FragmentSpread
152
+ fragment = @query . fragments [ sel . name ]
153
+ selections_to_check . concat ( fragment . selections )
154
+ when GraphQL ::Language ::Nodes ::Field
155
+ if sel . alias == name_in_doc || sel . name == name_in_doc
156
+ next_selections << sel
157
+ end
158
+ else
159
+ raise "Unexpected selection in partial path: #{ sel . class } , #{ sel . inspect } "
160
+ end
161
+ end
162
+ end
163
+
164
+ if next_selections . empty?
165
+ raise ArgumentError , "Path `#{ @path . inspect } ` is not present in this query. `#{ name_in_doc . inspect } ` was not found. Try a different path or rewrite the query to include it."
166
+ end
167
+ field_name = next_selections . first . name
168
+ field_defn = @schema . get_field ( type , field_name , @query . context ) || raise ( "Invariant: no field called #{ field_name } on #{ type . graphql_name } " )
169
+ parent_type = type
170
+ type = field_defn . type
171
+ if type . non_null?
172
+ type = type . of_type
173
+ end
174
+ selections = next_selections
175
+ end
176
+
177
+ @ast_nodes = selections
178
+ @root_type = type
179
+ @field_definition = field_defn
180
+ end
158
181
end
159
182
end
160
183
end
0 commit comments