-
Notifications
You must be signed in to change notification settings - Fork 227
Expand file tree
/
Copy pathgraphql_client.rb
More file actions
80 lines (69 loc) · 2.85 KB
/
graphql_client.rb
File metadata and controls
80 lines (69 loc) · 2.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# typed: true
# frozen_string_literal: true
require "graphql/client"
require "graphql/client/http"
require "tapioca/dsl/helpers/graphql_type_helper"
module Tapioca
module Dsl
module Compilers
class GraphqlClient < Compiler
extend T::Sig
# This is a hack to make Sorbet happy.
# It's necessary because there's no static class that implements this interface.
# See `GraphQL::Client::Schema::ObjectType.new`
class TypeClass
def self.fields; end
end
ConstantType = type_member { { fixed: T.class_of(TypeClass) } }
sig { override.returns(T::Enumerable[Module]) }
def self.gather_constants
graphql_type_modules = all_modules
.select { |mod| mod.singleton_class < GraphQL::Client::Schema::ClassMethods }
graphql_types = graphql_type_modules.flat_map do |mod|
mod_name = qualified_name_of(mod)
next unless mod_name # Ignore anonymous modules
mod.constants.map { |const| "#{mod_name}::#{const}".constantize }
end
graphql_types.select { |c| c.is_a?(Class) }
end
sig { override.void }
def decorate
root.create_path(constant) do |klass|
constant.fields.each do |name, definition|
define_field(klass, name, definition, constant)
end
end
end
private
def define_field(klass, name, definition, constant)
type = type_for(definition, constant)
klass.create_method(name.to_s.underscore, return_type: type) if type
end
def type_for(definition, constant, nilable: true)
type = case definition
when GraphQL::Client::Schema::NonNullType
nilable = false
type_for(definition.of_klass, constant, nilable: false)
when GraphQL::Client::Schema::ListType
sub_type = type_for(definition.of_klass, constant, nilable: nilable)
"T::Array[#{sub_type}]" if sub_type
when GraphQL::Client::Schema::ScalarType, GraphQL::Client::Schema::EnumType
argument = GraphQL::Schema::Argument.new(owner: nil)
argument.type = GraphQL::Schema::NonNull.new(definition.type)
Tapioca::Dsl::Helpers::GraphqlTypeHelper
.type_for_argument(argument, constant)
when GraphQL::Client::Schema::UnionType, GraphQL::Client::Schema::InterfaceType
nil
when Class
definition.name
else
raise "Unrecognised definition: #{definition}"
end
return unless type
type = "T.nilable(#{type})" if nilable && type != 'T.untyped'
type
end
end
end
end
end