graphiti_gql 0.2.5 → 0.2.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/probots.yml +2 -0
- data/Gemfile.lock +1 -1
- data/lib/graphiti_gql/active_resource.rb +66 -15
- data/lib/graphiti_gql/graphiti_hax.rb +29 -9
- data/lib/graphiti_gql/loaders/belongs_to.rb +1 -0
- data/lib/graphiti_gql/loaders/many_to_many.rb +4 -1
- data/lib/graphiti_gql/schema/fields/attribute.rb +1 -1
- data/lib/graphiti_gql/schema/fields/to_many.rb +29 -18
- data/lib/graphiti_gql/schema/list_arguments.rb +4 -1
- data/lib/graphiti_gql/schema/resource_type.rb +8 -3
- data/lib/graphiti_gql/spec_helper.rb +15 -17
- data/lib/graphiti_gql/version.rb +1 -1
- metadata +8 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c8711fac905c21ac485bec3ead197d2c5a8e2135eb5fcf1ff4156fec2a34d3ec
|
4
|
+
data.tar.gz: 82a643591b6f630d78d67e480cf915b8dbf1c0531fa0c817f204a9ae405d237c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6a6935dda01d0d68bacfc8c49252469322e93c96613a852f092dc76aa80cc44545b7e3c3d478fd5da28d6039c1a33940c9164f8bb1aad0b8018b1d2a5c92de72
|
7
|
+
data.tar.gz: fd9004e64db1c3dc39321e4eb2df56e5a7bf37a221c5323b062ddce182446ea1a4285649f61fdbb8508ac0b1a654c3311a7429bdc535f2589866b053c9d0617e
|
data/.github/probots.yml
ADDED
data/Gemfile.lock
CHANGED
@@ -1,17 +1,26 @@
|
|
1
|
+
# TODO: Rushing here so tests are in app and code is gross
|
1
2
|
module GraphitiGql
|
2
3
|
module ActiveResource
|
3
4
|
extend ActiveSupport::Concern
|
4
5
|
|
5
6
|
class Node < OpenStruct
|
6
|
-
def initialize(
|
7
|
+
def initialize(hash, resource = nil)
|
7
8
|
@resource = resource
|
9
|
+
@edges = {}
|
10
|
+
@node_id = hash.delete(:node_id)
|
8
11
|
hash.each_pair do |key, value|
|
9
12
|
if value.is_a?(Hash)
|
10
13
|
if (sideload = resource.sideload(key))
|
11
14
|
if value.key?(:edges)
|
12
|
-
|
15
|
+
@edges[key] = value[:edges].map do |edge|
|
16
|
+
node_id = edge[:node][:id]
|
17
|
+
Node.new(edge.except(:node).merge(node_id: node_id))
|
18
|
+
end
|
19
|
+
hash[key] = value[:edges].map { |v| Node.new(v[:node], sideload.resource.class) }
|
20
|
+
elsif value.key?(:nodes)
|
21
|
+
hash[key] = value[:nodes].map { |n| Node.new(n, sideload.resource.class) }
|
13
22
|
else
|
14
|
-
hash[key] = Node.new(sideload.resource.class
|
23
|
+
hash[key] = Node.new(value, sideload.resource.class)
|
15
24
|
end
|
16
25
|
end
|
17
26
|
end
|
@@ -19,6 +28,15 @@ module GraphitiGql
|
|
19
28
|
super(hash)
|
20
29
|
end
|
21
30
|
|
31
|
+
def edge(name, node_id)
|
32
|
+
found = @edges[name].empty? ? nil : @edges[name]
|
33
|
+
if found && node_id
|
34
|
+
found.find { |f| f.instance_variable_get(:@node_id) == node_id.to_s }
|
35
|
+
else
|
36
|
+
found
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
22
40
|
def decoded_id
|
23
41
|
Base64.decode64(self.id)
|
24
42
|
end
|
@@ -29,7 +47,8 @@ module GraphitiGql
|
|
29
47
|
end
|
30
48
|
|
31
49
|
class Proxy
|
32
|
-
def initialize(resource, params, ctx)
|
50
|
+
def initialize(resource, params, ctx, query)
|
51
|
+
@query = query
|
33
52
|
@resource = resource
|
34
53
|
@ctx = ctx
|
35
54
|
@params = params.deep_transform_keys { |key| key.to_s.camelize(:lower).to_sym }
|
@@ -46,10 +65,18 @@ module GraphitiGql
|
|
46
65
|
result
|
47
66
|
end
|
48
67
|
|
68
|
+
def node(id)
|
69
|
+
nodes.find { |n| n.id == id.to_s }
|
70
|
+
end
|
71
|
+
|
49
72
|
def nodes
|
50
73
|
return [] unless data
|
51
|
-
|
52
|
-
|
74
|
+
elements = if edges
|
75
|
+
edges.map { |e| e[:node] }
|
76
|
+
else
|
77
|
+
data[data.keys.first][:nodes] || []
|
78
|
+
end
|
79
|
+
elements.map { |n| Node.new(underscore(n), @resource) }
|
53
80
|
end
|
54
81
|
alias :to_a :nodes
|
55
82
|
|
@@ -85,10 +112,14 @@ module GraphitiGql
|
|
85
112
|
underscore(data[data.keys.first][:pageInfo])
|
86
113
|
end
|
87
114
|
|
115
|
+
# barf
|
88
116
|
def query
|
117
|
+
return @query if @query
|
118
|
+
|
89
119
|
name = Schema.registry.key_for(@resource)
|
90
|
-
filter_bang = "!" if @resource.filters.values.any? { |f| f[:required] }
|
91
120
|
sortvar = "$sort: [#{name}Sort!]," if @resource.sorts.any?
|
121
|
+
filter_bang = "!" if @resource.filters.values.any? { |f| f[:required] }
|
122
|
+
filtervar = "$filter: #{name}Filter#{filter_bang}," if @resource.filters.any?
|
92
123
|
|
93
124
|
if !(fields = @params[:fields])
|
94
125
|
fields = []
|
@@ -99,7 +130,7 @@ module GraphitiGql
|
|
99
130
|
|
100
131
|
q = %|
|
101
132
|
query #{name} (
|
102
|
-
|
133
|
+
#{filtervar}
|
103
134
|
#{sortvar}
|
104
135
|
$first: Int,
|
105
136
|
$last: Int,
|
@@ -107,7 +138,7 @@ module GraphitiGql
|
|
107
138
|
$after: String,
|
108
139
|
) {
|
109
140
|
#{@resource.graphql_entrypoint} (
|
110
|
-
filter: $filter,
|
141
|
+
#{ 'filter: $filter,' if filtervar }
|
111
142
|
#{ 'sort: $sort,' if sortvar }
|
112
143
|
first: $first,
|
113
144
|
last: $last,
|
@@ -118,6 +149,7 @@ module GraphitiGql
|
|
118
149
|
node {|
|
119
150
|
|
120
151
|
fields.each do |name|
|
152
|
+
next if name.is_a?(Hash)
|
121
153
|
q << %|
|
122
154
|
#{name.to_s.camelize(:lower)}|
|
123
155
|
end
|
@@ -129,17 +161,36 @@ module GraphitiGql
|
|
129
161
|
sideload = @resource.sideload(inc.to_sym)
|
130
162
|
to_one = [:belongs_to, :has_one, :polymorphic_belongs_to].include?(sideload.type)
|
131
163
|
indent = " " if !to_one
|
164
|
+
|
165
|
+
edge_fields = []
|
166
|
+
runtime_sideload_fields = @params[:fields].find { |f| f.is_a?(Hash) && f.key?(inc.to_sym) }
|
167
|
+
if runtime_sideload_fields
|
168
|
+
runtime_sideload_fields = runtime_sideload_fields.values
|
169
|
+
edge_fields = runtime_sideload_fields.find { |f| f.is_a?(Hash) && f.key?(:edge) }
|
170
|
+
runtime_sideload_fields = runtime_sideload_fields.reject { |f| f.is_a?(Hash) }
|
171
|
+
edge_fields = edge_fields[:edge] if edge_fields
|
172
|
+
end
|
173
|
+
|
132
174
|
q << %|
|
133
175
|
#{inc.to_s.camelize(:lower)} {|
|
134
176
|
if !to_one
|
135
177
|
q << %|
|
136
|
-
edges {
|
178
|
+
edges {|
|
179
|
+
|
180
|
+
edge_fields.each do |ef|
|
181
|
+
q << %|
|
182
|
+
#{ef.to_s.camelize(:lower)}|
|
183
|
+
end
|
184
|
+
|
185
|
+
q << %|
|
137
186
|
node {|
|
138
187
|
end
|
139
188
|
|
140
|
-
|
141
|
-
|
142
|
-
|
189
|
+
sideload_fields = runtime_sideload_fields
|
190
|
+
if sideload_fields.blank?
|
191
|
+
sideload_fields = @resource.sideload(inc.to_sym).resource.attributes.select { |_, config| config[:readable] }.map(&:first)
|
192
|
+
end
|
193
|
+
sideload_fields.each do |name|
|
143
194
|
q << %|
|
144
195
|
#{indent}#{name.to_s.camelize(:lower)}|
|
145
196
|
end
|
@@ -200,8 +251,8 @@ module GraphitiGql
|
|
200
251
|
end
|
201
252
|
|
202
253
|
class_methods do
|
203
|
-
def gql(params = {}, ctx = {})
|
204
|
-
Proxy.new(self, params, ctx)
|
254
|
+
def gql(params = {}, ctx = {}, query = nil)
|
255
|
+
Proxy.new(self, params, ctx, query)
|
205
256
|
end
|
206
257
|
end
|
207
258
|
end
|
@@ -143,22 +143,42 @@ module GraphitiGql
|
|
143
143
|
Graphiti::Scoping::Paginate.send(:prepend, PaginateExtras)
|
144
144
|
|
145
145
|
module ManyToManyExtras
|
146
|
-
|
146
|
+
def self.prepended(klass)
|
147
|
+
klass.class_eval do
|
148
|
+
class << self
|
149
|
+
attr_accessor :edge_resource
|
147
150
|
|
148
|
-
|
149
|
-
|
151
|
+
def attribute(*args, &blk)
|
152
|
+
@edge_resource ||= Class.new(Graphiti::Resource) do
|
153
|
+
def self.abstract_class?
|
154
|
+
true
|
155
|
+
end
|
156
|
+
end
|
157
|
+
@edge_resource.attribute(*args, &blk)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def apply_belongs_to_many_filter
|
164
|
+
super
|
165
|
+
return unless respond_to?(:belongs_to_many_filter) # activerecord
|
166
|
+
self_ref = self
|
167
|
+
fk_type = parent_resource_class.attributes[:id][:type]
|
168
|
+
fk_type = :hash if polymorphic?
|
169
|
+
filters = resource_class.config[:filters]
|
150
170
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
171
|
+
# Keep the options, apply the eq proc
|
172
|
+
if (filter = filters[inverse_filter.to_sym])
|
173
|
+
if filter[:operators][:eq].nil?
|
174
|
+
filter[:operators][:eq] = proc do |scope, value|
|
175
|
+
self_ref.belongs_to_many_filter(scope, value)
|
155
176
|
end
|
156
177
|
end
|
157
|
-
@edge_resource.attribute(*args, &blk)
|
158
178
|
end
|
159
179
|
end
|
160
180
|
end
|
161
|
-
Graphiti::Sideload::ManyToMany.send(:
|
181
|
+
Graphiti::Sideload::ManyToMany.send(:prepend, ManyToManyExtras)
|
162
182
|
|
163
183
|
module StatsExtras
|
164
184
|
def calculate_stat(name, function)
|
@@ -19,8 +19,11 @@ module GraphitiGql
|
|
19
19
|
def add_join_table_magic(proxy)
|
20
20
|
if defined?(ActiveRecord) && proxy.resource.model.ancestors.include?(ActiveRecord::Base)
|
21
21
|
thru = @sideload.foreign_key.keys.first
|
22
|
-
|
22
|
+
reflection = @sideload.parent_resource.model.reflect_on_association(thru)
|
23
|
+
thru_model = reflection.klass
|
24
|
+
|
23
25
|
names = thru_model.column_names.map do |n|
|
26
|
+
next if n == :id
|
24
27
|
"#{thru_model.table_name}.#{n} as _edge_#{n}"
|
25
28
|
end
|
26
29
|
scope = proxy.scope.object
|
@@ -4,11 +4,8 @@ module GraphitiGql
|
|
4
4
|
class ToMany
|
5
5
|
def initialize(sideload, sideload_type)
|
6
6
|
@sideload = sideload
|
7
|
-
@sideload_type =
|
8
|
-
|
9
|
-
else
|
10
|
-
sideload_type
|
11
|
-
end
|
7
|
+
@sideload_type = sideload_type
|
8
|
+
@connection_type = find_or_build_connection
|
12
9
|
end
|
13
10
|
|
14
11
|
def apply(type)
|
@@ -18,7 +15,7 @@ module GraphitiGql
|
|
18
15
|
extras: [:lookahead]
|
19
16
|
}
|
20
17
|
opts[:extensions] = [RelayConnectionExtension] unless has_one?
|
21
|
-
field_type = has_one? ? @sideload_type : @
|
18
|
+
field_type = has_one? ? @sideload_type : @connection_type
|
22
19
|
field = type.field @sideload.name,
|
23
20
|
field_type,
|
24
21
|
**opts
|
@@ -41,25 +38,39 @@ module GraphitiGql
|
|
41
38
|
@sideload.type == :many_to_many && @sideload.class.edge_resource
|
42
39
|
end
|
43
40
|
|
44
|
-
def
|
45
|
-
|
46
|
-
|
47
|
-
|
41
|
+
def find_or_build_connection
|
42
|
+
if customized_edge?
|
43
|
+
prior = @sideload_type.connection_type
|
44
|
+
klass = Class.new(prior)
|
45
|
+
registered_parent = Schema.registry.get(@sideload.parent_resource.class)
|
46
|
+
parent_name = registered_parent[:type].graphql_name
|
47
|
+
name = "#{parent_name}To#{@sideload_type.graphql_name}Connection"
|
48
|
+
klass.graphql_name(name)
|
49
|
+
edge_type_class = build_edge_type_class(@sideload_type)
|
50
|
+
edge_type_class.node_type(prior.node_type)
|
51
|
+
klass.edge_type(edge_type_class)
|
52
|
+
klass
|
53
|
+
else
|
54
|
+
@sideload_type.connection_type
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def build_edge_type_class(sideload_type)
|
59
|
+
prior_edge_type_class = sideload_type.edge_type_class
|
60
|
+
edge_type_class = Class.new(prior_edge_type_class)
|
48
61
|
edge_resource = @sideload.class.edge_resource
|
49
62
|
edge_resource.attributes.each_pair do |name, config|
|
50
63
|
next if name == :id
|
51
|
-
Schema::Fields::Attribute.new(name, config, @sideload).apply(
|
64
|
+
Schema::Fields::Attribute.new(name, config, @sideload).apply(edge_type_class)
|
52
65
|
end
|
53
66
|
registered_parent = Schema.registry.get(@sideload.parent_resource.class)
|
54
67
|
parent_name = registered_parent[:type].graphql_name
|
55
|
-
|
56
|
-
|
68
|
+
edge_type_class_name = "#{parent_name}To#{sideload_type.graphql_name}Edge"
|
69
|
+
edge_type_class.define_method :graphql_name do
|
70
|
+
edge_type_class_name
|
57
71
|
end
|
58
|
-
|
59
|
-
|
60
|
-
klass = Class.new(sideload_type)
|
61
|
-
klass.edge_type_class(edge_class)
|
62
|
-
klass
|
72
|
+
edge_type_class.graphql_name(edge_type_class_name)
|
73
|
+
edge_type_class
|
63
74
|
end
|
64
75
|
end
|
65
76
|
end
|
@@ -23,12 +23,15 @@ module GraphitiGql
|
|
23
23
|
Registry.instance
|
24
24
|
end
|
25
25
|
|
26
|
+
# TODO - when no sorts schema error, when no filters schema error
|
26
27
|
def define_filters(field)
|
27
28
|
filter_type = generate_filter_type(field)
|
28
29
|
required = @resource.filters.any? { |name, config|
|
29
30
|
value = !!config[:required]
|
30
31
|
if @sideload
|
31
|
-
|
32
|
+
fk = @sideload.foreign_key
|
33
|
+
fk = fk.values.first if fk.is_a?(Hash)
|
34
|
+
value && fk != name
|
32
35
|
else
|
33
36
|
value
|
34
37
|
end
|
@@ -34,14 +34,19 @@ module GraphitiGql
|
|
34
34
|
|
35
35
|
private
|
36
36
|
|
37
|
-
def process_polymorphic_parent(
|
37
|
+
def process_polymorphic_parent(interface_type)
|
38
|
+
registry_name = registry.key_for(@resource, interface: false)
|
39
|
+
type = Class.new(Schema.base_object)
|
40
|
+
type.graphql_name(registry_name)
|
41
|
+
type.implements(interface_type)
|
42
|
+
|
38
43
|
# Define the actual class that implements the interface
|
39
44
|
registry.set(@resource, type, interface: false)
|
40
45
|
@resource.children.each do |child|
|
41
46
|
if (registered = registry.get(child))
|
42
|
-
registered[:type].implements(
|
47
|
+
registered[:type].implements(interface_type)
|
43
48
|
else
|
44
|
-
self.class.new(child, implements:
|
49
|
+
self.class.new(child, implements: interface_type).build
|
45
50
|
end
|
46
51
|
end
|
47
52
|
end
|
@@ -24,6 +24,7 @@ module GraphitiGql
|
|
24
24
|
:errors,
|
25
25
|
:error_messages,
|
26
26
|
:nodes,
|
27
|
+
:node,
|
27
28
|
:stats
|
28
29
|
|
29
30
|
Graphiti::Resource.send(:prepend, ScopeTrackable)
|
@@ -42,20 +43,20 @@ module GraphitiGql
|
|
42
43
|
def self.except_fields(*fields)
|
43
44
|
let(:except_fields) { fields }
|
44
45
|
end
|
45
|
-
end
|
46
|
-
end
|
47
46
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
47
|
+
let(:fields) do
|
48
|
+
fields = []
|
49
|
+
resource.attributes.each_pair do |name, config|
|
50
|
+
(fields << name) if config[:readable]
|
51
|
+
end
|
52
|
+
if respond_to?(:only_fields) && only_fields.present?
|
53
|
+
fields.select! { |f| only_fields.include?(f) }
|
54
|
+
elsif respond_to?(:except_fields) && except_fields.present?
|
55
|
+
fields.reject! { |f| except_fields.include?(f) }
|
56
|
+
end
|
57
|
+
fields
|
58
|
+
end
|
57
59
|
end
|
58
|
-
fields
|
59
60
|
end
|
60
61
|
|
61
62
|
def gql_datetime(timestamp, precise = false)
|
@@ -67,11 +68,8 @@ module GraphitiGql
|
|
67
68
|
end
|
68
69
|
|
69
70
|
def proxy
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
def query
|
74
|
-
proxy.query
|
71
|
+
q = defined?(query) ? query : nil
|
72
|
+
resource.gql(params.merge(fields: fields), ctx, q)
|
75
73
|
end
|
76
74
|
|
77
75
|
def run
|
data/lib/graphiti_gql/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graphiti_gql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lee Richmond
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-07-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: graphql
|
@@ -108,13 +108,14 @@ dependencies:
|
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '7.0'
|
111
|
-
description:
|
111
|
+
description:
|
112
112
|
email:
|
113
113
|
- richmolj@gmail.com
|
114
114
|
executables: []
|
115
115
|
extensions: []
|
116
116
|
extra_rdoc_files: []
|
117
117
|
files:
|
118
|
+
- ".github/probots.yml"
|
118
119
|
- ".gitignore"
|
119
120
|
- ".rspec"
|
120
121
|
- ".travis.yml"
|
@@ -169,7 +170,7 @@ licenses:
|
|
169
170
|
- MIT
|
170
171
|
metadata:
|
171
172
|
homepage_uri: https://www.graphiti.dev
|
172
|
-
post_install_message:
|
173
|
+
post_install_message:
|
173
174
|
rdoc_options: []
|
174
175
|
require_paths:
|
175
176
|
- lib
|
@@ -184,8 +185,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
184
185
|
- !ruby/object:Gem::Version
|
185
186
|
version: '0'
|
186
187
|
requirements: []
|
187
|
-
rubygems_version: 3.
|
188
|
-
signing_key:
|
188
|
+
rubygems_version: 3.3.7
|
189
|
+
signing_key:
|
189
190
|
specification_version: 4
|
190
191
|
summary: GraphQL support for Graphiti
|
191
192
|
test_files: []
|