graphiti_gql 0.1.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 +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
|