graphql-client 0.8.0 → 0.8.1

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
  SHA1:
3
- metadata.gz: 9c735cc6d34d7372e777934b15cbf86540cf994a
4
- data.tar.gz: 329f6769cf02065e726dd26e9006cb1143f3f8df
3
+ metadata.gz: 3207be7a370ae7995dd3355381f4dfc6d839e100
4
+ data.tar.gz: 80b877dd6c13310c10217a6a65a375728a6a9cb6
5
5
  SHA512:
6
- metadata.gz: fd69bd130b837dff72de557d1b0c51e7a4f0b499af231af00d8b2df65a638116021f45660be83c8695aa27bbf808741db5317d4791e68f6bf0db9f059dbf9273
7
- data.tar.gz: 20d75c1fa9d08f56a096328cf499e163eea4b7d13bfc9767f8fa743004e87c9a611d32d6533cbc0f28d72770b41635eff526549baf81bd52cc319ed0437ccb4c
6
+ metadata.gz: 036b98757f630e799ca5f8b111aad802d77f2723bc0cc73dae113c24687189cbfd6ad440224a6ba952902dc401a57a6f7cfa33523c6b764aa83f37e526a3452f
7
+ data.tar.gz: db865264342c1e9dc7b42d07fbe4ae5d01319514ca884c92bee4aff7e3980436e5fad4a851768f1c97bd371d1ae3a0b7c6460e3c0b895a48bf81dd2d0e3153d8
@@ -110,32 +110,37 @@ module GraphQL
110
110
 
111
111
  definition_dependencies = Set.new
112
112
 
113
- str = str.gsub(/\.\.\.([a-zA-Z0-9_]+(::[a-zA-Z0-9_]+)+)/) do
113
+ str = str.gsub(/\.\.\.([a-zA-Z0-9_]+(::[a-zA-Z0-9_]+)*)/) do
114
114
  match = Regexp.last_match
115
115
  const_name = match[1]
116
- begin
117
- fragment = ActiveSupport::Inflector.constantize(const_name)
118
- rescue NameError
119
- fragment = nil
120
- end
121
116
 
