graphiti_gql 0.2.5 → 0.2.8
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/.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: []
|