nxt_schema 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +3 -3
- data/README.md +80 -38
- data/lib/nxt_schema.rb +17 -17
- data/lib/nxt_schema/dsl.rb +7 -7
- data/lib/nxt_schema/{application.rb → node.rb} +1 -1
- data/lib/nxt_schema/node/any_of.rb +21 -33
- data/lib/nxt_schema/node/base.rb +70 -171
- data/lib/nxt_schema/node/collection.rb +43 -8
- data/lib/nxt_schema/{application → node}/error_store.rb +5 -5
- data/lib/nxt_schema/{application → node}/errors/schema_error.rb +1 -1
- data/lib/nxt_schema/{application → node}/errors/validation_error.rb +1 -1
- data/lib/nxt_schema/node/leaf.rb +7 -5
- data/lib/nxt_schema/node/schema.rb +101 -8
- data/lib/nxt_schema/template/any_of.rb +50 -0
- data/lib/nxt_schema/template/base.rb +218 -0
- data/lib/nxt_schema/template/collection.rb +23 -0
- data/lib/nxt_schema/{node → template}/has_sub_nodes.rb +16 -10
- data/lib/nxt_schema/template/leaf.rb +13 -0
- data/lib/nxt_schema/{node → template}/maybe_evaluator.rb +1 -1
- data/lib/nxt_schema/{node → template}/on_evaluator.rb +1 -1
- data/lib/nxt_schema/template/schema.rb +22 -0
- data/lib/nxt_schema/{node → template}/sub_nodes.rb +1 -1
- data/lib/nxt_schema/{node → template}/type_resolver.rb +2 -2
- data/lib/nxt_schema/{node → template}/type_system_resolver.rb +1 -1
- data/lib/nxt_schema/version.rb +1 -1
- metadata +17 -17
- data/lib/nxt_schema/application/any_of.rb +0 -40
- data/lib/nxt_schema/application/base.rb +0 -116
- data/lib/nxt_schema/application/collection.rb +0 -57
- data/lib/nxt_schema/application/leaf.rb +0 -15
- data/lib/nxt_schema/application/schema.rb +0 -114
data/lib/nxt_schema/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nxt_schema
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andreas Robecke
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-12-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -155,32 +155,32 @@ files:
|
|
155
155
|
- bin/console
|
156
156
|
- bin/setup
|
157
157
|
- lib/nxt_schema.rb
|
158
|
-
- lib/nxt_schema/application.rb
|
159
|
-
- lib/nxt_schema/application/any_of.rb
|
160
|
-
- lib/nxt_schema/application/base.rb
|
161
|
-
- lib/nxt_schema/application/collection.rb
|
162
|
-
- lib/nxt_schema/application/error_store.rb
|
163
|
-
- lib/nxt_schema/application/errors/schema_error.rb
|
164
|
-
- lib/nxt_schema/application/errors/validation_error.rb
|
165
|
-
- lib/nxt_schema/application/leaf.rb
|
166
|
-
- lib/nxt_schema/application/schema.rb
|
167
158
|
- lib/nxt_schema/callable.rb
|
168
159
|
- lib/nxt_schema/dsl.rb
|
169
160
|
- lib/nxt_schema/error.rb
|
170
161
|
- lib/nxt_schema/errors/invalid.rb
|
171
162
|
- lib/nxt_schema/errors/invalid_options.rb
|
172
163
|
- lib/nxt_schema/missing_input.rb
|
164
|
+
- lib/nxt_schema/node.rb
|
173
165
|
- lib/nxt_schema/node/any_of.rb
|
174
166
|
- lib/nxt_schema/node/base.rb
|
175
167
|
- lib/nxt_schema/node/collection.rb
|
176
|
-
- lib/nxt_schema/node/
|
168
|
+
- lib/nxt_schema/node/error_store.rb
|
169
|
+
- lib/nxt_schema/node/errors/schema_error.rb
|
170
|
+
- lib/nxt_schema/node/errors/validation_error.rb
|
177
171
|
- lib/nxt_schema/node/leaf.rb
|
178
|
-
- lib/nxt_schema/node/maybe_evaluator.rb
|
179
|
-
- lib/nxt_schema/node/on_evaluator.rb
|
180
172
|
- lib/nxt_schema/node/schema.rb
|
181
|
-
- lib/nxt_schema/
|
182
|
-
- lib/nxt_schema/
|
183
|
-
- lib/nxt_schema/
|
173
|
+
- lib/nxt_schema/template/any_of.rb
|
174
|
+
- lib/nxt_schema/template/base.rb
|
175
|
+
- lib/nxt_schema/template/collection.rb
|
176
|
+
- lib/nxt_schema/template/has_sub_nodes.rb
|
177
|
+
- lib/nxt_schema/template/leaf.rb
|
178
|
+
- lib/nxt_schema/template/maybe_evaluator.rb
|
179
|
+
- lib/nxt_schema/template/on_evaluator.rb
|
180
|
+
- lib/nxt_schema/template/schema.rb
|
181
|
+
- lib/nxt_schema/template/sub_nodes.rb
|
182
|
+
- lib/nxt_schema/template/type_resolver.rb
|
183
|
+
- lib/nxt_schema/template/type_system_resolver.rb
|
184
184
|
- lib/nxt_schema/types.rb
|
185
185
|
- lib/nxt_schema/validators/attribute.rb
|
186
186
|
- lib/nxt_schema/validators/equal_to.rb
|
@@ -1,40 +0,0 @@
|
|
1
|
-
module NxtSchema
|
2
|
-
module Application
|
3
|
-
class AnyOf < Application::Base
|
4
|
-
def valid?
|
5
|
-
valid_application.present?
|
6
|
-
end
|
7
|
-
|
8
|
-
def call
|
9
|
-
# TODO: We should check that this is not empty!
|
10
|
-
child_applications.map(&:call)
|
11
|
-
|
12
|
-
if valid?
|
13
|
-
self.output = valid_application.output
|
14
|
-
else
|
15
|
-
child_applications.each do |application|
|
16
|
-
merge_errors(application)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
self
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
|
25
|
-
delegate :[], to: :child_applications
|
26
|
-
|
27
|
-
def valid_application
|
28
|
-
child_applications.find(&:valid?)
|
29
|
-
end
|
30
|
-
|
31
|
-
def child_applications
|
32
|
-
@child_applications ||= nodes.map { |node| node.build_application(input: input, context: context, parent: self) }
|
33
|
-
end
|
34
|
-
|
35
|
-
def nodes
|
36
|
-
@nodes ||= node.sub_nodes.values
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
@@ -1,116 +0,0 @@
|
|
1
|
-
module NxtSchema
|
2
|
-
module Application
|
3
|
-
class Base
|
4
|
-
def initialize(node:, input: MissingInput.new, parent:, context:, error_key:)
|
5
|
-
@node = node
|
6
|
-
@input = input
|
7
|
-
@parent = parent
|
8
|
-
@output = nil
|
9
|
-
@error_key = error_key
|
10
|
-
@context = context || parent&.context
|
11
|
-
@applied = false
|
12
|
-
@applied_nodes = parent&.applied_nodes || []
|
13
|
-
@is_root = parent.nil?
|
14
|
-
@root = parent.nil? ? self : parent.root
|
15
|
-
@errors = ErrorStore.new(self)
|
16
|
-
@locale = node.options.fetch(:locale) { parent&.locale || 'en' }.to_s
|
17
|
-
|
18
|
-
@index = error_key
|
19
|
-
resolve_error_key(error_key)
|
20
|
-
end
|
21
|
-
|
22
|
-
attr_accessor :output, :node, :input
|
23
|
-
attr_reader :parent, :context, :error_key, :applied, :applied_nodes, :root, :errors, :locale, :index
|
24
|
-
|
25
|
-
def call
|
26
|
-
raise NotImplementedError, 'Implement this in our sub class'
|
27
|
-
end
|
28
|
-
|
29
|
-
delegate :name, :options, to: :node
|
30
|
-
|
31
|
-
def root?
|
32
|
-
@is_root
|
33
|
-
end
|
34
|
-
|
35
|
-
def valid?
|
36
|
-
errors.empty?
|
37
|
-
end
|
38
|
-
|
39
|
-
def add_error(error)
|
40
|
-
errors.add_validation_error(message: error)
|
41
|
-
end
|
42
|
-
|
43
|
-
def add_schema_error(error)
|
44
|
-
errors.add_schema_error(message: error)
|
45
|
-
end
|
46
|
-
|
47
|
-
def merge_errors(application)
|
48
|
-
errors.merge_errors(application)
|
49
|
-
end
|
50
|
-
|
51
|
-
def run_validations
|
52
|
-
return false unless applied?
|
53
|
-
|
54
|
-
node.validations.each do |validation|
|
55
|
-
args = [self, input]
|
56
|
-
validation.call(*args.take(validation.arity))
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def up(levels = 1)
|
61
|
-
0.upto(levels - 1).inject(self) do |acc, _|
|
62
|
-
parent = acc.send(:parent)
|
63
|
-
break acc unless parent
|
64
|
-
|
65
|
-
parent
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
private
|
70
|
-
|
71
|
-
attr_writer :applied, :root
|
72
|
-
|
73
|
-
def coerce_input
|
74
|
-
output = input.is_a?(MissingInput) && node.omnipresent? ? input : node.type[input]
|
75
|
-
self.output = output
|
76
|
-
|
77
|
-
rescue Dry::Types::CoercionError => error
|
78
|
-
add_schema_error(error.message)
|
79
|
-
end
|
80
|
-
|
81
|
-
def apply_on_evaluators
|
82
|
-
node.on_evaluators.each { |evaluator| evaluator.call(input, self, context) { |result| self.input = result } }
|
83
|
-
end
|
84
|
-
|
85
|
-
def maybe_evaluator_applies?
|
86
|
-
@maybe_evaluator_applies ||= node.maybe_evaluators.inject(false) do |acc, evaluator|
|
87
|
-
result = (acc || evaluator.call(input, self, context))
|
88
|
-
|
89
|
-
if result
|
90
|
-
self.output = input
|
91
|
-
break true
|
92
|
-
else
|
93
|
-
false
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
def register_as_applied_when_valid
|
99
|
-
return unless valid?
|
100
|
-
|
101
|
-
self.applied = true
|
102
|
-
applied_nodes << self
|
103
|
-
end
|
104
|
-
|
105
|
-
def resolve_error_key(key)
|
106
|
-
parts = [parent&.error_key].compact
|
107
|
-
parts << (key.present? ? "#{node.name}[#{key}]" : node.name)
|
108
|
-
@error_key = parts.join('.')
|
109
|
-
end
|
110
|
-
|
111
|
-
def applied?
|
112
|
-
@applied
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
@@ -1,57 +0,0 @@
|
|
1
|
-
module NxtSchema
|
2
|
-
module Application
|
3
|
-
class Collection < Application::Base
|
4
|
-
def call
|
5
|
-
apply_on_evaluators
|
6
|
-
child_applications # build applications here so we can access them even when invalid
|
7
|
-
return self if maybe_evaluator_applies?
|
8
|
-
|
9
|
-
coerce_input
|
10
|
-
validate_filled
|
11
|
-
return self unless valid?
|
12
|
-
|
13
|
-
child_applications.each_with_index do |item, index|
|
14
|
-
current_application = item.call
|
15
|
-
|
16
|
-
if !current_application.valid?
|
17
|
-
merge_errors(current_application)
|
18
|
-
else
|
19
|
-
output[index] = current_application.output
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
register_as_applied_when_valid
|
24
|
-
run_validations
|
25
|
-
|
26
|
-
self
|
27
|
-
end
|
28
|
-
|
29
|
-
delegate :[], to: :child_applications
|
30
|
-
|
31
|
-
private
|
32
|
-
|
33
|
-
def validate_filled
|
34
|
-
add_schema_error('is not allowed to be empty') if input.blank? && !maybe_evaluator_applies?
|
35
|
-
end
|
36
|
-
|
37
|
-
def child_applications
|
38
|
-
@child_applications ||= begin
|
39
|
-
return [] unless input.respond_to?(:each_with_index)
|
40
|
-
|
41
|
-
input.each_with_index.map do |item, index|
|
42
|
-
build_child_application(item, index)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
end
|
47
|
-
|
48
|
-
def build_child_application(item, error_key)
|
49
|
-
sub_node.build_application(input: item, context: context, parent: self, error_key: error_key)
|
50
|
-
end
|
51
|
-
|
52
|
-
def sub_node
|
53
|
-
@sub_node ||= node.sub_nodes.values.first
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
@@ -1,114 +0,0 @@
|
|
1
|
-
module NxtSchema
|
2
|
-
module Application
|
3
|
-
class Schema < Application::Base
|
4
|
-
def call
|
5
|
-
apply_on_evaluators
|
6
|
-
child_applications # build applications here so we can access them even when invalid
|
7
|
-
return self if maybe_evaluator_applies?
|
8
|
-
|
9
|
-
coerce_input
|
10
|
-
return self unless valid?
|
11
|
-
|
12
|
-
flag_missing_keys
|
13
|
-
apply_additional_keys_strategy
|
14
|
-
|
15
|
-
child_applications.each do |key, child|
|
16
|
-
current_application = child.call
|
17
|
-
|
18
|
-
if !current_application.valid?
|
19
|
-
merge_errors(current_application)
|
20
|
-
else
|
21
|
-
output[key] = current_application.output
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
transform_keys
|
26
|
-
register_as_applied_when_valid
|
27
|
-
run_validations
|
28
|
-
self
|
29
|
-
end
|
30
|
-
|
31
|
-
delegate :[], to: :child_applications
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
def transform_keys
|
36
|
-
transformer = node.key_transformer
|
37
|
-
return unless transformer && output.respond_to?(:transform_keys!)
|
38
|
-
|
39
|
-
output.transform_keys!(&transformer)
|
40
|
-
end
|
41
|
-
|
42
|
-
def keys
|
43
|
-
@keys ||= node.sub_nodes.reject { |key, _| optional_and_not_given_key?(key) }.keys
|
44
|
-
end
|
45
|
-
|
46
|
-
def additional_keys
|
47
|
-
@additional_keys ||= input.keys - keys
|
48
|
-
end
|
49
|
-
|
50
|
-
def optional_and_not_given_key?(key)
|
51
|
-
node.sub_nodes[key].optional? && !input.key?(key)
|
52
|
-
end
|
53
|
-
|
54
|
-
def additional_keys?
|
55
|
-
additional_keys.any?
|
56
|
-
end
|
57
|
-
|
58
|
-
def missing_keys
|
59
|
-
@missing_keys ||= node.sub_nodes.reject { |_, node| node.omnipresent? || node.optional? }.keys - input.keys
|
60
|
-
end
|
61
|
-
|
62
|
-
def apply_additional_keys_strategy
|
63
|
-
return if allow_additional_keys?
|
64
|
-
return unless additional_keys?
|
65
|
-
|
66
|
-
if restrict_additional_keys?
|
67
|
-
add_schema_error("Additional keys are not allowed: #{additional_keys}")
|
68
|
-
elsif reject_additional_keys?
|
69
|
-
self.output = output.except(*additional_keys)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
def flag_missing_keys
|
74
|
-
return if missing_keys.empty?
|
75
|
-
|
76
|
-
add_schema_error("The following keys are missing: #{missing_keys}")
|
77
|
-
end
|
78
|
-
|
79
|
-
def allow_additional_keys?
|
80
|
-
node.additional_keys_strategy == :allow
|
81
|
-
end
|
82
|
-
|
83
|
-
def reject_additional_keys?
|
84
|
-
node.additional_keys_strategy == :reject
|
85
|
-
end
|
86
|
-
|
87
|
-
def restrict_additional_keys?
|
88
|
-
node.additional_keys_strategy == :restrict
|
89
|
-
end
|
90
|
-
|
91
|
-
def child_applications
|
92
|
-
@child_applications ||= begin
|
93
|
-
keys.inject({}) do |acc, key|
|
94
|
-
child_application = build_child_application(key)
|
95
|
-
acc[key] = child_application if child_application.present?
|
96
|
-
acc
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
def build_child_application(key)
|
102
|
-
sub_node = node.sub_nodes[key]
|
103
|
-
return unless sub_node.present?
|
104
|
-
|
105
|
-
value = input_has_key?(input, key) ? input[key] : MissingInput.new
|
106
|
-
sub_node.build_application(input: value, context: context, parent: self)
|
107
|
-
end
|
108
|
-
|
109
|
-
def input_has_key?(input, key)
|
110
|
-
input.respond_to?(:key?) && input.key?(key)
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|