graphql-client 0.9.0 → 0.10.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.
@@ -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