graphiti 1.0.alpha.1 → 1.0.alpha.4
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/.travis.yml +0 -8
- data/README.md +2 -72
- data/bin/console +1 -1
- data/exe/graphiti +5 -0
- data/graphiti.gemspec +2 -2
- data/lib/generators/jsonapi/resource_generator.rb +1 -1
- data/lib/generators/jsonapi/templates/application_resource.rb.erb +0 -2
- data/lib/graphiti.rb +17 -1
- data/lib/graphiti/adapters/abstract.rb +32 -0
- data/lib/graphiti/adapters/active_record/base.rb +8 -0
- data/lib/graphiti/adapters/active_record/many_to_many_sideload.rb +2 -9
- data/lib/graphiti/cli.rb +45 -0
- data/lib/graphiti/configuration.rb +12 -0
- data/lib/graphiti/context.rb +1 -0
- data/lib/graphiti/errors.rb +105 -3
- data/lib/graphiti/filter_operators.rb +13 -3
- data/lib/graphiti/query.rb +8 -0
- data/lib/graphiti/rails.rb +1 -1
- data/lib/graphiti/railtie.rb +21 -2
- data/lib/graphiti/renderer.rb +2 -1
- data/lib/graphiti/resource.rb +11 -2
- data/lib/graphiti/resource/configuration.rb +1 -0
- data/lib/graphiti/resource/dsl.rb +4 -3
- data/lib/graphiti/resource/interface.rb +15 -0
- data/lib/graphiti/resource/links.rb +92 -0
- data/lib/graphiti/resource/polymorphism.rb +1 -0
- data/lib/graphiti/resource/sideloading.rb +13 -5
- data/lib/graphiti/resource_proxy.rb +1 -1
- data/lib/graphiti/schema.rb +169 -0
- data/lib/graphiti/schema_diff.rb +174 -0
- data/lib/graphiti/scoping/filter.rb +1 -1
- data/lib/graphiti/sideload.rb +47 -18
- data/lib/graphiti/sideload/belongs_to.rb +5 -1
- data/lib/graphiti/sideload/has_many.rb +5 -1
- data/lib/graphiti/sideload/many_to_many.rb +6 -2
- data/lib/graphiti/sideload/polymorphic_belongs_to.rb +3 -1
- data/lib/graphiti/types.rb +39 -17
- data/lib/graphiti/util/class.rb +22 -0
- data/lib/graphiti/util/hash.rb +16 -0
- data/lib/graphiti/util/hooks.rb +2 -2
- data/lib/graphiti/util/link.rb +48 -0
- data/lib/graphiti/util/serializer_relationships.rb +94 -0
- data/lib/graphiti/version.rb +1 -1
- metadata +16 -7
@@ -0,0 +1,174 @@
|
|
1
|
+
module Graphiti
|
2
|
+
class SchemaDiff
|
3
|
+
def initialize(old, new)
|
4
|
+
@old = old.deep_symbolize_keys
|
5
|
+
@new = new.deep_symbolize_keys
|
6
|
+
@errors = []
|
7
|
+
end
|
8
|
+
|
9
|
+
def compare
|
10
|
+
compare_each if @old != @new
|
11
|
+
@errors
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def compare_each
|
17
|
+
compare_resources
|
18
|
+
compare_endpoints
|
19
|
+
compare_types
|
20
|
+
end
|
21
|
+
|
22
|
+
def compare_resources
|
23
|
+
@old[:resources].each_with_index do |r, index|
|
24
|
+
new_resource = @new[:resources].find { |n| n[:name] == r[:name] }
|
25
|
+
compare_resource(r, new_resource) do
|
26
|
+
compare_attributes(r, new_resource)
|
27
|
+
compare_extra_attributes(r, new_resource)
|
28
|
+
compare_filters(r, new_resource)
|
29
|
+
compare_relationships(r, new_resource)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def compare_resource(old_resource, new_resource)
|
35
|
+
unless new_resource
|
36
|
+
@errors << "#{old_resource[:name]} was removed."
|
37
|
+
return
|
38
|
+
end
|
39
|
+
|
40
|
+
if old_resource[:type] != new_resource[:type]
|
41
|
+
@errors << "#{old_resource[:name]} changed type from #{old_resource[:type].inspect} to #{new_resource[:type].inspect}."
|
42
|
+
end
|
43
|
+
yield
|
44
|
+
end
|
45
|
+
|
46
|
+
def compare_attributes(old_resource, new_resource)
|
47
|
+
old_resource[:attributes].each_pair do |name, old_att|
|
48
|
+
unless new_att = new_resource[:attributes][name]
|
49
|
+
@errors << "#{old_resource[:name]}: attribute #{name.inspect} was removed."
|
50
|
+
next
|
51
|
+
end
|
52
|
+
|
53
|
+
compare_attribute(old_resource[:name], name, old_att, new_att)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def compare_relationships(old_resource, new_resource)
|
58
|
+
old_resource[:relationships].each_pair do |name, old_rel|
|
59
|
+
unless new_rel = new_resource[:relationships][name]
|
60
|
+
@errors << "#{old_resource[:name]}: relationship #{name.inspect} was removed."
|
61
|
+
next
|
62
|
+
end
|
63
|
+
|
64
|
+
if new_rel[:resource] != old_rel[:resource]
|
65
|
+
@errors << "#{old_resource[:name]}: relationship #{name.inspect} changed resource from #{old_rel[:resource]} to #{new_rel[:resource]}."
|
66
|
+
end
|
67
|
+
|
68
|
+
if new_rel[:type] != old_rel[:type]
|
69
|
+
@errors << "#{old_resource[:name]}: relationship #{name.inspect} changed type from #{old_rel[:type].inspect} to #{new_rel[:type].inspect}."
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def compare_extra_attributes(old_resource, new_resource)
|
75
|
+
old_resource[:extra_attributes].each_pair do |name, old_att|
|
76
|
+
unless new_att = new_resource[:extra_attributes][name]
|
77
|
+
@errors << "#{old_resource[:name]}: extra attribute #{name.inspect} was removed."
|
78
|
+
next
|
79
|
+
end
|
80
|
+
|
81
|
+
compare_attribute(old_resource[:name], name, old_att, new_att, extra: true)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def compare_filters(old_resource, new_resource)
|
86
|
+
old_resource[:filters].each_pair do |name, old_filter|
|
87
|
+
unless new_filter = new_resource[:filters][name]
|
88
|
+
@errors << "#{old_resource[:name]}: filter #{name.inspect} was removed."
|
89
|
+
next
|
90
|
+
end
|
91
|
+
|
92
|
+
if new_filter[:type] != old_filter[:type]
|
93
|
+
@errors << "#{old_resource[:name]}: filter #{name.inspect} changed type from #{old_filter[:type].inspect} to #{new_filter[:type].inspect}."
|
94
|
+
next
|
95
|
+
end
|
96
|
+
|
97
|
+
if (diff = old_filter[:operators] - new_filter[:operators]).length > 0
|
98
|
+
diff.each do |op|
|
99
|
+
@errors << "#{old_resource[:name]}: filter #{name.inspect} removed operator #{op.inspect}."
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
if new_filter[:required] && !old_filter[:required]
|
104
|
+
@errors << "#{old_resource[:name]}: filter #{name.inspect} went from optional to required."
|
105
|
+
end
|
106
|
+
|
107
|
+
if new_filter[:guard] && !old_filter[:guard]
|
108
|
+
@errors << "#{old_resource[:name]}: filter #{name.inspect} went from unguarded to guarded."
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def compare_endpoints
|
114
|
+
@old[:endpoints].each_pair do |path, old_endpoint|
|
115
|
+
unless new_endpoint = @new[:endpoints][path]
|
116
|
+
@errors << "Endpoint \"#{path}\" was removed."
|
117
|
+
next
|
118
|
+
end
|
119
|
+
|
120
|
+
old_endpoint[:actions].each_pair do |name, old_action|
|
121
|
+
unless new_action = new_endpoint[:actions][name]
|
122
|
+
@errors << "Endpoint \"#{path}\" removed action #{name.inspect}."
|
123
|
+
next
|
124
|
+
end
|
125
|
+
|
126
|
+
if new_action[:sideload_whitelist] && !old_action[:sideload_whitelist]
|
127
|
+
@errors << "Endpoint \"#{path}\" added sideload whitelist."
|
128
|
+
end
|
129
|
+
|
130
|
+
if new_action[:sideload_whitelist]
|
131
|
+
if new_action[:sideload_whitelist] != old_action[:sideload_whitelist]
|
132
|
+
removal = Util::Hash.include_removed? \
|
133
|
+
new_action[:sideload_whitelist], old_action[:sideload_whitelist]
|
134
|
+
if removal
|
135
|
+
@errors << "Endpoint \"#{path}\" had incompatible sideload whitelist. Was #{old_action[:sideload_whitelist].inspect}, now #{new_action[:sideload_whitelist].inspect}."
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def compare_types
|
144
|
+
@old[:types].each_pair do |name, old_type|
|
145
|
+
unless new_type = @new[:types][name]
|
146
|
+
@errors << "Type #{name.inspect} was removed."
|
147
|
+
next
|
148
|
+
end
|
149
|
+
|
150
|
+
if new_type[:kind] != old_type[:kind]
|
151
|
+
@errors << "Type #{name.inspect} changed kind from #{old_type[:kind].inspect} to #{new_type[:kind].inspect}."
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def compare_attribute(resource_name, att_name, old_att, new_att, extra: false)
|
157
|
+
prefix = extra ? "extra attribute" : "attribute"
|
158
|
+
|
159
|
+
if old_att[:type] != new_att[:type]
|
160
|
+
@errors << "#{resource_name}: #{prefix} #{att_name.inspect} changed type from #{old_att[:type].inspect} to #{new_att[:type].inspect}."
|
161
|
+
end
|
162
|
+
|
163
|
+
[:readable, :writable, :sortable].each do |flag|
|
164
|
+
if [true, 'guarded'].include?(old_att[flag]) && new_att[flag] == false
|
165
|
+
@errors << "#{resource_name}: #{prefix} #{att_name.inspect} changed flag #{flag.inspect} from #{old_att[flag].inspect} to #{new_att[flag].inspect}."
|
166
|
+
end
|
167
|
+
|
168
|
+
if new_att[flag] == 'guarded' && old_att[flag] == true
|
169
|
+
@errors << "#{resource_name}: #{prefix} #{att_name.inspect} changed flag #{flag.inspect} from #{old_att[flag].inspect} to #{new_att[flag].inspect}."
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
@@ -44,7 +44,7 @@ module Graphiti
|
|
44
44
|
def filter_scope(filter, operator, value)
|
45
45
|
operator = operator.to_s.gsub('!', 'not_').to_sym
|
46
46
|
|
47
|
-
if custom_scope = filter.values
|
47
|
+
if custom_scope = filter.values[0][:operators][operator]
|
48
48
|
custom_scope.call(@scope, value, resource.context)
|
49
49
|
else
|
50
50
|
filter_via_adapter(filter, operator, value)
|
data/lib/graphiti/sideload.rb
CHANGED
@@ -9,13 +9,15 @@ module Graphiti
|
|
9
9
|
:foreign_key,
|
10
10
|
:primary_key,
|
11
11
|
:parent,
|
12
|
-
:group_name
|
12
|
+
:group_name,
|
13
|
+
:link
|
13
14
|
|
14
15
|
class_attribute :scope_proc,
|
15
16
|
:assign_proc,
|
16
17
|
:assign_each_proc,
|
17
18
|
:params_proc,
|
18
|
-
:pre_load_proc
|
19
|
+
:pre_load_proc,
|
20
|
+
:link_proc
|
19
21
|
|
20
22
|
def initialize(name, opts)
|
21
23
|
@name = name
|
@@ -28,6 +30,7 @@ module Graphiti
|
|
28
30
|
@readable = opts[:readable]
|
29
31
|
@writable = opts[:writable]
|
30
32
|
@as = opts[:as]
|
33
|
+
@link = opts[:link]
|
31
34
|
|
32
35
|
# polymorphic-specific
|
33
36
|
@group_name = opts[:group_name]
|
@@ -36,6 +39,8 @@ module Graphiti
|
|
36
39
|
if polymorphic_child?
|
37
40
|
parent.resource.polymorphic << resource_class
|
38
41
|
end
|
42
|
+
|
43
|
+
check! if defined?(::Rails)
|
39
44
|
end
|
40
45
|
|
41
46
|
def self.scope(&blk)
|
@@ -58,6 +63,30 @@ module Graphiti
|
|
58
63
|
self.pre_load_proc = blk
|
59
64
|
end
|
60
65
|
|
66
|
+
def self.link(&blk)
|
67
|
+
self.link_proc = blk
|
68
|
+
end
|
69
|
+
|
70
|
+
def check!
|
71
|
+
case type
|
72
|
+
when :has_many, :has_one
|
73
|
+
unless resource.filters[foreign_key]
|
74
|
+
raise Errors::MissingSideloadFilter.new parent_resource_class,
|
75
|
+
self, foreign_key
|
76
|
+
end
|
77
|
+
when :belongs_to
|
78
|
+
unless resource.filters[primary_key]
|
79
|
+
raise Errors::MissingSideloadFilter.new parent_resource_class,
|
80
|
+
self, primary_key
|
81
|
+
end
|
82
|
+
when :many_to_many
|
83
|
+
unless resource.filters[true_foreign_key]
|
84
|
+
raise Errors::MissingSideloadFilter.new parent_resource_class,
|
85
|
+
self, true_foreign_key
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
61
90
|
def readable?
|
62
91
|
!!@readable
|
63
92
|
end
|
@@ -66,6 +95,16 @@ module Graphiti
|
|
66
95
|
!!@writable
|
67
96
|
end
|
68
97
|
|
98
|
+
def link?
|
99
|
+
return true if link_proc
|
100
|
+
|
101
|
+
if @link.nil?
|
102
|
+
!!@parent_resource_class.autolink
|
103
|
+
else
|
104
|
+
!!@link
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
69
108
|
def polymorphic_parent?
|
70
109
|
resource.polymorphic?
|
71
110
|
end
|
@@ -116,7 +155,7 @@ module Graphiti
|
|
116
155
|
|
117
156
|
def load(parents, query)
|
118
157
|
params = load_params(parents, query)
|
119
|
-
params_proc.call(params, parents
|
158
|
+
params_proc.call(params, parents) if params_proc
|
120
159
|
opts = load_options(parents, query)
|
121
160
|
proxy = resource.class._all(params, opts, base_scope)
|
122
161
|
pre_load_proc.call(proxy) if pre_load_proc
|
@@ -157,8 +196,7 @@ module Graphiti
|
|
157
196
|
end
|
158
197
|
|
159
198
|
def resolve(parents, query)
|
160
|
-
|
161
|
-
if self.class.scope_proc || type == :many_to_many
|
199
|
+
if self.class.scope_proc
|
162
200
|
sideload_scope = fire_scope(parents)
|
163
201
|
sideload_scope = Scope.new sideload_scope,
|
164
202
|
resource,
|
@@ -261,21 +299,12 @@ module Graphiti
|
|
261
299
|
end
|
262
300
|
end
|
263
301
|
|
264
|
-
def
|
265
|
-
|
266
|
-
split = namespace.split('::')
|
267
|
-
split[0,split.length-1].join('::')
|
302
|
+
def infer_resource_class
|
303
|
+
Util::Class.infer_resource_class(parent_resource.class, name)
|
268
304
|
end
|
269
305
|
|
270
|
-
def
|
271
|
-
|
272
|
-
inferred_name = "#{name.to_s.singularize.classify}Resource"
|
273
|
-
klass = "#{namespace}::#{inferred_name}".safe_constantize
|
274
|
-
klass ||= inferred_name.safe_constantize
|
275
|
-
unless klass
|
276
|
-
raise Errors::ResourceNotFound.new(parent_resource, name)
|
277
|
-
end
|
278
|
-
klass
|
306
|
+
def namespace_for(klass)
|
307
|
+
Util::Class.namespace_for(klass)
|
279
308
|
end
|
280
309
|
end
|
281
310
|
end
|
@@ -6,10 +6,14 @@ class Graphiti::Sideload::BelongsTo < Graphiti::Sideload
|
|
6
6
|
def load_params(parents, query)
|
7
7
|
query.to_hash.tap do |hash|
|
8
8
|
hash[:filter] ||= {}
|
9
|
-
hash[:filter]
|
9
|
+
hash[:filter].merge!(base_filter(parents))
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
+
def base_filter(parents)
|
14
|
+
{ primary_key => ids_for_parents(parents).join(',') }
|
15
|
+
end
|
16
|
+
|
13
17
|
def assign_each(parent, children)
|
14
18
|
children.find { |c| c.send(primary_key) == parent.send(foreign_key) }
|
15
19
|
end
|
@@ -6,10 +6,14 @@ class Graphiti::Sideload::HasMany < Graphiti::Sideload
|
|
6
6
|
def load_params(parents, query)
|
7
7
|
query.to_hash.tap do |hash|
|
8
8
|
hash[:filter] ||= {}
|
9
|
-
hash[:filter]
|
9
|
+
hash[:filter].merge!(base_filter(parents))
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
+
def base_filter(parents)
|
14
|
+
{ foreign_key => ids_for_parents(parents).join(',') }
|
15
|
+
end
|
16
|
+
|
13
17
|
def assign_each(parent, children)
|
14
18
|
children.select { |c| c.send(foreign_key) == parent.send(primary_key) }
|
15
19
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
class Graphiti::Sideload::ManyToMany < Graphiti::Sideload
|
1
|
+
class Graphiti::Sideload::ManyToMany < Graphiti::Sideload::HasMany
|
2
2
|
def type
|
3
3
|
:many_to_many
|
4
4
|
end
|
@@ -11,8 +11,12 @@ class Graphiti::Sideload::ManyToMany < Graphiti::Sideload
|
|
11
11
|
foreign_key.values.first
|
12
12
|
end
|
13
13
|
|
14
|
+
def base_filter(parents)
|
15
|
+
{ true_foreign_key => ids_for_parents(parents).join(',') }
|
16
|
+
end
|
17
|
+
|
14
18
|
def infer_foreign_key
|
15
|
-
raise 'You must explicitly pass :foreign_key for many-to-many
|
19
|
+
raise 'You must explicitly pass :foreign_key for many-to-many relationships, or override in subclass to return a hash.'
|
16
20
|
end
|
17
21
|
|
18
22
|
def assign_each(parent, children)
|
@@ -23,12 +23,14 @@ class Graphiti::Sideload::PolymorphicBelongsTo < Graphiti::Sideload::BelongsTo
|
|
23
23
|
def on(name, &blk)
|
24
24
|
group = Group.new(name)
|
25
25
|
@groups << group
|
26
|
-
group.belongs_to(name.to_s.underscore.to_sym)
|
27
26
|
group
|
28
27
|
end
|
29
28
|
|
30
29
|
def apply(sideload, resource_class)
|
31
30
|
@groups.each do |group|
|
31
|
+
if group.calls.empty?
|
32
|
+
group.belongs_to(group.name.to_s.underscore.to_sym)
|
33
|
+
end
|
32
34
|
group.calls.each do |call|
|
33
35
|
args = call[1]
|
34
36
|
opts = args.extract_options!
|
data/lib/graphiti/types.rb
CHANGED
@@ -72,6 +72,8 @@ module Graphiti
|
|
72
72
|
Dry::Types['params.hash'][input].deep_symbolize_keys
|
73
73
|
end
|
74
74
|
|
75
|
+
REQUIRED_KEYS = [:params, :read, :write, :kind, :description]
|
76
|
+
|
75
77
|
def self.map
|
76
78
|
@map ||= begin
|
77
79
|
hash = {
|
@@ -79,52 +81,72 @@ module Graphiti
|
|
79
81
|
canonical_name: :integer,
|
80
82
|
params: Dry::Types['coercible.integer'],
|
81
83
|
read: Dry::Types['coercible.string'],
|
82
|
-
write: Dry::Types['coercible.integer']
|
84
|
+
write: Dry::Types['coercible.integer'],
|
85
|
+
kind: 'scalar',
|
86
|
+
description: 'Base Type. Query/persist as integer, render as string.'
|
83
87
|
},
|
84
88
|
string: {
|
85
89
|
params: Dry::Types['coercible.string'],
|
86
90
|
read: Dry::Types['coercible.string'],
|
87
|
-
write: Dry::Types['coercible.string']
|
91
|
+
write: Dry::Types['coercible.string'],
|
92
|
+
kind: 'scalar',
|
93
|
+
description: 'Base Type.'
|
88
94
|
},
|
89
95
|
integer: {
|
90
96
|
params: PresentInteger,
|
91
97
|
read: Integer,
|
92
|
-
write: Integer
|
98
|
+
write: Integer,
|
99
|
+
kind: 'scalar',
|
100
|
+
description: 'Base Type.'
|
93
101
|
},
|
94
102
|
big_decimal: {
|
95
103
|
params: ParamDecimal,
|
96
104
|
read: Dry::Types['json.decimal'],
|
97
|
-
write: Dry::Types['json.decimal']
|
105
|
+
write: Dry::Types['json.decimal'],
|
106
|
+
kind: 'scalar',
|
107
|
+
description: 'Base Type.'
|
98
108
|
},
|
99
109
|
float: {
|
100
110
|
params: Dry::Types['coercible.float'],
|
101
111
|
read: Float,
|
102
|
-
write: Float
|
112
|
+
write: Float,
|
113
|
+
kind: 'scalar',
|
114
|
+
description: 'Base Type.'
|
103
115
|
},
|
104
116
|
boolean: {
|
105
117
|
params: PresentBool,
|
106
118
|
read: Bool,
|
107
|
-
write: Bool
|
119
|
+
write: Bool,
|
120
|
+
kind: 'scalar',
|
121
|
+
description: 'Base Type.'
|
108
122
|
},
|
109
123
|
date: {
|
110
124
|
params: PresentDate,
|
111
125
|
read: Date,
|
112
|
-
write: Date
|
126
|
+
write: Date,
|
127
|
+
kind: 'scalar',
|
128
|
+
description: 'Base Type.'
|
113
129
|
},
|
114
130
|
datetime: {
|
115
131
|
params: PresentParamsDateTime,
|
116
132
|
read: ReadDateTime,
|
117
|
-
write: WriteDateTime
|
133
|
+
write: WriteDateTime,
|
134
|
+
kind: 'scalar',
|
135
|
+
description: 'Base Type.'
|
118
136
|
},
|
119
137
|
hash: {
|
120
138
|
params: PresentParamsHash,
|
121
139
|
read: Dry::Types['strict.hash'],
|
122
|
-
write: Dry::Types['strict.hash']
|
140
|
+
write: Dry::Types['strict.hash'],
|
141
|
+
kind: 'record',
|
142
|
+
description: 'Base Type.'
|
123
143
|
},
|
124
144
|
array: {
|
125
145
|
params: Dry::Types['strict.array'],
|
126
146
|
read: Dry::Types['strict.array'],
|
127
|
-
write: Dry::Types['strict.array']
|
147
|
+
write: Dry::Types['strict.array'],
|
148
|
+
kind: 'array',
|
149
|
+
description: 'Base Type.'
|
128
150
|
}
|
129
151
|
}
|
130
152
|
|
@@ -134,12 +156,16 @@ module Graphiti
|
|
134
156
|
|
135
157
|
arrays = {}
|
136
158
|
hash.each_pair do |name, map|
|
159
|
+
next if [:boolean, :hash, :array].include?(name)
|
160
|
+
|
137
161
|
arrays[:"array_of_#{name.to_s.pluralize}"] = {
|
138
162
|
canonical_name: name,
|
139
163
|
params: Dry::Types['strict.array'].of(map[:params]),
|
140
164
|
read: Dry::Types['strict.array'].of(map[:read]),
|
141
165
|
test: Dry::Types['strict.array'].of(map[:test]),
|
142
|
-
write: Dry::Types['strict.array'].of(map[:write])
|
166
|
+
write: Dry::Types['strict.array'].of(map[:write]),
|
167
|
+
kind: 'array',
|
168
|
+
description: 'Base Type.'
|
143
169
|
}
|
144
170
|
end
|
145
171
|
hash.merge!(arrays)
|
@@ -153,12 +179,8 @@ module Graphiti
|
|
153
179
|
end
|
154
180
|
|
155
181
|
def self.[]=(key, value)
|
156
|
-
unless value.is_a?(Hash)
|
157
|
-
|
158
|
-
read: value,
|
159
|
-
params: value,
|
160
|
-
test: value
|
161
|
-
}
|
182
|
+
unless value.is_a?(Hash) && (REQUIRED_KEYS - value.keys).length.zero?
|
183
|
+
raise Errors::InvalidType.new(key, value)
|
162
184
|
end
|
163
185
|
map[key.to_sym] = value
|
164
186
|
end
|