122
- case fragment
123
- when FragmentDefinition
124
- definition_dependencies.merge(fragment.document.definitions)
125
- "...#{fragment.definition_name}"
117
+ if str.match(/fragment\s*#{const_name}/)
118
+ match[0]
126
119
  else
127
- if fragment
128
- message = "expected #{const_name} to be a #{FragmentDefinition}, but was a #{fragment.class}."
129
- if fragment.is_a?(Module) && fragment.constants.any?
130
- message += " Did you mean #{fragment}::#{fragment.constants.first}?"
131
- end
132
- else
133
- message = "uninitialized constant #{const_name}"
120
+ begin
121
+ fragment = ActiveSupport::Inflector.constantize(const_name)
122
+ rescue NameError
123
+ fragment = nil
134
124
  end
135
125
 
136
- error = ValidationError.new(message)
137
- error.set_backtrace(["#{filename}:#{lineno + match.pre_match.count("\n") + 1}"] + caller)
138
- raise error
126
+ case fragment
127
+ when FragmentDefinition
128
+ definition_dependencies.merge(fragment.document.definitions)
129
+ "...#{fragment.definition_name}"
130
+ else
131
+ if fragment
132
+ message = "expected #{const_name} to be a #{FragmentDefinition}, but was a #{fragment.class}."
133
+ if fragment.is_a?(Module) && fragment.constants.any?
134
+ message += " Did you mean #{fragment}::#{fragment.constants.first}?"
135
+ end
136
+ else
137
+ message = "uninitialized constant #{const_name}"
138
+ end
139
+
140
+ error = ValidationError.new(message)
141
+ error.set_backtrace(["#{filename}:#{lineno + match.pre_match.count("\n") + 1}"] + caller)
142
+ raise error
143
+ end
139
144
  end
140
145
  end
141
146
 
@@ -76,7 +76,7 @@ module GraphQL
76
76
 
77
77
  def type
78
78
  # TODO: Fix type indirection
79
- @type ||= GraphQL::Client::QueryResult.wrap(self, definition_node, name: "#{name}.type")
79
+ @type ||= GraphQL::Client::QueryResult.wrap(self, definition_node, document_types[definition_node], name: "#{name}.type")
80
80
  end
81
81
  end
82
82
  end
@@ -31,6 +31,9 @@ module GraphQL
31
31
  visitor[GraphQL::Language::Nodes::FragmentDefinition] << ->(node, _parent) do
32
32
  fields[node] = type_stack.object_types.last
33
33
  end
34
+ visitor[GraphQL::Language::Nodes::InlineFragment] << ->(node, _parent) do
35
+ fields[node] = type_stack.object_types.last
36
+ end
34
37
  visitor[GraphQL::Language::Nodes::Field] << ->(node, _parent) do
35
38
  fields[node] = type_stack.field_definitions.last.type
36
39
  end
@@ -22,41 +22,114 @@ module GraphQL
22
22
  # Internal: Get QueryResult class for result of query.
23
23
  #
24
24
  # Returns subclass of QueryResult or nil.
25
- def self.wrap(source_definition, node, name: nil)
26
- fields = {}
25
+ def self.wrap(source_definition, node, type, name: nil)
26
+ case type
27
+ when GraphQL::NonNullType
28
+ NonNullWrapper.new(wrap(source_definition, node, type.of_type, name: name))
29
+ when GraphQL::ListType
30
+ ListWrapper.new(wrap(source_definition, node, type.of_type, name: name))
31
+ when GraphQL::ScalarType
32
+ ScalarWrapper.new(type)
33
+ when GraphQL::ObjectType, GraphQL::InterfaceType, GraphQL::UnionType
34
+ fields = {}
35
+
36
+ node.selections.each do |selection|
37
+ case selection
38
+ when Language::Nodes::FragmentSpread
39
+ nil
40
+ when Language::Nodes::Field
41
+ field_name = selection.alias || selection.name
42
+ selection_type = source_definition.document_types[selection]
43
+ selection_type = GraphQL::STRING_TYPE if field_name == "__typename"
44
+ field_klass = wrap(source_definition, selection, selection_type, name: "#{name}[:#{field_name}]")
45
+ fields[field_name] ? fields[field_name] |= field_klass : fields[field_name] = field_klass
46
+ when Language::Nodes::InlineFragment
47
+ selection_type = source_definition.document_types[selection]
48
+ wrap(source_definition, selection, selection_type, name: name).fields.each do |fragment_name, klass|
49
+ fields[fragment_name.to_s] ? fields[fragment_name.to_s] |= klass : fields[fragment_name.to_s] = klass
50
+ end
51
+ end
52
+ end
27
53
 
28
- node.selections.each do |selection|
29
- case selection
30
- when Language::Nodes::FragmentSpread
54
+ define(name: name, type: type, source_definition: source_definition, source_node: node, fields: fields)
55
+ else
56
+ raise TypeError, "unexpected #{type.class}"
57
+ end
58
+ end
59
+
60
+ class ListWrapper
61
+ def initialize(type)
62
+ @of_klass = type
63
+ end
64
+
65
+ def cast(value, errors)
66
+ case value
67
+ when Array
68
+ List.new(value.each_with_index.map { |e, idx|
69
+ @of_klass.cast(e, errors.filter_by_path(idx))
70
+ }, errors)
71
+ else
72
+ raise ArgumentError, "expected list value to be an Array, but was #{value.class}"
73
+ end
74
+ end
75
+
76
+ def |(other)
77
+ if self.class == other.class
78
+ self.of_klass | other.of_klass
79
+ else
80
+ raise TypeError, "expected other to be a #{self.class}"
81
+ end
82
+ end
83
+ end
84
+
85
+ class NonNullWrapper
86
+ attr_reader :of_klass
87
+
88
+ def initialize(type)
89
+ @of_klass = type
90
+ end
91
+
92
+ def cast(value, errors)
93
+ case value
94
+ when NilClass
95
+ # TODO
96
+ # raise ArgumentError, "expected non-nullable value to be present"
31
97
  nil
32
- when Language::Nodes::Field
33
- field_name = selection.alias || selection.name
34
- field_klass = nil
35
- if selection.selections.any?
36
- field_klass = wrap(source_definition, selection, name: "#{name}[:#{field_name}]")
37
- end
38
- fields[field_name] ? fields[field_name] |= field_klass : fields[field_name] = field_klass
39
- when Language::Nodes::InlineFragment
40
- wrap(source_definition, selection, name: name).fields.each do |fragment_name, klass|
41
- fields[fragment_name.to_s] ? fields[fragment_name.to_s] |= klass : fields[fragment_name.to_s] = klass
42
- end
98
+ else
99
+ @of_klass.cast(value, errors)
43
100
  end
44
101
  end
45
102
 
46
- define(name: name, source_definition: source_definition, source_node: node, fields: fields)
103
+ def |(other)
104
+ if self.class == other.class
105
+ self.of_klass | other.of_klass
106
+ else
107
+ raise TypeError, "expected other to be a #{self.class}"
108
+ end
109
+ end
47
110
  end
48
111
 
49
112
  # :nodoc:
50
- class Scalar
113
+ class ScalarWrapper
51
114
  def initialize(type)
52
115
  @type = type
53
116
  end
54
117
 
55
118
  def cast(value, _errors = nil)
56
119
  if value.is_a? Array
57
- value.map { |item| @type.coerce_input(item) }
120
+ value.map { |item|
121
+ if @type.respond_to?(:coerce_isolated_input)
122
+ @type.coerce_isolated_input(item)
123
+ else
124
+ @type.coerce_input(item)
125
+ end
126
+ }
58
127
  else
59
- @type.coerce_input(value)
128
+ if @type.respond_to?(:coerce_isolated_input)
129
+ @type.coerce_isolated_input(value)
130
+ else
131
+ @type.coerce_input(value)
132
+ end
60
133
  end
61
134
  end
62
135
 
@@ -67,10 +140,7 @@ module GraphQL
67
140
  end
68
141
 
69
142
  # Internal
70
- def self.define(name:, source_definition:, source_node:, fields: {})
71
- type = source_definition.document_types[source_node]
72
- type = type.unwrap if type
73
-
143
+ def self.define(name:, type:, source_definition:, source_node:, fields: {})
74
144
  Class.new(self) do
75
145
  @name = name
76
146
  @type = type
@@ -81,13 +151,6 @@ module GraphQL
81
151
  field_readers = Set.new
82
152
 
83
153
  fields.each do |field, klass|
84
- if @type.is_a?(GraphQL::ObjectType)
85
- field_node = @type.get_field(field.to_s)
86
- if field_node && field_node.type.unwrap.is_a?(GraphQL::ScalarType)
87
- klass = Scalar.new(field_node.type.unwrap)
88
- end
89
- end
90
-
91
154
  @fields[field.to_sym] = klass
92
155
 
93
156
  send :attr_reader, field
@@ -107,18 +170,12 @@ module GraphQL
107
170
  end
108
171
 
109
172
  assigns = @fields.map do |field, klass|
110
- if klass
111
- <<-RUBY
112
- @#{field} = self.class.fields[:#{field}].cast(@data["#{field}"], @errors.filter_by_path("#{field}"))
113
- RUBY
114
- else
115
- <<-RUBY
116
- @#{field} = @data["#{field}"]
117
- RUBY
118
- end
173
+ <<-RUBY
174
+ @#{field} = self.class.fields[:#{field}].cast(@data["#{field}"], @errors.filter_by_path("#{field}"))
175
+ RUBY
119
176
  end
120
177
 
121
- if @type && @type.is_a?(GraphQL::ObjectType)
178
+ if @type.is_a?(GraphQL::ObjectType)
122
179
  assigns.unshift "@__typename = self.class.type.name"
123
180
  end
124
181
 
@@ -177,12 +234,10 @@ module GraphQL
177
234
  raise TypeError, "#{self.source_definition.name} is not included in #{obj.class.source_definition.name}"
178
235
  end
179
236
  cast(obj.to_h, obj.errors)
180
- when Array
181
- List.new(obj.each_with_index.map { |e, idx| cast(e, errors.filter_by_path(idx)) }, errors)
182
237
  when NilClass
183
238
  nil
184
239
  else
185
- raise TypeError, obj.class.to_s
240
+ raise TypeError, "expected #{obj.inspect} to be a Hash"
186
241
  end
187
242
  end
188
243
 
@@ -219,7 +274,7 @@ module GraphQL
219
274
  end
220
275
  end
221
276
  # TODO: Picking first source node seems error prone
222
- define(name: self.name, source_definition: source_definition, source_node: source_node, fields: new_fields)
277
+ define(name: self.name, type: self.type, source_definition: source_definition, source_node: source_node, fields: new_fields)
223
278
  end
224
279
 
225
280
  # Public: Return errors associated with data.
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.8.0
4
+ version: 0.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitHub
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-04-04 00:00:00.000000000 Z
11
+ date: 2017-04-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport