graphiti_gql 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.travis.yml +7 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +98 -0
- data/LICENSE.txt +21 -0
- data/README.md +3 -0
- data/Rakefile +6 -0
- data/bin/bundle +114 -0
- data/bin/byebug +27 -0
- data/bin/coderay +27 -0
- data/bin/console +14 -0
- data/bin/graphiti +27 -0
- data/bin/htmldiff +27 -0
- data/bin/ldiff +27 -0
- data/bin/pry +27 -0
- data/bin/rake +27 -0
- data/bin/rspec +27 -0
- data/bin/setup +8 -0
- data/config/routes.rb +6 -0
- data/graphiti_gql.gemspec +46 -0
- data/lib/graphiti_gql/engine.rb +29 -0
- data/lib/graphiti_gql/errors.rb +21 -0
- data/lib/graphiti_gql/graphiti_hax.rb +71 -0
- data/lib/graphiti_gql/loaders/belongs_to.rb +63 -0
- data/lib/graphiti_gql/loaders/has_many.rb +14 -0
- data/lib/graphiti_gql/loaders/many.rb +79 -0
- data/lib/graphiti_gql/loaders/many_to_many.rb +16 -0
- data/lib/graphiti_gql/loaders/polymorphic_has_many.rb +17 -0
- data/lib/graphiti_gql/response_shim.rb +13 -0
- data/lib/graphiti_gql/schema/connection.rb +57 -0
- data/lib/graphiti_gql/schema/fields/attribute.rb +46 -0
- data/lib/graphiti_gql/schema/fields/index.rb +33 -0
- data/lib/graphiti_gql/schema/fields/show.rb +33 -0
- data/lib/graphiti_gql/schema/fields/stats.rb +54 -0
- data/lib/graphiti_gql/schema/fields/to_many.rb +37 -0
- data/lib/graphiti_gql/schema/fields/to_one.rb +47 -0
- data/lib/graphiti_gql/schema/list_arguments.rb +127 -0
- data/lib/graphiti_gql/schema/polymorphic_belongs_to_interface.rb +35 -0
- data/lib/graphiti_gql/schema/query.rb +62 -0
- data/lib/graphiti_gql/schema/registry.rb +67 -0
- data/lib/graphiti_gql/schema/resource_type.rb +100 -0
- data/lib/graphiti_gql/schema/util.rb +74 -0
- data/lib/graphiti_gql/schema.rb +46 -0
- data/lib/graphiti_gql/version.rb +3 -0
- data/lib/graphiti_gql.rb +62 -0
- metadata +188 -0
@@ -0,0 +1,127 @@
|
|
1
|
+
module GraphitiGql
|
2
|
+
class Schema
|
3
|
+
class ListArguments
|
4
|
+
class SortDirType < GraphQL::Schema::Enum
|
5
|
+
graphql_name "SortDir"
|
6
|
+
value "asc", "Ascending"
|
7
|
+
value "desc", "Descending"
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(resource, sideload = nil)
|
11
|
+
@resource = resource
|
12
|
+
@sideload = sideload
|
13
|
+
end
|
14
|
+
|
15
|
+
def apply(field)
|
16
|
+
define_filters(field) unless @resource.filters.empty?
|
17
|
+
define_sorts(field) unless @resource.sorts.empty?
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def registry
|
23
|
+
Registry.instance
|
24
|
+
end
|
25
|
+
|
26
|
+
def define_filters(field)
|
27
|
+
filter_type = generate_filter_type(field)
|
28
|
+
required = @resource.filters.any? { |name, config|
|
29
|
+
value = !!config[:required]
|
30
|
+
if @sideload
|
31
|
+
value && @sideload.foreign_key != name
|
32
|
+
else
|
33
|
+
value
|
34
|
+
end
|
35
|
+
}
|
36
|
+
field.argument :filter, filter_type, required: required
|
37
|
+
end
|
38
|
+
|
39
|
+
def generate_filter_type(field)
|
40
|
+
type_name = "#{registry.key_for(@resource)}Filter"
|
41
|
+
if (registered = registry[type_name])
|
42
|
+
return registered[:type]
|
43
|
+
end
|
44
|
+
klass = Class.new(GraphQL::Schema::InputObject)
|
45
|
+
klass.graphql_name type_name
|
46
|
+
@resource.filters.each_pair do |name, config|
|
47
|
+
attr_type = generate_filter_attribute_type(type_name, name, config)
|
48
|
+
klass.argument name.to_s.camelize(:lower),
|
49
|
+
attr_type,
|
50
|
+
required: !!config[:required]
|
51
|
+
end
|
52
|
+
registry[type_name] = { type: klass }
|
53
|
+
klass
|
54
|
+
end
|
55
|
+
|
56
|
+
def generate_filter_attribute_type(type_name, filter_name, filter_config)
|
57
|
+
klass = Class.new(GraphQL::Schema::InputObject)
|
58
|
+
filter_graphql_name = "#{type_name}Filter#{filter_name.to_s.camelize(:lower)}"
|
59
|
+
klass.graphql_name(filter_graphql_name)
|
60
|
+
filter_config[:operators].keys.each do |operator|
|
61
|
+
canonical_graphiti_type = Graphiti::Types
|
62
|
+
.name_for(filter_config[:type])
|
63
|
+
type = GQL_TYPE_MAP[canonical_graphiti_type]
|
64
|
+
type = String if filter_name == :id
|
65
|
+
required = !!filter_config[:required] && operator == "eq"
|
66
|
+
|
67
|
+
if (allowlist = filter_config[:allow])
|
68
|
+
type = define_allowlist_type(filter_graphql_name, allowlist)
|
69
|
+
end
|
70
|
+
|
71
|
+
type = [type] unless !!filter_config[:single]
|
72
|
+
klass.argument operator, type, required: required
|
73
|
+
end
|
74
|
+
klass
|
75
|
+
end
|
76
|
+
|
77
|
+
def define_allowlist_type(filter_graphql_name, allowlist)
|
78
|
+
name = "#{filter_graphql_name}Allow"
|
79
|
+
if (registered = registry[name])
|
80
|
+
return registered[:type]
|
81
|
+
end
|
82
|
+
klass = Class.new(GraphQL::Schema::Enum)
|
83
|
+
klass.graphql_name(name)
|
84
|
+
allowlist.each do |allowed|
|
85
|
+
klass.value(allowed)
|
86
|
+
end
|
87
|
+
registry[name] = { type: klass }
|
88
|
+
klass
|
89
|
+
end
|
90
|
+
|
91
|
+
def define_sorts(field)
|
92
|
+
sort_type = generate_sort_type
|
93
|
+
field.argument :sort, [sort_type], required: false
|
94
|
+
end
|
95
|
+
|
96
|
+
def generate_sort_att_type
|
97
|
+
type_name = "#{registry.key_for(@resource)}SortAtt"
|
98
|
+
if (registered = registry[type_name])
|
99
|
+
return registered[:type]
|
100
|
+
end
|
101
|
+
klass = Class.new(GraphQL::Schema::Enum) {
|
102
|
+
graphql_name(type_name)
|
103
|
+
}
|
104
|
+
@resource.sorts.each_pair do |name, config|
|
105
|
+
klass.value name.to_s.camelize(:lower), "Sort by #{name}"
|
106
|
+
end
|
107
|
+
registry[type_name] = { type: klass }
|
108
|
+
klass
|
109
|
+
end
|
110
|
+
|
111
|
+
def generate_sort_type
|
112
|
+
type_name = "#{registry.key_for(@resource)}Sort"
|
113
|
+
if (registered = registry[type_name])
|
114
|
+
return registered[:type]
|
115
|
+
end
|
116
|
+
att_type = generate_sort_att_type
|
117
|
+
klass = Class.new(GraphQL::Schema::InputObject) {
|
118
|
+
graphql_name type_name
|
119
|
+
argument :att, att_type, required: true
|
120
|
+
argument :dir, SortDirType, required: true
|
121
|
+
}
|
122
|
+
registry[type_name] = { type: klass }
|
123
|
+
klass
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module GraphitiGql
|
2
|
+
class Schema
|
3
|
+
class PolymorphicBelongsToInterface
|
4
|
+
def initialize(resource, sideload)
|
5
|
+
@resource = resource
|
6
|
+
@sideload = sideload
|
7
|
+
end
|
8
|
+
|
9
|
+
def build
|
10
|
+
return registry[name][:type] if registry[name]
|
11
|
+
|
12
|
+
klass = Module.new
|
13
|
+
klass.send :include, ResourceType::BaseInterface
|
14
|
+
klass.field :id, String, null: false
|
15
|
+
klass.field :_type, String, null: false
|
16
|
+
klass.graphql_name(name)
|
17
|
+
@sideload.children.values.each do |child|
|
18
|
+
registry.get(child.resource.class)[:type].implements(klass)
|
19
|
+
end
|
20
|
+
registry[name] = { type: klass }
|
21
|
+
registry[name]
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def registry
|
27
|
+
Registry.instance
|
28
|
+
end
|
29
|
+
|
30
|
+
def name
|
31
|
+
"#{registry.key_for(@resource)}__#{@sideload.name}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module GraphitiGql
|
2
|
+
class Schema
|
3
|
+
class Query
|
4
|
+
def initialize(resources, existing_query: nil)
|
5
|
+
@resources = resources
|
6
|
+
@query_class = Class.new(existing_query || ::GraphQL::Schema::Object)
|
7
|
+
@query_class.graphql_name "Query"
|
8
|
+
@query_class.field_class ::GraphQL::Schema::Field
|
9
|
+
end
|
10
|
+
|
11
|
+
def build
|
12
|
+
@resources.each { |resource| ResourceType.new(resource).build }
|
13
|
+
define_entrypoints
|
14
|
+
add_relationships
|
15
|
+
@query_class
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def registry
|
21
|
+
Registry.instance
|
22
|
+
end
|
23
|
+
|
24
|
+
def define_entrypoints
|
25
|
+
registry.resource_types.each do |registered|
|
26
|
+
if GraphitiGql.entrypoint?(registered[:resource])
|
27
|
+
Fields::Index.new(registered).apply(@query_class)
|
28
|
+
Fields::Show.new(registered).apply(@query_class)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def add_relationships
|
34
|
+
each_relationship do |type, sideload_type, sideload|
|
35
|
+
if [:has_many, :many_to_many].include?(sideload.type)
|
36
|
+
Fields::ToMany.new(sideload, sideload_type).apply(type)
|
37
|
+
else
|
38
|
+
Fields::ToOne.new(sideload, sideload_type).apply(type)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def each_relationship
|
44
|
+
registry.resource_types.each do |registered|
|
45
|
+
registered[:resource].sideloads.each do |name, sl|
|
46
|
+
next unless sl.readable?
|
47
|
+
|
48
|
+
registered_sl = if sl.type == :polymorphic_belongs_to
|
49
|
+
PolymorphicBelongsToInterface
|
50
|
+
.new(registered[:resource], sl)
|
51
|
+
.build
|
52
|
+
else
|
53
|
+
registry.get(sl.resource.class)
|
54
|
+
end
|
55
|
+
|
56
|
+
yield registered[:type], registered_sl[:type], sl
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module GraphitiGql
|
2
|
+
class Schema
|
3
|
+
class Registry
|
4
|
+
include Singleton
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
clear
|
8
|
+
end
|
9
|
+
|
10
|
+
def get(object, interface: true)
|
11
|
+
@data[key_for(object, interface: interface)]
|
12
|
+
end
|
13
|
+
|
14
|
+
def set(resource, type, interface: true)
|
15
|
+
@data[key_for(resource, interface: interface)] = { resource: resource, type: type, interface: interface }
|
16
|
+
end
|
17
|
+
|
18
|
+
def key_for(object, interface: true)
|
19
|
+
if object.ancestors.include?(Graphiti::Resource)
|
20
|
+
key = key_for_resource(object)
|
21
|
+
if object.polymorphic?
|
22
|
+
if !object.polymorphic_child? && interface
|
23
|
+
key = "I#{key}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
key
|
27
|
+
else
|
28
|
+
raise 'unknown object!'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def clear
|
33
|
+
@data = {}
|
34
|
+
end
|
35
|
+
|
36
|
+
def []=(key, value)
|
37
|
+
@data[key] = value
|
38
|
+
end
|
39
|
+
|
40
|
+
def [](key)
|
41
|
+
@data[key]
|
42
|
+
end
|
43
|
+
|
44
|
+
def key?(key)
|
45
|
+
@data.key?(key)
|
46
|
+
end
|
47
|
+
|
48
|
+
def values
|
49
|
+
@data.values
|
50
|
+
end
|
51
|
+
|
52
|
+
# When polymorphic parent, returns the Interface not the Class
|
53
|
+
def resource_types
|
54
|
+
values
|
55
|
+
.select { |v| v.key?(:resource) && !v[:interface] }
|
56
|
+
.map { |registered| get(registered[:resource]) }
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def key_for_resource(resource)
|
62
|
+
resource.graphql_name ||
|
63
|
+
resource.name.gsub('Resource', '').gsub('::', '')
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module GraphitiGql
|
2
|
+
class Schema
|
3
|
+
class ResourceType
|
4
|
+
module BaseInterface
|
5
|
+
include GraphQL::Schema::Interface
|
6
|
+
|
7
|
+
definition_methods do
|
8
|
+
# Optional: if this method is defined, it overrides `Schema.resolve_type`
|
9
|
+
def resolve_type(object, context)
|
10
|
+
return object.type if object.is_a?(Loaders::FakeRecord)
|
11
|
+
resource = object.instance_variable_get(:@__graphiti_resource)
|
12
|
+
Registry.instance.get(resource.class)[:type]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(resource, implements: nil)
|
18
|
+
@resource = resource
|
19
|
+
@implements = implements
|
20
|
+
end
|
21
|
+
|
22
|
+
def build
|
23
|
+
return registry.get(@resource)[:type] if registry.get(@resource)
|
24
|
+
type = build_base_type
|
25
|
+
registry_name = registry.key_for(@resource, interface: poly_parent?)
|
26
|
+
type.connection_type_class(build_connection_class)
|
27
|
+
type.graphql_name(registry_name)
|
28
|
+
type.implements(@implements) if @implements
|
29
|
+
add_fields(type, @resource)
|
30
|
+
registry.set(@resource, type, interface: poly_parent?)
|
31
|
+
process_polymorphic_parent(type) if poly_parent?
|
32
|
+
type
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def process_polymorphic_parent(type)
|
38
|
+
# Define the actual class that implements the interface
|
39
|
+
registry.set(@resource, type, interface: false)
|
40
|
+
@resource.children.each do |child|
|
41
|
+
if (registered = registry.get(child))
|
42
|
+
registered[:type].implements(type)
|
43
|
+
else
|
44
|
+
self.class.new(child, implements: type).build
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def poly_parent?
|
50
|
+
@resource.polymorphic? && !@resource.polymorphic_child?
|
51
|
+
end
|
52
|
+
|
53
|
+
def build_base_type
|
54
|
+
klass = nil
|
55
|
+
if poly_parent?
|
56
|
+
type_name = "I#{name}"
|
57
|
+
klass = Module.new
|
58
|
+
klass.send(:include, BaseInterface)
|
59
|
+
ctx = nil
|
60
|
+
klass.definition_methods { ctx = self }
|
61
|
+
ctx.define_method :resolve_type do |object, context|
|
62
|
+
resource = object.instance_variable_get(:@__graphiti_resource)
|
63
|
+
registry_name = Registry.instance.key_for(resource.class)
|
64
|
+
if resource.polymorphic?
|
65
|
+
resource = resource.class.resource_for_model(object)
|
66
|
+
registry_name = Registry.instance.key_for(resource)
|
67
|
+
end
|
68
|
+
Registry.instance[registry_name][:type]
|
69
|
+
end
|
70
|
+
else
|
71
|
+
klass = Class.new(GraphQL::Schema::Object)
|
72
|
+
end
|
73
|
+
|
74
|
+
klass
|
75
|
+
end
|
76
|
+
|
77
|
+
def registry
|
78
|
+
Registry.instance
|
79
|
+
end
|
80
|
+
|
81
|
+
def name
|
82
|
+
registry.key_for(@resource)
|
83
|
+
end
|
84
|
+
|
85
|
+
def add_fields(type, resource)
|
86
|
+
resource.attributes.each_pair do |name, config|
|
87
|
+
if config[:readable]
|
88
|
+
Fields::Attribute.new(name, config).apply(type)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def build_connection_class
|
94
|
+
klass = Class.new(GraphQL::Types::Relay::BaseConnection)
|
95
|
+
Fields::Stats.new(@resource).apply(klass)
|
96
|
+
klass
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module GraphitiGql
|
2
|
+
class Schema
|
3
|
+
class Util
|
4
|
+
def self.params_from_args(arguments)
|
5
|
+
lookahead = arguments.delete(:lookahead)
|
6
|
+
params = arguments.as_json.deep_transform_keys { |key| key.to_s.underscore.to_sym }
|
7
|
+
if params[:sort]
|
8
|
+
params[:sort] = Util.transform_sort_param(params[:sort])
|
9
|
+
end
|
10
|
+
|
11
|
+
if (first = params.delete(:first))
|
12
|
+
params[:page] ||= {}
|
13
|
+
params[:page][:size] = first
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
if (last = params.delete(:last))
|
18
|
+
params[:page] ||= {}
|
19
|
+
params[:page][:size] = last
|
20
|
+
params[:reverse] = true
|
21
|
+
end
|
22
|
+
|
23
|
+
if (after = params.delete(:after))
|
24
|
+
params[:page] ||= {}
|
25
|
+
params[:page][:after] = after
|
26
|
+
end
|
27
|
+
|
28
|
+
if (before = params.delete(:before))
|
29
|
+
params[:page] ||= {}
|
30
|
+
params[:page][:before] = before
|
31
|
+
end
|
32
|
+
|
33
|
+
if (id = params.delete(:id))
|
34
|
+
params[:filter] ||= {}
|
35
|
+
params[:filter][:id] = { eq: id }
|
36
|
+
end
|
37
|
+
|
38
|
+
if lookahead.selects?(:stats)
|
39
|
+
stats = lookahead.selection(:stats)
|
40
|
+
payload = {}
|
41
|
+
stats.selections.map(&:name).each do |name|
|
42
|
+
payload[name] = stats.selection(name).selections.map(&:name)
|
43
|
+
end
|
44
|
+
params[:stats] = payload
|
45
|
+
|
46
|
+
# only requesting stats
|
47
|
+
if lookahead.selections.map(&:name) == [:stats]
|
48
|
+
params[:page] = { size: 0 }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
params
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.transform_sort_param(sorts)
|
56
|
+
sorts.map do |sort_param|
|
57
|
+
sort = sort_param[:att].underscore
|
58
|
+
sort = "-#{sort}" if sort_param[:dir] == "desc"
|
59
|
+
sort
|
60
|
+
end.join(",")
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.is_readable_sideload!(sideload)
|
64
|
+
readable = sideload.instance_variable_get(:@readable)
|
65
|
+
if readable.is_a?(Symbol)
|
66
|
+
path = Graphiti.context[:object][:current_path].join(".")
|
67
|
+
unless sideload.parent_resource.send(readable)
|
68
|
+
raise Errors::UnauthorizedField.new(path)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module GraphitiGql
|
2
|
+
class Schema
|
3
|
+
GQL_TYPE_MAP = {
|
4
|
+
integer_id: String,
|
5
|
+
string: String,
|
6
|
+
uuid: String,
|
7
|
+
integer: Integer,
|
8
|
+
float: Float,
|
9
|
+
boolean: GraphQL::Schema::Member::GraphQLTypeNames::Boolean,
|
10
|
+
date: GraphQL::Types::ISO8601Date,
|
11
|
+
datetime: GraphQL::Types::ISO8601DateTime,
|
12
|
+
hash: GraphQL::Types::JSON,
|
13
|
+
array: [GraphQL::Types::JSON],
|
14
|
+
array_of_strings: [String],
|
15
|
+
array_of_integers: [Integer],
|
16
|
+
array_of_floats: [Float],
|
17
|
+
array_of_dates: [GraphQL::Types::ISO8601Date],
|
18
|
+
array_of_datetimes: [GraphQL::Types::ISO8601DateTime]
|
19
|
+
}
|
20
|
+
|
21
|
+
class RelayConnectionExtension < GraphQL::Schema::Field::ConnectionExtension
|
22
|
+
def resolve(object:, arguments:, context:)
|
23
|
+
next_args = arguments.dup
|
24
|
+
yield(object, next_args, arguments)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize(resources)
|
29
|
+
@resources = resources
|
30
|
+
end
|
31
|
+
|
32
|
+
def generate
|
33
|
+
klass = Class.new(::GraphQL::Schema)
|
34
|
+
klass.query(Query.new(@resources).build)
|
35
|
+
klass.use(GraphQL::Batch)
|
36
|
+
klass.connections.add(ResponseShim, Connection)
|
37
|
+
klass.connections.add(Array, ToManyConnection)
|
38
|
+
klass
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
|
45
|
+
|
46
|
+
|
data/lib/graphiti_gql.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require "active_support/core_ext/object/json"
|
2
|
+
require "graphql"
|
3
|
+
require 'graphql/batch'
|
4
|
+
require "graphiti_gql/graphiti_hax"
|
5
|
+
require "graphiti_gql/version"
|
6
|
+
require "graphiti_gql/errors"
|
7
|
+
require "graphiti_gql/loaders/many"
|
8
|
+
require "graphiti_gql/loaders/has_many"
|
9
|
+
require "graphiti_gql/loaders/many_to_many"
|
10
|
+
require "graphiti_gql/loaders/polymorphic_has_many"
|
11
|
+
require "graphiti_gql/loaders/belongs_to"
|
12
|
+
require "graphiti_gql/response_shim"
|
13
|
+
require "graphiti_gql/schema"
|
14
|
+
require "graphiti_gql/schema/connection"
|
15
|
+
require "graphiti_gql/schema/registry"
|
16
|
+
require "graphiti_gql/schema/util"
|
17
|
+
require "graphiti_gql/schema/query"
|
18
|
+
require "graphiti_gql/schema/resource_type"
|
19
|
+
require "graphiti_gql/schema/polymorphic_belongs_to_interface"
|
20
|
+
require "graphiti_gql/schema/list_arguments"
|
21
|
+
require "graphiti_gql/schema/fields/show"
|
22
|
+
require "graphiti_gql/schema/fields/index"
|
23
|
+
require "graphiti_gql/schema/fields/to_many"
|
24
|
+
require "graphiti_gql/schema/fields/to_one"
|
25
|
+
require "graphiti_gql/schema/fields/attribute"
|
26
|
+
require "graphiti_gql/schema/fields/stats"
|
27
|
+
require "graphiti_gql/engine" if defined?(Rails)
|
28
|
+
|
29
|
+
module GraphitiGql
|
30
|
+
class Error < StandardError; end
|
31
|
+
|
32
|
+
def self.schema!
|
33
|
+
Schema::Registry.instance.clear
|
34
|
+
resources ||= Graphiti.resources.reject(&:abstract_class?)
|
35
|
+
@schema = Schema.new(resources).generate
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.schema
|
39
|
+
@schema
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.entrypoints=(val)
|
43
|
+
@entrypoints = val
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.entrypoints
|
47
|
+
@entrypoints
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.entrypoint?(resource)
|
51
|
+
@entrypoints.nil? || @entrypoints.include?(resource)
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.run(query_string, variables = {}, context = {})
|
55
|
+
Graphiti.with_context(context) do
|
56
|
+
result = schema.execute query_string,
|
57
|
+
variables: variables,
|
58
|
+
context: context
|
59
|
+
result.to_h
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|