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/LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,17 +1,15 @@
|
|
1
1
|
[gem]: https://rubygems.org/gems/dry-schema
|
2
|
-
[travis]: https://travis-ci.com/dry-rb/dry-schema
|
3
2
|
[actions]: https://github.com/dry-rb/dry-schema/actions
|
4
|
-
[
|
3
|
+
[codacy]: https://www.codacy.com/gh/dry-rb/dry-schema
|
5
4
|
[chat]: https://dry-rb.zulipchat.com
|
6
5
|
[inchpages]: http://inch-ci.org/github/dry-rb/dry-schema
|
7
6
|
|
8
7
|
# dry-schema [][chat]
|
9
8
|
|
10
9
|
[][gem]
|
11
|
-
[][travis]
|
12
10
|
[][actions]
|
13
|
-
[][codacy]
|
12
|
+
[][codacy]
|
15
13
|
[][inchpages]
|
16
14
|
|
17
15
|
## Links
|
@@ -21,7 +19,7 @@
|
|
21
19
|
|
22
20
|
## Supported Ruby versions
|
23
21
|
|
24
|
-
This library officially supports following Ruby versions:
|
22
|
+
This library officially supports the following Ruby versions:
|
25
23
|
|
26
24
|
* MRI >= `2.4`
|
27
25
|
* jruby >= `9.2`
|
data/config/errors.yml
CHANGED
@@ -3,6 +3,8 @@ en:
|
|
3
3
|
or: "or"
|
4
4
|
|
5
5
|
errors:
|
6
|
+
unexpected_key: "is not allowed"
|
7
|
+
|
6
8
|
array?: "must be an array"
|
7
9
|
|
8
10
|
empty?: "must be empty"
|
@@ -101,5 +103,7 @@ en:
|
|
101
103
|
default: "must be %{size} bytes long"
|
102
104
|
range: "must be within %{size_left} - %{size_right} bytes long"
|
103
105
|
|
106
|
+
uuid_v4?: "is not a valid UUID"
|
107
|
+
|
104
108
|
not:
|
105
109
|
empty?: "cannot be empty"
|
data/dry-schema.gemspec
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# this file is managed by dry-rb/devtools project
|
3
|
+
|
4
|
+
lib = File.expand_path('lib', __dir__)
|
5
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
6
|
+
require 'dry/schema/version'
|
7
|
+
|
8
|
+
Gem::Specification.new do |spec|
|
9
|
+
spec.name = 'dry-schema'
|
10
|
+
spec.authors = ["Piotr Solnica"]
|
11
|
+
spec.email = ["piotr.solnica@gmail.com"]
|
12
|
+
spec.license = 'MIT'
|
13
|
+
spec.version = Dry::Schema::VERSION.dup
|
14
|
+
|
15
|
+
spec.summary = "Coercion and validation for data structures"
|
16
|
+
spec.description = <<~TEXT
|
17
|
+
dry-schema provides a DSL for defining schemas with keys and rules that should be applied to
|
18
|
+
values. It supports coercion, input sanitization, custom types and localized error messages
|
19
|
+
(with or without I18n gem). It's also used as the schema engine in dry-validation.
|
20
|
+
TEXT
|
21
|
+
spec.homepage = 'https://dry-rb.org/gems/dry-schema'
|
22
|
+
spec.files = Dir["CHANGELOG.md", "LICENSE", "README.md", "dry-schema.gemspec", "lib/**/*", "config/*.yml"]
|
23
|
+
spec.bindir = 'bin'
|
24
|
+
spec.executables = []
|
25
|
+
spec.require_paths = ['lib']
|
26
|
+
|
27
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
28
|
+
spec.metadata['changelog_uri'] = 'https://github.com/dry-rb/dry-schema/blob/master/CHANGELOG.md'
|
29
|
+
spec.metadata['source_code_uri'] = 'https://github.com/dry-rb/dry-schema'
|
30
|
+
spec.metadata['bug_tracker_uri'] = 'https://github.com/dry-rb/dry-schema/issues'
|
31
|
+
|
32
|
+
spec.required_ruby_version = ">= 2.4.0"
|
33
|
+
|
34
|
+
# to update dependencies edit project.yml
|
35
|
+
spec.add_runtime_dependency "concurrent-ruby", "~> 1.0"
|
36
|
+
spec.add_runtime_dependency "dry-configurable", "~> 0.8", ">= 0.8.3"
|
37
|
+
spec.add_runtime_dependency "dry-core", "~> 0.4"
|
38
|
+
spec.add_runtime_dependency "dry-equalizer", "~> 0.2"
|
39
|
+
spec.add_runtime_dependency "dry-initializer", "~> 3.0"
|
40
|
+
spec.add_runtime_dependency "dry-logic", "~> 1.0"
|
41
|
+
spec.add_runtime_dependency "dry-types", "~> 1.4"
|
42
|
+
|
43
|
+
spec.add_development_dependency "bundler"
|
44
|
+
spec.add_development_dependency "rake"
|
45
|
+
spec.add_development_dependency "rspec"
|
46
|
+
end
|
data/lib/dry-schema.rb
CHANGED
data/lib/dry/schema.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "dry/core/extensions"
|
4
4
|
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
5
|
+
require "dry/schema/config"
|
6
|
+
require "dry/schema/constants"
|
7
|
+
require "dry/schema/dsl"
|
8
|
+
require "dry/schema/params"
|
9
|
+
require "dry/schema/json"
|
9
10
|
|
10
11
|
module Dry
|
11
12
|
# Main interface
|
@@ -14,6 +15,18 @@ module Dry
|
|
14
15
|
module Schema
|
15
16
|
extend Dry::Core::Extensions
|
16
17
|
|
18
|
+
# Configuration
|
19
|
+
#
|
20
|
+
# @example
|
21
|
+
# Dry::Schema.config.messages.backend = :i18n
|
22
|
+
#
|
23
|
+
# @return [Config]
|
24
|
+
#
|
25
|
+
# @api public
|
26
|
+
def self.config
|
27
|
+
@config ||= Config.new
|
28
|
+
end
|
29
|
+
|
17
30
|
# Define a schema
|
18
31
|
#
|
19
32
|
# @example
|
@@ -30,7 +43,7 @@ module Dry
|
|
30
43
|
#
|
31
44
|
# @api public
|
32
45
|
def self.define(**options, &block)
|
33
|
-
DSL.new(options, &block).call
|
46
|
+
DSL.new(**options, &block).call
|
34
47
|
end
|
35
48
|
|
36
49
|
# Define a schema suitable for HTTP params
|
@@ -74,4 +87,4 @@ module Dry
|
|
74
87
|
end
|
75
88
|
end
|
76
89
|
|
77
|
-
require
|
90
|
+
require "dry/schema/extensions"
|
data/lib/dry/schema/compiler.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
3
|
+
require "dry/logic/rule_compiler"
|
4
|
+
require "dry/schema/namespaced_rule"
|
5
|
+
require "dry/schema/predicate_registry"
|
6
6
|
|
7
7
|
module Dry
|
8
8
|
module Schema
|
@@ -30,12 +30,12 @@ module Dry
|
|
30
30
|
# used as nested schemas
|
31
31
|
#
|
32
32
|
# @param [Array] node
|
33
|
-
# @param [Hash]
|
33
|
+
# @param [Hash] _opts Unused
|
34
34
|
#
|
35
35
|
# @return [NamespacedRule]
|
36
36
|
#
|
37
37
|
# @api private
|
38
|
-
def visit_namespace(node,
|
38
|
+
def visit_namespace(node, _opts = EMPTY_HASH)
|
39
39
|
namespace, rest = node
|
40
40
|
NamespacedRule.new(namespace, visit(rest))
|
41
41
|
end
|
data/lib/dry/schema/config.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "dry/equalizer"
|
4
|
+
require "dry/configurable"
|
5
5
|
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
6
|
+
require "dry/schema/constants"
|
7
|
+
require "dry/schema/predicate_registry"
|
8
|
+
require "dry/schema/type_container"
|
9
9
|
|
10
10
|
module Dry
|
11
11
|
module Schema
|
@@ -51,6 +51,15 @@ module Dry
|
|
51
51
|
setting(:default_locale, nil)
|
52
52
|
end
|
53
53
|
|
54
|
+
# @!method validate_keys
|
55
|
+
#
|
56
|
+
# On/off switch for key validator
|
57
|
+
#
|
58
|
+
# @return [Boolean]
|
59
|
+
#
|
60
|
+
# @api public
|
61
|
+
setting(:validate_keys, false)
|
62
|
+
|
54
63
|
# @api private
|
55
64
|
def respond_to_missing?(meth, include_private = false)
|
56
65
|
super || config.respond_to?(meth, include_private)
|
@@ -58,7 +67,7 @@ module Dry
|
|
58
67
|
|
59
68
|
# @api private
|
60
69
|
def inspect
|
61
|
-
"#<#{self.class} #{to_h.map { |k,v| ["#{k}=", v.inspect] }.map(&:join).join(
|
70
|
+
"#<#{self.class} #{to_h.map { |k, v| ["#{k}=", v.inspect] }.map(&:join).join(" ")}>"
|
62
71
|
end
|
63
72
|
|
64
73
|
private
|
data/lib/dry/schema/constants.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "pathname"
|
4
|
+
require "dry/core/constants"
|
5
5
|
|
6
6
|
module Dry
|
7
7
|
# Common constants used across the library
|
@@ -10,15 +10,24 @@ module Dry
|
|
10
10
|
module Schema
|
11
11
|
include Core::Constants
|
12
12
|
|
13
|
-
LIST_SEPARATOR =
|
14
|
-
QUESTION_MARK =
|
15
|
-
DOT =
|
13
|
+
LIST_SEPARATOR = ", "
|
14
|
+
QUESTION_MARK = "?"
|
15
|
+
DOT = "."
|
16
|
+
|
17
|
+
# core processor steps in the default execution order
|
18
|
+
STEPS_IN_ORDER = %i[
|
19
|
+
key_validator
|
20
|
+
key_coercer
|
21
|
+
filter_schema
|
22
|
+
value_coercer
|
23
|
+
rule_applier
|
24
|
+
].freeze
|
16
25
|
|
17
26
|
# Path to the default set of localized messages bundled within the gem
|
18
|
-
DEFAULT_MESSAGES_PATH = Pathname(__dir__).join(
|
27
|
+
DEFAULT_MESSAGES_PATH = Pathname(__dir__).join("../../../config/errors.yml").realpath.freeze
|
19
28
|
|
20
29
|
# Default namespace used for localized messages in YAML files
|
21
|
-
DEFAULT_MESSAGES_ROOT =
|
30
|
+
DEFAULT_MESSAGES_ROOT = "dry_schema"
|
22
31
|
|
23
32
|
# An error raised when DSL is used in an incorrect way
|
24
33
|
InvalidSchemaError = Class.new(StandardError)
|
data/lib/dry/schema/dsl.rb
CHANGED
@@ -1,19 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
|
11
|
-
|
12
|
-
require
|
13
|
-
require
|
14
|
-
require
|
15
|
-
require
|
16
|
-
require
|
3
|
+
require "dry/initializer"
|
4
|
+
|
5
|
+
require "dry/schema/constants"
|
6
|
+
require "dry/schema/path"
|
7
|
+
require "dry/schema/config"
|
8
|
+
require "dry/schema/compiler"
|
9
|
+
require "dry/schema/types"
|
10
|
+
require "dry/schema/macros"
|
11
|
+
|
12
|
+
require "dry/schema/processor"
|
13
|
+
require "dry/schema/processor_steps"
|
14
|
+
require "dry/schema/key_map"
|
15
|
+
require "dry/schema/key_coercer"
|
16
|
+
require "dry/schema/key_validator"
|
17
|
+
require "dry/schema/value_coercer"
|
18
|
+
require "dry/schema/rule_applier"
|
17
19
|
|
18
20
|
module Dry
|
19
21
|
module Schema
|
@@ -51,8 +53,6 @@ module Dry
|
|
51
53
|
|
52
54
|
extend Dry::Initializer
|
53
55
|
|
54
|
-
include ::Dry::Equalizer(:options)
|
55
|
-
|
56
56
|
# @return [Compiler] The rule compiler object
|
57
57
|
option :compiler, default: -> { Compiler.new }
|
58
58
|
|
@@ -69,10 +69,13 @@ module Dry
|
|
69
69
|
option :parent, Types::Coercible::Array, default: -> { EMPTY_ARRAY.dup }, as: :parents
|
70
70
|
|
71
71
|
# @return [Config] Configuration object exposed via `#configure` method
|
72
|
-
option :config, optional: true, default: proc {
|
72
|
+
option :config, optional: true, default: proc { default_config }
|
73
73
|
|
74
74
|
# @return [ProcessorSteps] Steps for the processor
|
75
|
-
option :steps, default: proc {
|
75
|
+
option :steps, default: proc { ProcessorSteps.new }
|
76
|
+
|
77
|
+
# @return [Path, Array] Path under which the schema is defined
|
78
|
+
option :path, -> *args { Path[*args] if args.any? }, default: proc { EMPTY_ARRAY }
|
76
79
|
|
77
80
|
# Build a new DSL object and evaluate provided block
|
78
81
|
#
|
@@ -173,7 +176,7 @@ module Dry
|
|
173
176
|
def key(name, macro:, &block)
|
174
177
|
raise ArgumentError, "Key +#{name}+ is not a symbol" unless name.is_a?(::Symbol)
|
175
178
|
|
176
|
-
set_type(name, Types::Any)
|
179
|
+
set_type(name, Types::Any.meta(default: true))
|
177
180
|
|
178
181
|
macro = macro.new(
|
179
182
|
name: name,
|
@@ -193,12 +196,31 @@ module Dry
|
|
193
196
|
#
|
194
197
|
# @api private
|
195
198
|
def call
|
196
|
-
steps[
|
197
|
-
steps[:value_coercer] = value_coercer
|
198
|
-
steps[:rule_applier] = rule_applier
|
199
|
-
steps[:filter_schema] = filter_schema.rule_applier if filter_rules?
|
199
|
+
all_steps = parents.map(&:steps) + [steps]
|
200
200
|
|
201
|
-
|
201
|
+
result_steps = all_steps.inject { |result, steps| result.merge(steps) }
|
202
|
+
|
203
|
+
result_steps[:key_validator] = key_validator if config.validate_keys
|
204
|
+
result_steps[:key_coercer] = key_coercer
|
205
|
+
result_steps[:value_coercer] = value_coercer
|
206
|
+
result_steps[:rule_applier] = rule_applier
|
207
|
+
result_steps[:filter_schema] = filter_schema.rule_applier if filter_rules?
|
208
|
+
|
209
|
+
processor_type.new(schema_dsl: self, steps: result_steps)
|
210
|
+
end
|
211
|
+
|
212
|
+
# Merge with another dsl
|
213
|
+
#
|
214
|
+
# @return [DSL]
|
215
|
+
#
|
216
|
+
# @api private
|
217
|
+
def merge(other)
|
218
|
+
new(
|
219
|
+
parent: parents + other.parents,
|
220
|
+
macros: macros + other.macros,
|
221
|
+
types: types.merge(other.types),
|
222
|
+
steps: steps.merge(other.steps)
|
223
|
+
)
|
202
224
|
end
|
203
225
|
|
204
226
|
# Cast this DSL into a rule object
|
@@ -217,7 +239,7 @@ module Dry
|
|
217
239
|
#
|
218
240
|
# @api public
|
219
241
|
def array
|
220
|
-
-> member_type { type_registry[
|
242
|
+
-> member_type { type_registry["array"].of(resolve_type(member_type)) }
|
221
243
|
end
|
222
244
|
|
223
245
|
# Method allows steps injection to the processor
|
@@ -265,7 +287,7 @@ module Dry
|
|
265
287
|
#
|
266
288
|
# @api private
|
267
289
|
def type_schema
|
268
|
-
our_schema = type_registry[
|
290
|
+
our_schema = type_registry["hash"].schema(types).lax
|
269
291
|
schemas = [*parents.map(&:type_schema), our_schema]
|
270
292
|
schemas.inject { |result, schema| result.schema(schema.to_a) }
|
271
293
|
end
|
@@ -275,8 +297,8 @@ module Dry
|
|
275
297
|
# @return [Dry::Types::Safe]
|
276
298
|
#
|
277
299
|
# @api private
|
278
|
-
def new(options
|
279
|
-
self.class.new(options
|
300
|
+
def new(**options, &block)
|
301
|
+
self.class.new(**options, processor_type: processor_type, config: config, &block)
|
280
302
|
end
|
281
303
|
|
282
304
|
# Set a type for the given key name
|
@@ -289,11 +311,20 @@ module Dry
|
|
289
311
|
# @api private
|
290
312
|
def set_type(name, spec)
|
291
313
|
type = resolve_type(spec)
|
292
|
-
meta = {
|
314
|
+
meta = {required: false, maybe: type.optional?}
|
293
315
|
|
294
316
|
types[name] = type.meta(meta)
|
295
317
|
end
|
296
318
|
|
319
|
+
# Check if a custom type was set under provided key name
|
320
|
+
#
|
321
|
+
# @return [Bool]
|
322
|
+
#
|
323
|
+
# @api private
|
324
|
+
def custom_type?(name)
|
325
|
+
!types[name].meta[:default].equal?(true)
|
326
|
+
end
|
327
|
+
|
297
328
|
# Resolve type object from the provided spec
|
298
329
|
#
|
299
330
|
# @param [Symbol, Array<Symbol>, Dry::Types::Type] spec
|
@@ -328,7 +359,7 @@ module Dry
|
|
328
359
|
#
|
329
360
|
# @api private
|
330
361
|
def filter_rules?
|
331
|
-
if instance_variable_defined?(
|
362
|
+
if instance_variable_defined?("@filter_schema_dsl") && !filter_schema_dsl.macros.empty?
|
332
363
|
return true
|
333
364
|
end
|
334
365
|
|
@@ -376,6 +407,15 @@ module Dry
|
|
376
407
|
parents.select(&:filter_rules?).map(&:filter_schema)
|
377
408
|
end
|
378
409
|
|
410
|
+
# Build a key validator
|
411
|
+
#
|
412
|
+
# @return [KeyValidator]
|
413
|
+
#
|
414
|
+
# @api private
|
415
|
+
def key_validator
|
416
|
+
KeyValidator.new(key_map: key_map + parent_key_map)
|
417
|
+
end
|
418
|
+
|
379
419
|
# Build a key coercer
|
380
420
|
#
|
381
421
|
# @return [KeyCoercer]
|
@@ -413,13 +453,19 @@ module Dry
|
|
413
453
|
|
414
454
|
# Build a key spec needed by the key map
|
415
455
|
#
|
456
|
+
# TODO: we need a key-map compiler using Types AST
|
457
|
+
#
|
416
458
|
# @api private
|
417
459
|
def key_spec(name, type)
|
418
460
|
if type.respond_to?(:keys)
|
419
|
-
{
|
461
|
+
{name => key_map(type.name_key_map)}
|
420
462
|
elsif type.respond_to?(:member)
|
421
463
|
kv = key_spec(name, type.member)
|
422
464
|
kv.equal?(name) ? name : kv.flatten(1)
|
465
|
+
elsif type.meta[:maybe] && type.respond_to?(:right)
|
466
|
+
key_spec(name, type.right)
|
467
|
+
elsif type.respond_to?(:type)
|
468
|
+
key_spec(name, type.type)
|
423
469
|
else
|
424
470
|
name
|
425
471
|
end
|
@@ -434,6 +480,18 @@ module Dry
|
|
434
480
|
def parent_key_map
|
435
481
|
parents.reduce([]) { |key_map, parent| parent.key_map + key_map }
|
436
482
|
end
|
483
|
+
|
484
|
+
# @api private
|
485
|
+
def default_config
|
486
|
+
parents.each_cons(2) do |left, right|
|
487
|
+
unless left.config == right.config
|
488
|
+
raise ArgumentError,
|
489
|
+
"Parent configs differ, left=#{left.inspect}, right=#{right.inspect}"
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
493
|
+
(parent || Schema).config.dup
|
494
|
+
end
|
437
495
|
end
|
438
496
|
end
|
439
497
|
end
|