graphiti 1.2.35 → 1.2.40
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/lib/graphiti/hash_renderer.rb +51 -19
- data/lib/graphiti/request_validators/validator.rb +10 -5
- data/lib/graphiti/schema.rb +18 -1
- data/lib/graphiti/schema_diff.rb +44 -4
- data/lib/graphiti/sideload.rb +6 -1
- data/lib/graphiti/util/serializer_attributes.rb +12 -6
- data/lib/graphiti/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d10b110934848ed53d75bb0b8595f73c50524833818d39dc53f3859c393d342b
|
|
4
|
+
data.tar.gz: a28ab64e8453486628ee93d131914479c24d60ade77e8dd201030bbe68dd055c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1d1d78896c8079cfbc4e74f3f6b754047a5c597adfe87023340adae7c56029ef60873c5cfe91fd099d7aac7965db7048dfb45e10efa8d29a39e4cdbfc19d99e3
|
|
7
|
+
data.tar.gz: f563f24c252c72e49a8bc8ba52ac8a6c5ab814d7699817fce981adee68dc74edc6e3dc82f2a5fdc5986e1b07411fbad776df5bba7099baeae930b305a03e0b92
|
|
@@ -74,19 +74,22 @@ module Graphiti
|
|
|
74
74
|
name_chain << k unless name_chain.last == k
|
|
75
75
|
|
|
76
76
|
unless remote_resource? && serializers.nil?
|
|
77
|
-
|
|
78
|
-
serializers.map
|
|
77
|
+
payload = if serializers.is_a?(Array)
|
|
78
|
+
data = serializers.map { |rr|
|
|
79
79
|
rr.to_hash(fields: fields, include: nested_include, graphql: graphql, name_chain: name_chain)
|
|
80
|
-
|
|
80
|
+
}
|
|
81
|
+
graphql ? {nodes: data} : data
|
|
81
82
|
elsif serializers.nil?
|
|
82
83
|
if @resource.class.respond_to?(:sideload)
|
|
83
84
|
if @resource.class.sideload(k).type.to_s.include?("_many")
|
|
84
|
-
[]
|
|
85
|
+
graphql ? {nodes: []} : []
|
|
85
86
|
end
|
|
86
87
|
end
|
|
87
88
|
else
|
|
88
89
|
serializers.to_hash(fields: fields, include: nested_include, graphql: graphql, name_chain: name_chain)
|
|
89
90
|
end
|
|
91
|
+
|
|
92
|
+
attrs[name.to_sym] = payload
|
|
90
93
|
end
|
|
91
94
|
end
|
|
92
95
|
|
|
@@ -133,29 +136,58 @@ module Graphiti
|
|
|
133
136
|
serializers = options[:data]
|
|
134
137
|
opts = options.slice(:fields, :include)
|
|
135
138
|
opts[:graphql] = @graphql
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
+
top_level_key = get_top_level_key(@resource, serializers.is_a?(Array))
|
|
140
|
+
|
|
141
|
+
hash = {top_level_key => {}}
|
|
142
|
+
nodes = get_nodes(serializers, opts)
|
|
143
|
+
add_nodes(hash, top_level_key, options, nodes, @graphql)
|
|
144
|
+
add_stats(hash, top_level_key, options, @graphql)
|
|
145
|
+
hash
|
|
139
146
|
end
|
|
140
147
|
|
|
141
148
|
private
|
|
142
149
|
|
|
143
|
-
def
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
150
|
+
def get_top_level_key(resource, is_many)
|
|
151
|
+
key = :data
|
|
152
|
+
|
|
153
|
+
if @graphql
|
|
154
|
+
key = @resource.graphql_entrypoint
|
|
155
|
+
key = key.to_s.singularize.to_sym unless is_many
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
key
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def get_nodes(serializers, opts)
|
|
162
|
+
if serializers.is_a?(Array)
|
|
163
|
+
serializers.map do |s|
|
|
164
|
+
s.to_hash(**opts)
|
|
151
165
|
end
|
|
166
|
+
else
|
|
167
|
+
serializers.to_hash(**opts)
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def add_nodes(hash, top_level_key, opts, nodes, graphql)
|
|
172
|
+
payload = nodes
|
|
173
|
+
if graphql && nodes.is_a?(Array)
|
|
174
|
+
payload = {nodes: nodes}
|
|
175
|
+
end
|
|
152
176
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
177
|
+
# Don't render nodes if we only requested stats
|
|
178
|
+
unless graphql && opts[:fields].values == [[:stats]]
|
|
179
|
+
hash[top_level_key] = payload
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def add_stats(hash, top_level_key, options, graphql)
|
|
184
|
+
if options[:meta] && !options[:meta].empty?
|
|
185
|
+
if @graphql
|
|
186
|
+
if (stats = options[:meta][:stats])
|
|
187
|
+
hash[top_level_key][:stats] = stats
|
|
156
188
|
end
|
|
157
189
|
else
|
|
158
|
-
|
|
190
|
+
hash.merge!(options.slice(:meta))
|
|
159
191
|
end
|
|
160
192
|
end
|
|
161
193
|
end
|
|
@@ -25,7 +25,7 @@ module Graphiti
|
|
|
25
25
|
end
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
typecast_attributes(resource, deserialized_payload.attributes, deserialized_payload.meta[:payload_path])
|
|
28
|
+
typecast_attributes(resource, deserialized_payload.attributes, @action, deserialized_payload.meta[:payload_path])
|
|
29
29
|
process_relationships(resource, deserialized_payload.relationships, deserialized_payload.meta[:payload_path])
|
|
30
30
|
else
|
|
31
31
|
errors.add(:"data.type", :missing)
|
|
@@ -65,15 +65,20 @@ module Graphiti
|
|
|
65
65
|
next
|
|
66
66
|
end
|
|
67
67
|
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
resource = x[:resource]
|
|
69
|
+
attributes = x[:attributes]
|
|
70
|
+
relationships = x[:relationships]
|
|
71
|
+
payload_path = x[:meta][:payload_path]
|
|
72
|
+
action = x[:meta][:method]
|
|
73
|
+
typecast_attributes(resource, attributes, action, payload_path)
|
|
74
|
+
process_relationships(resource, relationships, payload_path)
|
|
70
75
|
end
|
|
71
76
|
end
|
|
72
77
|
|
|
73
|
-
def typecast_attributes(resource, attributes, payload_path)
|
|
78
|
+
def typecast_attributes(resource, attributes, action, payload_path)
|
|
74
79
|
attributes.each_pair do |key, value|
|
|
75
80
|
# Only validate id if create action, otherwise it's only used for lookup
|
|
76
|
-
next if
|
|
81
|
+
next if action != :create &&
|
|
77
82
|
key == :id &&
|
|
78
83
|
resource.class.config[:attributes][:id][:writable] == false
|
|
79
84
|
|
data/lib/graphiti/schema.rb
CHANGED
|
@@ -96,9 +96,14 @@ module Graphiti
|
|
|
96
96
|
extra_attributes: extra_attributes(r),
|
|
97
97
|
sorts: sorts(r),
|
|
98
98
|
filters: filters(r),
|
|
99
|
-
relationships: relationships(r)
|
|
99
|
+
relationships: relationships(r),
|
|
100
|
+
stats: stats(r)
|
|
100
101
|
}
|
|
101
102
|
|
|
103
|
+
if r.grouped_filters.any?
|
|
104
|
+
config[:filter_group] = r.grouped_filters
|
|
105
|
+
end
|
|
106
|
+
|
|
102
107
|
if r.default_sort
|
|
103
108
|
default_sort = r.default_sort.map { |s|
|
|
104
109
|
{s.keys.first.to_s => s.values.first.to_s}
|
|
@@ -165,6 +170,14 @@ module Graphiti
|
|
|
165
170
|
end
|
|
166
171
|
end
|
|
167
172
|
|
|
173
|
+
def stats(resource)
|
|
174
|
+
{}.tap do |stats|
|
|
175
|
+
resource.stats.each_pair do |name, config|
|
|
176
|
+
stats[name] = config.calculations.keys
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
168
181
|
def sorts(resource)
|
|
169
182
|
{}.tap do |s|
|
|
170
183
|
resource.sorts.each_pair do |name, sort|
|
|
@@ -212,6 +225,10 @@ module Graphiti
|
|
|
212
225
|
end
|
|
213
226
|
end
|
|
214
227
|
|
|
228
|
+
def filter_group(resource)
|
|
229
|
+
resource.config[:grouped_filters]
|
|
230
|
+
end
|
|
231
|
+
|
|
215
232
|
def relationships(resource)
|
|
216
233
|
{}.tap do |r|
|
|
217
234
|
resource.sideloads.each_pair do |name, config|
|
data/lib/graphiti/schema_diff.rb
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
module Graphiti
|
|
2
2
|
class SchemaDiff
|
|
3
3
|
def initialize(old, new)
|
|
4
|
-
@old = old.deep_symbolize_keys
|
|
5
|
-
@new = new.deep_symbolize_keys
|
|
4
|
+
@old = JSON.parse(old.to_json).deep_symbolize_keys
|
|
5
|
+
@new = JSON.parse(new.to_json).deep_symbolize_keys
|
|
6
6
|
@errors = []
|
|
7
7
|
end
|
|
8
8
|
|
|
@@ -30,6 +30,8 @@ module Graphiti
|
|
|
30
30
|
compare_extra_attributes(r, new_resource)
|
|
31
31
|
compare_sorts(r, new_resource)
|
|
32
32
|
compare_filters(r, new_resource)
|
|
33
|
+
compare_filter_group(r, new_resource)
|
|
34
|
+
compare_stats(r, new_resource)
|
|
33
35
|
compare_relationships(r, new_resource)
|
|
34
36
|
end
|
|
35
37
|
end
|
|
@@ -133,12 +135,12 @@ module Graphiti
|
|
|
133
135
|
end
|
|
134
136
|
|
|
135
137
|
if new_sort[:only] && !old_sort[:only]
|
|
136
|
-
@errors << "#{old_resource[:name]}: sort #{name.inspect} now limited to only #{new_sort[:only].inspect}."
|
|
138
|
+
@errors << "#{old_resource[:name]}: sort #{name.inspect} now limited to only #{new_sort[:only].to_sym.inspect}."
|
|
137
139
|
end
|
|
138
140
|
|
|
139
141
|
if new_sort[:only] && old_sort[:only]
|
|
140
142
|
if new_sort[:only] != old_sort[:only]
|
|
141
|
-
@errors << "#{old_resource[:name]}: sort #{name.inspect} was limited to only #{old_sort[:only].inspect}, now limited to only #{new_sort[:only].inspect}."
|
|
143
|
+
@errors << "#{old_resource[:name]}: sort #{name.inspect} was limited to only #{old_sort[:only].to_sym.inspect}, now limited to only #{new_sort[:only].to_sym.inspect}."
|
|
142
144
|
end
|
|
143
145
|
end
|
|
144
146
|
end
|
|
@@ -204,6 +206,44 @@ module Graphiti
|
|
|
204
206
|
end
|
|
205
207
|
end
|
|
206
208
|
|
|
209
|
+
def compare_filter_group(old_resource, new_resource)
|
|
210
|
+
if new_resource[:filter_group]
|
|
211
|
+
if old_resource[:filter_group]
|
|
212
|
+
new_names = new_resource[:filter_group][:names]
|
|
213
|
+
old_names = old_resource[:filter_group][:names]
|
|
214
|
+
diff = new_names - old_names
|
|
215
|
+
if !diff.empty? && new_resource[:filter_group][:required] == "all"
|
|
216
|
+
@errors << "#{old_resource[:name]}: all required filter group #{old_names.map(&:to_sym).inspect} added #{"member".pluralize(diff.length)} #{diff.map(&:to_sym).inspect}."
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
old_required = old_resource[:filter_group][:required]
|
|
220
|
+
new_required = new_resource[:filter_group][:required]
|
|
221
|
+
if old_required == "any" && new_required == "all"
|
|
222
|
+
@errors << "#{old_resource[:name]}: filter group #{old_names.map(&:to_sym).inspect} moved from required: :any to required: :all"
|
|
223
|
+
end
|
|
224
|
+
else
|
|
225
|
+
@errors << "#{old_resource[:name]}: filter group #{new_resource[:filter_group][:names].map(&:to_sym).inspect} was added."
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def compare_stats(old_resource, new_resource)
|
|
231
|
+
return unless old_resource.key?(:stats)
|
|
232
|
+
|
|
233
|
+
old_resource[:stats].each_pair do |name, old_calculations|
|
|
234
|
+
new_calculations = new_resource[:stats][name]
|
|
235
|
+
if new_calculations
|
|
236
|
+
old_calculations.each do |calc|
|
|
237
|
+
unless new_calculations.include?(calc)
|
|
238
|
+
@errors << "#{old_resource[:name]}: calculation #{calc.to_sym.inspect} was removed from stat #{name.inspect}."
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
else
|
|
242
|
+
@errors << "#{old_resource[:name]}: stat #{name.inspect} was removed."
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
|
|
207
247
|
def compare_endpoints
|
|
208
248
|
@old[:endpoints].each_pair do |path, old_endpoint|
|
|
209
249
|
unless (new_endpoint = @new[:endpoints][path])
|
data/lib/graphiti/sideload.rb
CHANGED
|
@@ -137,11 +137,16 @@ module Graphiti
|
|
|
137
137
|
end
|
|
138
138
|
|
|
139
139
|
def link_extra_fields
|
|
140
|
+
return unless context&.respond_to?(:params)
|
|
141
|
+
|
|
140
142
|
extra_fields_name = [association_name, resource.type].find { |param|
|
|
141
143
|
context.params.dig(:extra_fields, param)
|
|
142
144
|
}
|
|
143
145
|
|
|
144
|
-
|
|
146
|
+
if extra_fields_name
|
|
147
|
+
extra_fields = context.params.dig(:extra_fields, extra_fields_name)
|
|
148
|
+
{resource.type => extra_fields}
|
|
149
|
+
end
|
|
145
150
|
end
|
|
146
151
|
|
|
147
152
|
# The parent resource is a remote,
|
|
@@ -16,13 +16,11 @@ module Graphiti
|
|
|
16
16
|
|
|
17
17
|
if @name == :id
|
|
18
18
|
@serializer.id(&proc)
|
|
19
|
-
elsif @attr[:proc]
|
|
19
|
+
elsif @attr[:proc] ||
|
|
20
|
+
!previously_applied? ||
|
|
21
|
+
previously_applied_via_resource?
|
|
20
22
|
@serializer.send(_method, @name, serializer_options, &proc)
|
|
21
|
-
|
|
22
|
-
@serializer.send(_method, @name, serializer_options, &proc)
|
|
23
|
-
elsif @serializer.send(applied_method).include?(@name)
|
|
24
|
-
@serializer.field_condition_blocks[@name] = guard if guard?
|
|
25
|
-
else
|
|
23
|
+
else # Previously applied via explicit serializer, so wrap it
|
|
26
24
|
inner = @serializer.attribute_blocks.delete(@name)
|
|
27
25
|
wrapped = wrap_proc(inner)
|
|
28
26
|
@serializer.send(_method, @name, serializer_options, &wrapped)
|
|
@@ -34,6 +32,14 @@ module Graphiti
|
|
|
34
32
|
|
|
35
33
|
private
|
|
36
34
|
|
|
35
|
+
def previously_applied?
|
|
36
|
+
@serializer.attribute_blocks[@name].present?
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def previously_applied_via_resource?
|
|
40
|
+
@serializer.send(applied_method).include?(@name)
|
|
41
|
+
end
|
|
42
|
+
|
|
37
43
|
def previously_guarded?
|
|
38
44
|
@serializer.field_condition_blocks[@name]
|
|
39
45
|
end
|
data/lib/graphiti/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: graphiti
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.2.
|
|
4
|
+
version: 1.2.40
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Lee Richmond
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2021-
|
|
11
|
+
date: 2021-04-13 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: jsonapi-serializable
|