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.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/graphql/client.rb +20 -10
- data/lib/graphql/client/definition.rb +116 -23
- data/lib/graphql/client/deprecation.rb +2 -2
- data/lib/graphql/client/document_types.rb +3 -0
- data/lib/graphql/client/error.rb +3 -0
- data/lib/graphql/client/response.rb +2 -2
- data/lib/graphql/client/schema.rb +106 -0
- data/lib/graphql/client/schema/base_type.rb +39 -0
- data/lib/graphql/client/schema/enum_type.rb +56 -0
- data/lib/graphql/client/schema/include_directive.rb +44 -0
- data/lib/graphql/client/schema/interface_type.rb +31 -0
- data/lib/graphql/client/schema/list_type.rb +57 -0
- data/lib/graphql/client/schema/non_null_type.rb +52 -0
- data/lib/graphql/client/schema/object_type.rb +162 -0
- data/lib/graphql/client/schema/possible_types.rb +55 -0
- data/lib/graphql/client/schema/scalar_type.rb +47 -0
- data/lib/graphql/client/schema/skip_directive.rb +44 -0
- data/lib/graphql/client/schema/union_type.rb +31 -0
- metadata +14 -3
- data/lib/graphql/client/query_result.rb +0 -402
@@ -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
|