graphql-client 0.13.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 342aa95830be1c53716c72962fad3c3785058f160404fba1aa603f9b94a96f92
|
4
|
+
data.tar.gz: c63ff270ab64ad1ee8a8ece5a36d20be9b12e138e86cc0a4eb88246bf2d4c2bb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a701d2ad7b0776f43d04b63fa394d5470fe7f5a8d0d71467affd78d04069ec212249fc1e0ab9c86d82bdabadc750ac6eb63b7e6c77d3b842f82f5c6c88d81baf
|
7
|
+
data.tar.gz: 3033fcb57a59f3518436f0f903154f9eaaa070230afd6ba4f83d3c6c42904f71a503f92f42aa5b91932770c15bb8551a5ea7ce7130a9bf8ac7eca11756ef53ce
|
data/lib/graphql/client.rb
CHANGED
@@ -120,13 +120,21 @@ module GraphQL
|
|
120
120
|
|
121
121
|
definition_dependencies = Set.new
|
122
122
|
|
123
|
+
# Replace Ruby constant reference with GraphQL fragment names,
|
124
|
+
# while populating `definition_dependencies` with
|
125
|
+
# GraphQL Fragment ASTs which this operation depends on
|
123
126
|
str = str.gsub(/\.\.\.([a-zA-Z0-9_]+(::[a-zA-Z0-9_]+)*)/) do
|
124
127
|
match = Regexp.last_match
|
125
128
|
const_name = match[1]
|
126
129
|
|
127
130
|
if str.match(/fragment\s*#{const_name}/)
|
131
|
+
# It's a fragment _definition_, not a fragment usage
|
128
132
|
match[0]
|
129
133
|
else
|
134
|
+
# It's a fragment spread, so we should load the fragment
|
135
|
+
# which corresponds to the spread.
|
136
|
+
# We depend on ActiveSupport to either find the already-loaded
|
137
|
+
# constant, or to load the constant by name
|
130
138
|
begin
|
131
139
|
fragment = ActiveSupport::Inflector.constantize(const_name)
|
132
140
|
rescue NameError
|
@@ -135,6 +143,10 @@ module GraphQL
|
|
135
143
|
|
136
144
|
case fragment
|
137
145
|
when FragmentDefinition
|
146
|
+
# We found the fragment definition that this fragment spread belongs to.
|
147
|
+
# So, register the AST of this fragment in `definition_dependencies`
|
148
|
+
# and update the query string to valid GraphQL syntax,
|
149
|
+
# replacing the Ruby constant
|
138
150
|
definition_dependencies.merge(fragment.document.definitions)
|
139
151
|
"...#{fragment.definition_name}"
|
140
152
|
else
|
@@ -157,10 +169,17 @@ module GraphQL
|
|
157
169
|
doc = GraphQL.parse(str)
|
158
170
|
|
159
171
|
document_types = DocumentTypes.analyze_types(self.schema, doc).freeze
|
160
|
-
QueryTypename.insert_typename_fields(doc, types: document_types)
|
172
|
+
doc = QueryTypename.insert_typename_fields(doc, types: document_types)
|
161
173
|
|
162
174
|
doc.definitions.each do |node|
|
163
|
-
node.name
|
175
|
+
if node.name.nil?
|
176
|
+
if node.respond_to?(:merge) # GraphQL 1.9 +
|
177
|
+
node_with_name = node.merge(name: "__anonymous__")
|
178
|
+
doc = doc.replace_child(node, node_with_name)
|
179
|
+
else
|
180
|
+
node.name = "__anonymous__"
|
181
|
+
end
|
182
|
+
end
|
164
183
|
end
|
165
184
|
|
166
185
|
document_dependencies = Language::Nodes::Document.new(definitions: doc.definitions + definition_dependencies.to_a)
|
@@ -192,7 +211,6 @@ module GraphQL
|
|
192
211
|
raise TypeError, "unexpected #{node.class}"
|
193
212
|
end
|
194
213
|
|
195
|
-
node.name = nil if node.name == "__anonymous__"
|
196
214
|
sliced_document = Language::DefinitionSlice.slice(document_dependencies, node.name)
|
197
215
|
definition = Definition.for(
|
198
216
|
client: self,
|
@@ -205,18 +223,26 @@ module GraphQL
|
|
205
223
|
end
|
206
224
|
|
207
225
|
name_hook = RenameNodeHook.new(definitions)
|
208
|
-
visitor = Language::Visitor.new(
|
226
|
+
visitor = Language::Visitor.new(document_dependencies)
|
209
227
|
visitor[Language::Nodes::FragmentDefinition].leave << name_hook.method(:rename_node)
|
210
228
|
visitor[Language::Nodes::OperationDefinition].leave << name_hook.method(:rename_node)
|
211
229
|
visitor[Language::Nodes::FragmentSpread].leave << name_hook.method(:rename_node)
|
212
230
|
visitor.visit
|
213
231
|
|
214
|
-
doc.
|
232
|
+
if !doc.respond_to?(:merge)
|
233
|
+
doc.deep_freeze # 1.9 introduced immutable AST nodes, so we skip this on 1.9+
|
234
|
+
end
|
215
235
|
|
216
|
-
|
236
|
+
if document_tracking_enabled
|
237
|
+
if @document.respond_to?(:merge) # GraphQL 1.9+
|
238
|
+
@document = @document.merge(definitions: @document.definitions + doc.definitions)
|
239
|
+
else
|
240
|
+
@document.definitions.concat(doc.definitions)
|
241
|
+
end
|
242
|
+
end
|
217
243
|
|
218
|
-
if definitions[
|
219
|
-
definitions[
|
244
|
+
if definitions["__anonymous__"]
|
245
|
+
definitions["__anonymous__"]
|
220
246
|
else
|
221
247
|
Module.new do
|
222
248
|
definitions.each do |name, definition|
|
@@ -235,7 +261,7 @@ module GraphQL
|
|
235
261
|
definition = @definitions[node.name]
|
236
262
|
if definition
|
237
263
|
node.extend(LazyName)
|
238
|
-
node.
|
264
|
+
node.name_proc = -> { definition.definition_name }
|
239
265
|
end
|
240
266
|
end
|
241
267
|
end
|
@@ -358,8 +384,10 @@ module GraphQL
|
|
358
384
|
# name to point to a lazily defined Proc instead of a static string.
|
359
385
|
module LazyName
|
360
386
|
def name
|
361
|
-
@
|
387
|
+
@name_proc.call
|
362
388
|
end
|
389
|
+
|
390
|
+
attr_writer :name_proc
|
363
391
|
end
|
364
392
|
|
365
393
|
private
|
@@ -13,33 +13,84 @@ module GraphQL
|
|
13
13
|
# document - GraphQL::Language::Nodes::Document to modify
|
14
14
|
# schema - Optional Map of GraphQL::Language::Nodes::Node to GraphQL::Type
|
15
15
|
#
|
16
|
-
# Returns
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
16
|
+
# Returns the document with `__typename` added to it
|
17
|
+
if GraphQL::Language::Nodes::AbstractNode.method_defined?(:merge)
|
18
|
+
# GraphQL 1.9 introduces a new visitor class
|
19
|
+
# and doesn't expose writer methods for node attributes.
|
20
|
+
# So, use the node mutation API instead.
|
21
|
+
class InsertTypenameVisitor < GraphQL::Language::Visitor
|
22
|
+
def initialize(document, types:)
|
23
|
+
@types = types
|
24
|
+
super(document)
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_typename(node, parent)
|
28
|
+
type = @types[node]
|
29
|
+
type = type && type.unwrap
|
30
|
+
|
31
|
+
if (node.selections.any? && (type.nil? || type.is_a?(GraphQL::InterfaceType) || type.is_a?(GraphQL::UnionType))) ||
|
32
|
+
(node.selections.none? && type.is_a?(GraphQL::ObjectType))
|
33
|
+
names = QueryTypename.node_flatten_selections(node.selections).map { |s| s.respond_to?(:name) ? s.name : nil }
|
25
34
|
names = Set.new(names.compact)
|
26
35
|
|
27
|
-
|
28
|
-
node
|
36
|
+
if names.include?("__typename")
|
37
|
+
yield(node, parent)
|
38
|
+
else
|
39
|
+
node_with_typename = node.merge(selections: [GraphQL::Language::Nodes::Field.new(name: "__typename")] + node.selections)
|
40
|
+
yield(node_with_typename, parent)
|
29
41
|
end
|
42
|
+
else
|
43
|
+
yield(node, parent)
|
30
44
|
end
|
31
|
-
|
32
|
-
|
45
|
+
end
|
46
|
+
|
47
|
+
def on_operation_definition(node, parent)
|
48
|
+
add_typename(node, parent) { |n, p| super(n, p) }
|
49
|
+
end
|
50
|
+
|
51
|
+
def on_field(node, parent)
|
52
|
+
add_typename(node, parent) { |n, p| super(n, p) }
|
53
|
+
end
|
54
|
+
|
55
|
+
def on_fragment_definition(node, parent)
|
56
|
+
add_typename(node, parent) { |n, p| super(n, p) }
|
33
57
|
end
|
34
58
|
end
|
35
59
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
60
|
+
def self.insert_typename_fields(document, types: {})
|
61
|
+
visitor = InsertTypenameVisitor.new(document, types: types)
|
62
|
+
visitor.visit
|
63
|
+
visitor.result
|
64
|
+
end
|
65
|
+
|
66
|
+
else
|
67
|
+
def self.insert_typename_fields(document, types: {})
|
68
|
+
on_selections = ->(node, _parent) do
|
69
|
+
type = types[node]
|
70
|
+
|
71
|
+
if node.selections.any?
|
72
|
+
case type && type.unwrap
|
73
|
+
when NilClass, GraphQL::InterfaceType, GraphQL::UnionType
|
74
|
+
names = node_flatten_selections(node.selections).map { |s| s.respond_to?(:name) ? s.name : nil }
|
75
|
+
names = Set.new(names.compact)
|
41
76
|
|
42
|
-
|
77
|
+
unless names.include?("__typename")
|
78
|
+
node.selections = [GraphQL::Language::Nodes::Field.new(name: "__typename")] + node.selections
|
79
|
+
end
|
80
|
+
end
|
81
|
+
elsif type && type.unwrap.is_a?(GraphQL::ObjectType)
|
82
|
+
node.selections = [GraphQL::Language::Nodes::Field.new(name: "__typename")]
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
visitor = GraphQL::Language::Visitor.new(document)
|
87
|
+
visitor[GraphQL::Language::Nodes::Field].leave << on_selections
|
88
|
+
visitor[GraphQL::Language::Nodes::FragmentDefinition].leave << on_selections
|
89
|
+
visitor[GraphQL::Language::Nodes::OperationDefinition].leave << on_selections
|
90
|
+
visitor.visit
|
91
|
+
|
92
|
+
document
|
93
|
+
end
|
43
94
|
end
|
44
95
|
|
45
96
|
def self.node_flatten_selections(selections)
|
@@ -41,7 +41,7 @@ module GraphQL
|
|
41
41
|
if type = possible_types[typename]
|
42
42
|
type.cast(value, errors)
|
43
43
|
else
|
44
|
-
raise InvariantError, "expected value to be one of (#{possible_types.keys.join(", ")}), but was #{typename}"
|
44
|
+
raise InvariantError, "expected value to be one of (#{possible_types.keys.join(", ")}), but was #{typename.inspect}"
|
45
45
|
end
|
46
46
|
when NilClass
|
47
47
|
nil
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graphql-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.14.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- GitHub
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-10-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|