graphql-client 0.9.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "graphql/client/error"
4
+ require "graphql/client/schema/base_type"
5
+
6
+ module GraphQL
7
+ class Client
8
+ module Schema
9
+ class EnumType < Module
10
+ include BaseType
11
+
12
+ # Internal: Construct enum wrapper from another GraphQL::EnumType.
13
+ #
14
+ # type - GraphQL::EnumType instance
15
+ def initialize(type)
16
+ unless type.is_a?(GraphQL::EnumType)
17
+ raise "expected type to be a GraphQL::EnumType, but was #{type.class}"
18
+ end
19
+
20
+ @type = type
21
+
22
+ all_values = type.values.keys
23
+
24
+ all_values.each do |value|
25
+ str = value.dup
26
+ all_values.each do |v|
27
+ str.define_singleton_method("#{v.downcase}?") { false }
28
+ end
29
+ str.define_singleton_method("#{value.downcase}?") { true }
30
+ str.freeze
31
+ const_set(value, str)
32
+ end
33
+ end
34
+
35
+ def define_class(definition, irep_node)
36
+ self
37
+ end
38
+
39
+ # Internal: Cast JSON value to wrapped value.
40
+ #
41
+ # values - JSON value
42
+ # errors - Errors instance
43
+ #
44
+ # Returns String or nil.
45
+ def cast(value, _errors = nil)
46
+ case value
47
+ when String, NilClass
48
+ value
49
+ else
50
+ raise InvariantError, "expected value to be a String, but was #{value.class}"
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "graphql/client/schema/base_type"
4
+
5
+ module GraphQL
6
+ class Client
7
+ module Schema
8
+ class IncludeDirective
9
+ include BaseType
10
+
11
+ # Internal: Construct list wrapper from other BaseType.
12
+ #
13
+ # of_klass - BaseType instance
14
+ def initialize(of_klass)
15
+ unless of_klass.is_a?(BaseType)
16
+ raise TypeError, "expected #{of_klass.inspect} to be a #{BaseType}"
17
+ end
18
+
19
+ @of_klass = of_klass
20
+ end
21
+
22
+ # Internal: Get wrapped klass.
23
+ #
24
+ # Returns BaseType instance.
25
+ attr_reader :of_klass
26
+
27
+ # Internal: Cast JSON value to wrapped value.
28
+ #
29
+ # values - JSON value
30
+ # errors - Errors instance
31
+ #
32
+ # Returns List instance or nil.
33
+ def cast(value, errors)
34
+ case value
35
+ when NilClass
36
+ nil
37
+ else
38
+ of_klass.cast(value, errors)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "graphql/client/schema/possible_types"
4
+
5
+ module GraphQL
6
+ class Client
7
+ module Schema
8
+ class InterfaceType < Module
9
+ include BaseType
10
+
11
+ def initialize(type)
12
+ unless type.is_a?(GraphQL::InterfaceType)
13
+ raise "expected type to be a GraphQL::InterfaceType, but was #{type.class}"
14
+ end
15
+
16
+ @type = type
17
+ end
18
+
19
+ def new(types)
20
+ PossibleTypes.new(type, types)
21
+ end
22
+
23
+ def define_class(definition, irep_node)
24
+ new(irep_node.typed_children.keys.map { |ctype|
25
+ schema_module.const_get(ctype.name).define_class(definition, irep_node)
26
+ })
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "graphql/client/error"
4
+ require "graphql/client/list"
5
+ require "graphql/client/schema/base_type"
6
+
7
+ module GraphQL
8
+ class Client
9
+ module Schema
10
+ class ListType
11
+ include BaseType
12
+
13
+ # Internal: Construct list wrapper from other BaseType.
14
+ #
15
+ # of_klass - BaseType instance
16
+ def initialize(of_klass)
17
+ unless of_klass.is_a?(BaseType)
18
+ raise TypeError, "expected #{of_klass.inspect} to be a #{BaseType}"
19
+ end
20
+
21
+ @of_klass = of_klass
22
+ end
23
+
24
+ # Internal: Get wrapped klass.
25
+ #
26
+ # Returns BaseType instance.
27
+ attr_reader :of_klass
28
+
29
+ # Internal: Cast JSON value to wrapped value.
30
+ #
31
+ # values - JSON value
32
+ # errors - Errors instance
33
+ #
34
+ # Returns List instance or nil.
35
+ def cast(values, errors)
36
+ case values
37
+ when Array
38
+ List.new(values.each_with_index.map { |e, idx|
39
+ of_klass.cast(e, errors.filter_by_path(idx))
40
+ }, errors)
41
+ when NilClass
42
+ nil
43
+ else
44
+ raise InvariantError, "expected value to be a list, but was #{values.class}"
45
+ end
46
+ end
47
+
48
+ # Internal: Get list wrapper of this type class.
49
+ #
50
+ # Returns ListType instance.
51
+ def to_list_type
52
+ self
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "graphql/client/error"
4
+ require "graphql/client/schema/base_type"
5
+
6
+ module GraphQL
7
+ class Client
8
+ module Schema
9
+ class NonNullType
10
+ include BaseType
11
+
12
+ # Internal: Construct non-nullable wrapper from other BaseType.
13
+ #
14
+ # of_klass - BaseType instance
15
+ def initialize(of_klass)
16
+ unless of_klass.is_a?(BaseType)
17
+ raise TypeError, "expected #{of_klass.inspect} to be a #{BaseType}"
18
+ end
19
+
20
+ @of_klass = of_klass
21
+ end
22
+
23
+ # Internal: Get wrapped klass.
24
+ #
25
+ # Returns BaseType instance.
26
+ attr_reader :of_klass
27
+
28
+ # Internal: Cast JSON value to wrapped value.
29
+ #
30
+ # value - JSON value
31
+ # errors - Errors instance
32
+ #
33
+ # Returns BaseType instance.
34
+ def cast(value, errors)
35
+ case value
36
+ when NilClass
37
+ raise InvariantError, "expected value to be non-nullable, but was nil"
38
+ else
39
+ of_klass.cast(value, errors)
40
+ end
41
+ end
42
+
43
+ # Internal: Get non-nullable wrapper of this type class.
44
+ #
45
+ # Returns NonNullType instance.
46
+ def to_non_null_type
47
+ self
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,162 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/inflector"
4
+ require "graphql/client/deprecation"
5
+ require "graphql/client/error"
6
+ require "graphql/client/errors"
7
+ require "graphql/client/schema/base_type"
8
+ require "graphql/client/schema/possible_types"
9
+
10
+ module GraphQL
11
+ class Client
12
+ module Schema
13
+ module ObjectType
14
+ def self.new(type, fields = {})
15
+ Class.new(ObjectClass) do
16
+ extend BaseType
17
+ extend ObjectType
18
+
19
+ define_singleton_method(:type) { type }
20
+ define_singleton_method(:fields) { fields }
21
+ end
22
+ end
23
+
24
+ def define_class(definition, irep_node)
25
+ fields = irep_node.typed_children[type].inject({}) { |h, (field_name, field_irep_node)|
26
+ if definition.indexes[:definitions][field_irep_node.ast_node] == definition.definition_node
27
+ h[field_name.to_sym] = schema_module.define_class(definition, field_irep_node, field_irep_node.definition.type)
28
+ end
29
+ h
30
+ }
31
+
32
+ Class.new(self) do
33
+ define_fields(fields)
34
+
35
+ if definition.client.enforce_collocated_callers
36
+ Client.enforce_collocated_callers(self, fields.keys, definition.source_location[0])
37
+ end
38
+
39
+ class << self
40
+ attr_reader :source_definition
41
+ attr_reader :_spreads
42
+ end
43
+
44
+ @source_definition = definition
45
+ @_spreads = definition.indexes[:spreads][irep_node.ast_node]
46
+ end
47
+ end
48
+
49
+ def define_fields(fields)
50
+ fields.each { |name, type| define_field(name, type) }
51
+ end
52
+
53
+ def define_field(name, type)
54
+ name = name.to_s
55
+ method_name = ActiveSupport::Inflector.underscore(name)
56
+
57
+ define_method(method_name) do
58
+ @casted_data.fetch(name) do
59
+ @casted_data[name] = type.cast(@data[name], @errors.filter_by_path(name))
60
+ end
61
+ end
62
+
63
+ define_method("#{method_name}?") do
64
+ @data[name] ? true : false
65
+ end
66
+
67
+ if name != method_name
68
+ define_method(name) do
69
+ @casted_data.fetch(name) do
70
+ @casted_data[name] = type.cast(@data[name], @errors.filter_by_path(name))
71
+ end
72
+ end
73
+ Deprecation.deprecate_methods(self, name => "Use ##{method_name} instead")
74
+ end
75
+ end
76
+
77
+ def cast(value, errors)
78
+ case value
79
+ when Hash
80
+ new(value, errors)
81
+ when NilClass
82
+ nil
83
+ else
84
+ raise InvariantError, "expected value to be a Hash, but was #{value.class}"
85
+ end
86
+ end
87
+ end
88
+
89
+ class ObjectClass
90
+ def initialize(data = {}, errors = Errors.new)
91
+ @data = data
92
+ @casted_data = {}
93
+ @errors = errors
94
+ end
95
+
96
+ # Public: Returns the raw response data
97
+ #
98
+ # Returns Hash
99
+ def to_h
100
+ @data
101
+ end
102
+
103
+ # Public: Return errors associated with data.
104
+ #
105
+ # Returns Errors collection.
106
+ attr_reader :errors
107
+
108
+ def method_missing(*args)
109
+ super
110
+ rescue NoMethodError => e
111
+ type = self.class.type
112
+
113
+ field = type.all_fields.find do |f|
114
+ f.name == e.name.to_s || ActiveSupport::Inflector.underscore(f.name) == e.name.to_s
115
+ end
116
+
117
+ unless field
118
+ raise UnimplementedFieldError, "undefined field `#{e.name}' on #{type} type. https://git.io/v1y3m"
119
+ end
120
+
121
+ if @data.key?(field.name)
122
+ error_class = ImplicitlyFetchedFieldError
123
+ message = "implicitly fetched field `#{field.name}' on #{type} type. https://git.io/v1yGL"
124
+ else
125
+ error_class = UnfetchedFieldError
126
+ message = "unfetched field `#{field.name}' on #{type} type. https://git.io/v1y3U"
127
+ end
128
+
129
+ raise error_class, message
130
+ end
131
+
132
+ def inspect
133
+ parent = self.class.ancestors.select { |m| m.is_a?(ObjectType) }.last
134
+
135
+ ivars = @data.map { |key, value|
136
+ if value.is_a?(Hash) || value.is_a?(Array)
137
+ "#{key}=..."
138
+ else
139
+ "#{key}=#{value.inspect}"
140
+ end
141
+ }
142
+
143
+ buf = "#<#{parent.name}".dup
144
+ buf << " " << ivars.join(" ") if ivars.any?
145
+ buf << ">"
146
+ buf
147
+ end
148
+
149
+ def typename
150
+ Deprecation.deprecation_warning("typename", "Use #class.type.name instead")
151
+ self.class.type.name
152
+ end
153
+
154
+ def type_of?(*types)
155
+ Deprecation.deprecation_warning("type_of?", "Use #is_a? instead")
156
+ names = ([self.class.type] + self.class.ancestors.select { |m| m.is_a?(InterfaceType) || m.is_a?(UnionType) }.map(&:type)).map(&:name)
157
+ types.any? { |type| names.include?(type.to_s) }
158
+ end
159
+ end
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "graphql/client/error"
4
+ require "graphql/client/schema/base_type"
5
+ require "graphql/client/schema/object_type"
6
+
7
+ module GraphQL
8
+ class Client
9
+ module Schema
10
+ class PossibleTypes
11
+ include BaseType
12
+
13
+ def initialize(type, types)
14
+ @type = type
15
+
16
+ unless types.is_a?(Enumerable)
17
+ raise TypeError, "expected types to be Enumerable, but was #{types.class}"
18
+ end
19
+
20
+ @possible_types = {}
21
+ types.each do |klass|
22
+ unless klass.is_a?(ObjectType)
23
+ raise TypeError, "expected type to be #{ObjectType}, but was #{type.class}"
24
+ end
25
+ @possible_types[klass.type.name] = klass
26
+ end
27
+ end
28
+
29
+ attr_reader :possible_types
30
+
31
+ # Internal: Cast JSON value to wrapped value.
32
+ #
33
+ # value - JSON value
34
+ # errors - Errors instance
35
+ #
36
+ # Returns BaseType instance.
37
+ def cast(value, errors)
38
+ case value
39
+ when Hash
40
+ typename = value["__typename"]
41
+ if type = possible_types[typename]
42
+ type.cast(value, errors)
43
+ else
44
+ raise InvariantError, "expected value to be one of (#{possible_types.keys.join(", ")}), but was #{typename}"
45
+ end
46
+ when NilClass
47
+ nil
48
+ else
49
+ raise InvariantError, "expected value to be a Hash, but was #{value.class}"
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end