dry-schema 1.4.1 → 1.5.2
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/CHANGELOG.md +210 -73
- data/LICENSE +1 -1
- data/README.md +4 -6
- data/config/errors.yml +4 -0
- data/dry-schema.gemspec +46 -0
- data/lib/dry-schema.rb +1 -1
- data/lib/dry/schema.rb +20 -7
- data/lib/dry/schema/compiler.rb +5 -5
- data/lib/dry/schema/config.rb +15 -6
- data/lib/dry/schema/constants.rb +16 -7
- data/lib/dry/schema/dsl.rb +89 -31
- data/lib/dry/schema/extensions.rb +10 -2
- data/lib/dry/schema/extensions/hints.rb +15 -8
- data/lib/dry/schema/extensions/hints/message_compiler_methods.rb +2 -2
- data/lib/dry/schema/extensions/hints/message_set_methods.rb +0 -47
- data/lib/dry/schema/extensions/info.rb +27 -0
- data/lib/dry/schema/extensions/info/schema_compiler.rb +105 -0
- data/lib/dry/schema/extensions/monads.rb +1 -1
- data/lib/dry/schema/extensions/struct.rb +32 -0
- data/lib/dry/schema/json.rb +1 -1
- data/lib/dry/schema/key.rb +20 -5
- data/lib/dry/schema/key_coercer.rb +4 -4
- data/lib/dry/schema/key_map.rb +9 -4
- data/lib/dry/schema/key_validator.rb +67 -0
- data/lib/dry/schema/macros.rb +8 -8
- data/lib/dry/schema/macros/array.rb +17 -4
- data/lib/dry/schema/macros/core.rb +11 -6
- data/lib/dry/schema/macros/dsl.rb +44 -23
- data/lib/dry/schema/macros/each.rb +4 -4
- data/lib/dry/schema/macros/filled.rb +5 -5
- data/lib/dry/schema/macros/hash.rb +21 -3
- data/lib/dry/schema/macros/key.rb +10 -9
- data/lib/dry/schema/macros/maybe.rb +4 -5
- data/lib/dry/schema/macros/optional.rb +1 -1
- data/lib/dry/schema/macros/required.rb +1 -1
- data/lib/dry/schema/macros/schema.rb +23 -2
- data/lib/dry/schema/macros/value.rb +34 -7
- data/lib/dry/schema/message.rb +35 -9
- data/lib/dry/schema/message/or.rb +18 -39
- data/lib/dry/schema/message/or/abstract.rb +28 -0
- data/lib/dry/schema/message/or/multi_path.rb +37 -0
- data/lib/dry/schema/message/or/single_path.rb +64 -0
- data/lib/dry/schema/message_compiler.rb +58 -22
- data/lib/dry/schema/message_compiler/visitor_opts.rb +2 -2
- data/lib/dry/schema/message_set.rb +26 -37
- data/lib/dry/schema/messages.rb +6 -6
- data/lib/dry/schema/messages/abstract.rb +54 -62
- data/lib/dry/schema/messages/i18n.rb +36 -10
- data/lib/dry/schema/messages/namespaced.rb +12 -2
- data/lib/dry/schema/messages/template.rb +19 -44
- data/lib/dry/schema/messages/yaml.rb +61 -14
- data/lib/dry/schema/params.rb +1 -1
- data/lib/dry/schema/path.rb +44 -5
- data/lib/dry/schema/predicate.rb +4 -2
- data/lib/dry/schema/predicate_inferrer.rb +4 -184
- data/lib/dry/schema/predicate_registry.rb +2 -2
- data/lib/dry/schema/primitive_inferrer.rb +16 -0
- data/lib/dry/schema/processor.rb +50 -29
- data/lib/dry/schema/processor_steps.rb +50 -27
- data/lib/dry/schema/result.rb +53 -6
- data/lib/dry/schema/rule_applier.rb +7 -7
- data/lib/dry/schema/step.rb +79 -0
- data/lib/dry/schema/trace.rb +5 -4
- data/lib/dry/schema/type_container.rb +3 -3
- data/lib/dry/schema/type_registry.rb +2 -2
- data/lib/dry/schema/types.rb +1 -1
- data/lib/dry/schema/value_coercer.rb +2 -2
- data/lib/dry/schema/version.rb +1 -1
- metadata +21 -7
data/lib/dry/schema/macros.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
3
|
+
require "dry/schema/macros/array"
|
4
|
+
require "dry/schema/macros/each"
|
5
|
+
require "dry/schema/macros/filled"
|
6
|
+
require "dry/schema/macros/schema"
|
7
|
+
require "dry/schema/macros/hash"
|
8
|
+
require "dry/schema/macros/maybe"
|
9
|
+
require "dry/schema/macros/optional"
|
10
|
+
require "dry/schema/macros/required"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "dry/schema/macros/dsl"
|
4
4
|
|
5
5
|
module Dry
|
6
6
|
module Schema
|
@@ -13,16 +13,29 @@ module Dry
|
|
13
13
|
def value(*args, **opts, &block)
|
14
14
|
type(:array)
|
15
15
|
|
16
|
-
extract_type_spec(*args, set_type: false) do |*predicates, type_spec:|
|
16
|
+
extract_type_spec(*args, set_type: false) do |*predicates, type_spec:, type_rule:|
|
17
17
|
type(schema_dsl.array[type_spec]) if type_spec
|
18
18
|
|
19
19
|
is_hash_block = type_spec.equal?(:hash)
|
20
20
|
|
21
21
|
if predicates.any? || opts.any? || !is_hash_block
|
22
|
-
super(
|
22
|
+
super(
|
23
|
+
*predicates, type_spec: type_spec, type_rule: type_rule, **opts,
|
24
|
+
&(is_hash_block ? nil : block)
|
25
|
+
)
|
23
26
|
end
|
24
27
|
|
25
|
-
|
28
|
+
is_op = args.size.equal?(2) && args[1].is_a?(Logic::Operations::Abstract)
|
29
|
+
|
30
|
+
if is_hash_block && !is_op
|
31
|
+
hash(&block)
|
32
|
+
elsif is_op
|
33
|
+
hash = Value.new(schema_dsl: schema_dsl.new, name: name).hash(args[1])
|
34
|
+
|
35
|
+
trace.captures.concat(hash.trace.captures)
|
36
|
+
|
37
|
+
type(schema_dsl.types[name].of(hash.schema_dsl.types[name]))
|
38
|
+
end
|
26
39
|
end
|
27
40
|
|
28
41
|
self
|
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "dry/initializer"
|
4
4
|
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
5
|
+
require "dry/schema/constants"
|
6
|
+
require "dry/schema/compiler"
|
7
|
+
require "dry/schema/trace"
|
8
8
|
|
9
9
|
module Dry
|
10
10
|
module Schema
|
@@ -28,8 +28,13 @@ module Dry
|
|
28
28
|
option :schema_dsl, optional: true
|
29
29
|
|
30
30
|
# @api private
|
31
|
-
def new(options
|
32
|
-
self.class.new(
|
31
|
+
def new(**options)
|
32
|
+
self.class.new(name: name, compiler: compiler, schema_dsl: schema_dsl, **options)
|
33
|
+
end
|
34
|
+
|
35
|
+
# @api private
|
36
|
+
def path
|
37
|
+
schema_dsl.path
|
33
38
|
end
|
34
39
|
|
35
40
|
# @api private
|
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require 'dry/types/predicate_inferrer'
|
5
|
-
require 'dry/types/primitive_inferrer'
|
3
|
+
require "dry/logic/operators"
|
6
4
|
|
7
|
-
require
|
5
|
+
require "dry/schema/macros/core"
|
6
|
+
require "dry/schema/predicate_inferrer"
|
7
|
+
require "dry/schema/primitive_inferrer"
|
8
8
|
|
9
9
|
module Dry
|
10
10
|
module Schema
|
@@ -28,13 +28,13 @@ module Dry
|
|
28
28
|
# PredicateInferrer is used to infer predicate type-check from a type spec
|
29
29
|
# @return [PredicateInferrer]
|
30
30
|
# @api private
|
31
|
-
option :predicate_inferrer, default: proc {
|
31
|
+
option :predicate_inferrer, default: proc { PredicateInferrer.new(compiler.predicates) }
|
32
32
|
|
33
33
|
# @!attribute [r] primitive_inferrer
|
34
34
|
# PrimitiveInferrer used to get a list of primitive classes from configured type
|
35
35
|
# @return [PrimitiveInferrer]
|
36
36
|
# @api private
|
37
|
-
option :primitive_inferrer, default: proc {
|
37
|
+
option :primitive_inferrer, default: proc { PrimitiveInferrer.new }
|
38
38
|
|
39
39
|
# @overload value(*predicates, **predicate_opts)
|
40
40
|
# Set predicates without and with arguments
|
@@ -57,11 +57,12 @@ module Dry
|
|
57
57
|
# @return [Macros::Core]
|
58
58
|
#
|
59
59
|
# @api public
|
60
|
-
def value(*predicates,
|
60
|
+
def value(*predicates, &block)
|
61
61
|
append_macro(Macros::Value) do |macro|
|
62
|
-
macro.call(*predicates,
|
62
|
+
macro.call(*predicates, &block)
|
63
63
|
end
|
64
64
|
end
|
65
|
+
ruby2_keywords :value if respond_to?(:ruby2_keywords, true)
|
65
66
|
|
66
67
|
# Prepends `:filled?` predicate
|
67
68
|
#
|
@@ -74,11 +75,12 @@ module Dry
|
|
74
75
|
# @return [Macros::Core]
|
75
76
|
#
|
76
77
|
# @api public
|
77
|
-
def filled(*args,
|
78
|
+
def filled(*args, &block)
|
78
79
|
append_macro(Macros::Filled) do |macro|
|
79
|
-
macro.call(*args,
|
80
|
+
macro.call(*args, &block)
|
80
81
|
end
|
81
82
|
end
|
83
|
+
ruby2_keywords :filled if respond_to?(:ruby2_keywords, true)
|
82
84
|
|
83
85
|
# Specify a nested hash without enforced `hash?` type-check
|
84
86
|
#
|
@@ -99,6 +101,7 @@ module Dry
|
|
99
101
|
macro.call(*args, &block)
|
100
102
|
end
|
101
103
|
end
|
104
|
+
ruby2_keywords :schema if respond_to?(:ruby2_keywords, true)
|
102
105
|
|
103
106
|
# Specify a nested hash with enforced `hash?` type-check
|
104
107
|
#
|
@@ -113,6 +116,7 @@ module Dry
|
|
113
116
|
macro.call(*args, &block)
|
114
117
|
end
|
115
118
|
end
|
119
|
+
ruby2_keywords :hash if respond_to?(:ruby2_keywords, true)
|
116
120
|
|
117
121
|
# Specify predicates that should be applied to each element of an array
|
118
122
|
#
|
@@ -136,6 +140,7 @@ module Dry
|
|
136
140
|
macro.value(*args, &block)
|
137
141
|
end
|
138
142
|
end
|
143
|
+
ruby2_keywords :each if respond_to?(:ruby2_keywords, true)
|
139
144
|
|
140
145
|
# Like `each` but sets `array?` type-check
|
141
146
|
#
|
@@ -155,6 +160,7 @@ module Dry
|
|
155
160
|
macro.value(*args, &block)
|
156
161
|
end
|
157
162
|
end
|
163
|
+
ruby2_keywords :array if respond_to?(:ruby2_keywords, true)
|
158
164
|
|
159
165
|
# Set type spec
|
160
166
|
#
|
@@ -171,6 +177,11 @@ module Dry
|
|
171
177
|
self
|
172
178
|
end
|
173
179
|
|
180
|
+
# @api private
|
181
|
+
def custom_type?
|
182
|
+
schema_dsl.custom_type?(name)
|
183
|
+
end
|
184
|
+
|
174
185
|
private
|
175
186
|
|
176
187
|
# @api private
|
@@ -189,29 +200,32 @@ module Dry
|
|
189
200
|
|
190
201
|
# @api private
|
191
202
|
def extract_type_spec(*args, nullable: false, set_type: true)
|
192
|
-
type_spec = args[0]
|
193
|
-
|
194
|
-
is_type_spec = type_spec.is_a?(Dry::Schema::Processor) ||
|
195
|
-
type_spec.is_a?(Symbol) &&
|
196
|
-
type_spec.to_s.end_with?(QUESTION_MARK)
|
197
|
-
|
198
|
-
type_spec = nil if is_type_spec
|
203
|
+
type_spec = args[0] unless schema_or_predicate?(args[0])
|
199
204
|
|
200
205
|
predicates = Array(type_spec ? args[1..-1] : args)
|
206
|
+
type_rule = nil
|
201
207
|
|
202
208
|
if type_spec
|
203
209
|
resolved_type = resolve_type(type_spec, nullable)
|
204
210
|
|
205
|
-
|
206
|
-
|
207
|
-
|
211
|
+
if type_spec.is_a?(::Array)
|
212
|
+
type_rule = type_spec.map { |ts| new(chain: false).value(ts) }.reduce(:|)
|
213
|
+
else
|
214
|
+
type_predicates = predicate_inferrer[resolved_type]
|
208
215
|
|
209
|
-
|
216
|
+
predicates.replace(type_predicates + predicates) unless type_predicates.empty?
|
210
217
|
|
211
|
-
|
218
|
+
return self if predicates.empty?
|
219
|
+
end
|
212
220
|
end
|
213
221
|
|
214
|
-
|
222
|
+
type(resolved_type) if set_type && resolved_type
|
223
|
+
|
224
|
+
if type_rule
|
225
|
+
yield(*predicates, type_spec: nil, type_rule: type_rule)
|
226
|
+
else
|
227
|
+
yield(*predicates, type_spec: type_spec, type_rule: nil)
|
228
|
+
end
|
215
229
|
end
|
216
230
|
|
217
231
|
# @api private
|
@@ -224,6 +238,13 @@ module Dry
|
|
224
238
|
schema_dsl.resolve_type([:nil, resolved])
|
225
239
|
end
|
226
240
|
end
|
241
|
+
|
242
|
+
# @api private
|
243
|
+
def schema_or_predicate?(arg)
|
244
|
+
arg.is_a?(Dry::Schema::Processor) ||
|
245
|
+
arg.is_a?(Symbol) &&
|
246
|
+
arg.to_s.end_with?(QUESTION_MARK)
|
247
|
+
end
|
227
248
|
end
|
228
249
|
end
|
229
250
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "dry/types/type"
|
4
|
+
require "dry/schema/macros/dsl"
|
5
5
|
|
6
6
|
module Dry
|
7
7
|
module Schema
|
@@ -12,12 +12,12 @@ module Dry
|
|
12
12
|
class Each < DSL
|
13
13
|
# @api private
|
14
14
|
def value(*args, **opts)
|
15
|
-
extract_type_spec(*args, set_type: false) do |*predicates, type_spec:|
|
15
|
+
extract_type_spec(*args, set_type: false) do |*predicates, type_spec:, type_rule:|
|
16
16
|
if type_spec && !type_spec.is_a?(Dry::Types::Type)
|
17
17
|
type(schema_dsl.array[type_spec])
|
18
18
|
end
|
19
19
|
|
20
|
-
super(*predicates, type_spec: type_spec, **opts)
|
20
|
+
super(*predicates, type_spec: type_spec, type_rule: type_rule, **opts)
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "dry/schema/macros/value"
|
4
4
|
|
5
5
|
module Dry
|
6
6
|
module Schema
|
@@ -15,23 +15,23 @@ module Dry
|
|
15
15
|
|
16
16
|
if opts[:type_spec] && !filter_empty_string?
|
17
17
|
value(predicates[0], :filled?, *predicates[1..predicates.size - 1], **opts, &block)
|
18
|
+
elsif opts[:type_rule]
|
19
|
+
value(:filled?).value(*predicates, **opts, &block)
|
18
20
|
else
|
19
21
|
value(:filled?, *predicates, **opts, &block)
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
23
25
|
# @api private
|
24
|
-
# rubocop:disable Style/GuardClause
|
25
26
|
def ensure_valid_predicates(predicates)
|
26
27
|
if predicates.include?(:empty?)
|
27
|
-
raise ::Dry::Schema::InvalidSchemaError,
|
28
|
+
raise ::Dry::Schema::InvalidSchemaError, "Using filled with empty? predicate is invalid"
|
28
29
|
end
|
29
30
|
|
30
31
|
if predicates.include?(:filled?)
|
31
|
-
raise ::Dry::Schema::InvalidSchemaError,
|
32
|
+
raise ::Dry::Schema::InvalidSchemaError, "Using filled with filled? is redundant"
|
32
33
|
end
|
33
34
|
end
|
34
|
-
# rubocop:enable Style/GuardClause
|
35
35
|
|
36
36
|
# @api private
|
37
37
|
def filter_empty_string?
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "dry/schema/macros/schema"
|
4
4
|
|
5
5
|
module Dry
|
6
6
|
module Schema
|
@@ -11,8 +11,26 @@ module Dry
|
|
11
11
|
class Hash < Schema
|
12
12
|
# @api private
|
13
13
|
def call(*args, &block)
|
14
|
-
|
15
|
-
|
14
|
+
if args.size >= 1 && args[0].respond_to?(:keys)
|
15
|
+
hash_type = args[0]
|
16
|
+
type_predicates = predicate_inferrer[hash_type]
|
17
|
+
all_predicats = type_predicates + args.drop(1)
|
18
|
+
|
19
|
+
super(*all_predicats) do
|
20
|
+
hash_type.each do |key|
|
21
|
+
if key.required?
|
22
|
+
required(key.name).value(key.type)
|
23
|
+
else
|
24
|
+
optional(key.name).value(key.type)
|
25
|
+
end
|
26
|
+
instance_exec(&block) if block
|
27
|
+
end
|
28
|
+
end
|
29
|
+
else
|
30
|
+
trace << hash?
|
31
|
+
|
32
|
+
super(*args, &block)
|
33
|
+
end
|
16
34
|
end
|
17
35
|
end
|
18
36
|
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
3
|
+
require "dry/schema/processor"
|
4
|
+
require "dry/schema/macros/dsl"
|
5
|
+
require "dry/schema/constants"
|
6
6
|
|
7
7
|
module Dry
|
8
8
|
module Schema
|
@@ -30,6 +30,7 @@ module Dry
|
|
30
30
|
(filter_schema_dsl[name] || filter_schema_dsl.optional(name)).value(*args, &block)
|
31
31
|
self
|
32
32
|
end
|
33
|
+
ruby2_keywords(:filter) if respond_to?(:ruby2_keywords, true)
|
33
34
|
|
34
35
|
# @overload value(type_spec, *predicates, **predicate_opts)
|
35
36
|
# Set type specification and predicates
|
@@ -53,8 +54,8 @@ module Dry
|
|
53
54
|
#
|
54
55
|
# @api public
|
55
56
|
def value(*args, **opts, &block)
|
56
|
-
extract_type_spec(*args) do |*predicates, type_spec:|
|
57
|
-
super(*predicates, type_spec: type_spec, **opts, &block)
|
57
|
+
extract_type_spec(*args) do |*predicates, type_spec:, type_rule:|
|
58
|
+
super(*predicates, type_spec: type_spec, type_rule: type_rule, **opts, &block)
|
58
59
|
end
|
59
60
|
end
|
60
61
|
|
@@ -69,8 +70,8 @@ module Dry
|
|
69
70
|
#
|
70
71
|
# @api public
|
71
72
|
def filled(*args, **opts, &block)
|
72
|
-
extract_type_spec(*args) do |*predicates, type_spec:|
|
73
|
-
super(*predicates, type_spec: type_spec, **opts, &block)
|
73
|
+
extract_type_spec(*args) do |*predicates, type_spec:, type_rule:|
|
74
|
+
super(*predicates, type_spec: type_spec, type_rule: type_rule, **opts, &block)
|
74
75
|
end
|
75
76
|
end
|
76
77
|
|
@@ -85,9 +86,9 @@ module Dry
|
|
85
86
|
#
|
86
87
|
# @api public
|
87
88
|
def maybe(*args, **opts, &block)
|
88
|
-
extract_type_spec(*args, nullable: true) do |*predicates, type_spec:|
|
89
|
+
extract_type_spec(*args, nullable: true) do |*predicates, type_spec:, type_rule:|
|
89
90
|
append_macro(Macros::Maybe) do |macro|
|
90
|
-
macro.call(*predicates, **opts, &block)
|
91
|
+
macro.call(*predicates, type_spec: type_spec, type_rule: type_rule, **opts, &block)
|
91
92
|
end
|
92
93
|
end
|
93
94
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "dry/schema/macros/dsl"
|
4
4
|
|
5
5
|
module Dry
|
6
6
|
module Schema
|
@@ -12,11 +12,11 @@ module Dry
|
|
12
12
|
# @api private
|
13
13
|
def call(*args, **opts, &block)
|
14
14
|
if args.include?(:empty?)
|
15
|
-
raise ::Dry::Schema::InvalidSchemaError,
|
15
|
+
raise ::Dry::Schema::InvalidSchemaError, "Using maybe with empty? predicate is invalid"
|
16
16
|
end
|
17
17
|
|
18
18
|
if args.include?(:nil?)
|
19
|
-
raise ::Dry::Schema::InvalidSchemaError,
|
19
|
+
raise ::Dry::Schema::InvalidSchemaError, "Using maybe with nil? predicate is redundant"
|
20
20
|
end
|
21
21
|
|
22
22
|
value(*args, **opts, &block)
|
@@ -30,8 +30,7 @@ module Dry
|
|
30
30
|
[
|
31
31
|
[:not, [:predicate, [:nil?, [[:input, Undefined]]]]],
|
32
32
|
trace.to_rule.to_ast
|
33
|
-
]
|
34
|
-
]
|
33
|
+
]]
|
35
34
|
end
|
36
35
|
end
|
37
36
|
end
|