dry-types 0.14.1 → 1.5.1
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 +631 -134
- data/LICENSE +17 -17
- data/README.md +15 -13
- data/dry-types.gemspec +27 -30
- data/lib/dry/types/any.rb +32 -12
- data/lib/dry/types/array/constructor.rb +32 -0
- data/lib/dry/types/array/member.rb +75 -16
- data/lib/dry/types/array.rb +19 -6
- data/lib/dry/types/builder.rb +131 -15
- data/lib/dry/types/builder_methods.rb +49 -20
- data/lib/dry/types/coercions/json.rb +43 -7
- data/lib/dry/types/coercions/params.rb +118 -31
- data/lib/dry/types/coercions.rb +76 -22
- data/lib/dry/types/compat.rb +0 -2
- data/lib/dry/types/compiler.rb +56 -41
- data/lib/dry/types/constrained/coercible.rb +36 -6
- data/lib/dry/types/constrained.rb +81 -32
- data/lib/dry/types/constraints.rb +18 -4
- data/lib/dry/types/constructor/function.rb +216 -0
- data/lib/dry/types/constructor/wrapper.rb +94 -0
- data/lib/dry/types/constructor.rb +126 -56
- data/lib/dry/types/container.rb +7 -0
- data/lib/dry/types/core.rb +54 -21
- data/lib/dry/types/decorator.rb +38 -17
- data/lib/dry/types/default.rb +61 -16
- data/lib/dry/types/enum.rb +43 -20
- data/lib/dry/types/errors.rb +75 -9
- data/lib/dry/types/extensions/maybe.rb +74 -16
- data/lib/dry/types/extensions/monads.rb +29 -0
- data/lib/dry/types/extensions.rb +7 -1
- data/lib/dry/types/fn_container.rb +6 -1
- data/lib/dry/types/hash/constructor.rb +33 -0
- data/lib/dry/types/hash.rb +86 -67
- data/lib/dry/types/inflector.rb +3 -1
- data/lib/dry/types/json.rb +18 -16
- data/lib/dry/types/lax.rb +75 -0
- data/lib/dry/types/map.rb +76 -33
- data/lib/dry/types/meta.rb +51 -0
- data/lib/dry/types/module.rb +120 -0
- data/lib/dry/types/nominal.rb +210 -0
- data/lib/dry/types/options.rb +13 -26
- data/lib/dry/types/params.rb +39 -25
- data/lib/dry/types/predicate_inferrer.rb +238 -0
- data/lib/dry/types/predicate_registry.rb +34 -0
- data/lib/dry/types/primitive_inferrer.rb +97 -0
- data/lib/dry/types/printable.rb +16 -0
- data/lib/dry/types/printer.rb +315 -0
- data/lib/dry/types/result.rb +29 -3
- data/lib/dry/types/schema/key.rb +156 -0
- data/lib/dry/types/schema.rb +408 -0
- data/lib/dry/types/spec/types.rb +103 -33
- data/lib/dry/types/sum.rb +84 -35
- data/lib/dry/types/type.rb +49 -0
- data/lib/dry/types/version.rb +3 -1
- data/lib/dry/types.rb +156 -76
- data/lib/dry-types.rb +3 -1
- metadata +65 -78
- data/.gitignore +0 -10
- data/.rspec +0 -2
- data/.travis.yml +0 -27
- data/.yardopts +0 -5
- data/CONTRIBUTING.md +0 -29
- data/Gemfile +0 -24
- data/Rakefile +0 -20
- data/benchmarks/hash_schemas.rb +0 -51
- data/lib/dry/types/compat/form_types.rb +0 -27
- data/lib/dry/types/compat/int.rb +0 -14
- data/lib/dry/types/definition.rb +0 -113
- data/lib/dry/types/hash/schema.rb +0 -199
- data/lib/dry/types/hash/schema_builder.rb +0 -75
- data/lib/dry/types/safe.rb +0 -59
- data/log/.gitkeep +0 -0
data/lib/dry/types/enum.rb
CHANGED
@@ -1,11 +1,18 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/core/equalizer"
|
4
|
+
require "dry/types/decorator"
|
2
5
|
|
3
6
|
module Dry
|
4
7
|
module Types
|
8
|
+
# Enum types can be used to define an enum on top of an existing type
|
9
|
+
#
|
10
|
+
# @api public
|
5
11
|
class Enum
|
6
12
|
include Type
|
7
|
-
include Dry::Equalizer(:type, :
|
13
|
+
include Dry::Equalizer(:type, :mapping, inspect: false, immutable: true)
|
8
14
|
include Decorator
|
15
|
+
include Builder
|
9
16
|
|
10
17
|
# @return [Array]
|
11
18
|
attr_reader :values
|
@@ -19,7 +26,9 @@ module Dry
|
|
19
26
|
# @param [Type] type
|
20
27
|
# @param [Hash] options
|
21
28
|
# @option options [Array] :values
|
22
|
-
|
29
|
+
#
|
30
|
+
# @api private
|
31
|
+
def initialize(type, **options)
|
23
32
|
super
|
24
33
|
@mapping = options.fetch(:mapping).freeze
|
25
34
|
@values = @mapping.keys.freeze
|
@@ -27,45 +36,59 @@ module Dry
|
|
27
36
|
freeze
|
28
37
|
end
|
29
38
|
|
30
|
-
# @param [Object] input
|
31
39
|
# @return [Object]
|
32
|
-
|
33
|
-
|
40
|
+
#
|
41
|
+
# @api private
|
42
|
+
def call_unsafe(input)
|
43
|
+
type.call_unsafe(map_value(input))
|
44
|
+
end
|
45
|
+
|
46
|
+
# @return [Object]
|
47
|
+
#
|
48
|
+
# @api private
|
49
|
+
def call_safe(input, &block)
|
50
|
+
type.call_safe(map_value(input), &block)
|
34
51
|
end
|
35
|
-
alias_method :[], :call
|
36
52
|
|
37
|
-
# @
|
38
|
-
#
|
39
|
-
# @
|
40
|
-
# @return [Logic::Result]
|
41
|
-
# @return [Object] if coercion fails and a block is given
|
53
|
+
# @see Dry::Types::Constrained#try
|
54
|
+
#
|
55
|
+
# @api public
|
42
56
|
def try(input)
|
43
57
|
super(map_value(input))
|
44
58
|
end
|
45
59
|
|
60
|
+
# @api private
|
46
61
|
def default(*)
|
47
|
-
raise
|
48
|
-
|
62
|
+
raise ".enum(*values).default(value) is not supported. Call "\
|
63
|
+
".default(value).enum(*values) instead"
|
49
64
|
end
|
50
65
|
|
51
66
|
# Check whether a value is in the enum
|
52
67
|
alias_method :include?, :valid?
|
53
68
|
|
54
|
-
# @
|
69
|
+
# @see Nominal#to_ast
|
55
70
|
#
|
56
|
-
# @
|
71
|
+
# @api public
|
57
72
|
def to_ast(meta: true)
|
58
|
-
[:enum, [type.to_ast(meta: meta),
|
59
|
-
|
60
|
-
|
73
|
+
[:enum, [type.to_ast(meta: meta), mapping]]
|
74
|
+
end
|
75
|
+
|
76
|
+
# @return [String]
|
77
|
+
#
|
78
|
+
# @api public
|
79
|
+
def to_s
|
80
|
+
PRINTER.(self)
|
61
81
|
end
|
82
|
+
alias_method :inspect, :to_s
|
62
83
|
|
63
84
|
private
|
64
85
|
|
65
86
|
# Maps a value
|
66
87
|
#
|
67
|
-
# @
|
88
|
+
# @param [Object] input
|
89
|
+
#
|
68
90
|
# @return [Object]
|
91
|
+
#
|
69
92
|
# @api private
|
70
93
|
def map_value(input)
|
71
94
|
if input.equal?(Undefined)
|
data/lib/dry/types/errors.rb
CHANGED
@@ -1,14 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Dry
|
2
4
|
module Types
|
3
|
-
extend Dry::Core::ClassAttributes
|
5
|
+
extend ::Dry::Core::ClassAttributes
|
4
6
|
|
5
7
|
# @!attribute [r] namespace
|
6
|
-
# @return [Container{String =>
|
8
|
+
# @return [Container{String => Nominal}]
|
7
9
|
defines :namespace
|
8
10
|
|
9
11
|
namespace self
|
10
12
|
|
11
|
-
class
|
13
|
+
# Base class for coercion errors raise by dry-types
|
14
|
+
#
|
15
|
+
class CoercionError < ::StandardError
|
16
|
+
# @api private
|
17
|
+
def self.handle(exception, meta: Undefined)
|
18
|
+
if block_given?
|
19
|
+
yield
|
20
|
+
else
|
21
|
+
raise new(
|
22
|
+
exception.message,
|
23
|
+
meta: meta,
|
24
|
+
backtrace: exception.backtrace
|
25
|
+
)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Metadata associated with the error
|
30
|
+
#
|
31
|
+
# @return [Object]
|
32
|
+
attr_reader :meta
|
33
|
+
|
34
|
+
# @api private
|
35
|
+
def initialize(message, meta: Undefined, backtrace: Undefined)
|
36
|
+
unless message.is_a?(::String)
|
37
|
+
raise ::ArgumentError, "message must be a string, #{message.class} given"
|
38
|
+
end
|
39
|
+
|
40
|
+
super(message)
|
41
|
+
@meta = Undefined.default(meta, nil)
|
42
|
+
set_backtrace(backtrace) unless Undefined.equal?(backtrace)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Collection of multiple errors
|
47
|
+
#
|
48
|
+
class MultipleError < CoercionError
|
49
|
+
# @return [Array<CoercionError>]
|
50
|
+
attr_reader :errors
|
51
|
+
|
52
|
+
# @param [Array<CoercionError>] errors
|
53
|
+
def initialize(errors)
|
54
|
+
@errors = errors
|
55
|
+
end
|
56
|
+
|
57
|
+
# @return string
|
58
|
+
def message
|
59
|
+
errors.map(&:message).join(", ")
|
60
|
+
end
|
61
|
+
|
62
|
+
# @return [Array]
|
63
|
+
def meta
|
64
|
+
errors.map(&:meta)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
class SchemaError < CoercionError
|
12
69
|
# @param [String,Symbol] key
|
13
70
|
# @param [Object] value
|
14
71
|
# @param [String, #to_s] result
|
@@ -17,26 +74,34 @@ module Dry
|
|
17
74
|
end
|
18
75
|
end
|
19
76
|
|
20
|
-
MapError = Class.new(
|
77
|
+
MapError = ::Class.new(CoercionError)
|
21
78
|
|
22
|
-
SchemaKeyError = Class.new(
|
79
|
+
SchemaKeyError = ::Class.new(CoercionError)
|
23
80
|
private_constant(:SchemaKeyError)
|
24
81
|
|
25
82
|
class MissingKeyError < SchemaKeyError
|
83
|
+
# @return [Symbol]
|
84
|
+
attr_reader :key
|
85
|
+
|
26
86
|
# @param [String,Symbol] key
|
27
87
|
def initialize(key)
|
28
|
-
|
88
|
+
@key = key
|
89
|
+
super("#{key.inspect} is missing in Hash input")
|
29
90
|
end
|
30
91
|
end
|
31
92
|
|
32
93
|
class UnknownKeysError < SchemaKeyError
|
94
|
+
# @return [Array<Symbol>]
|
95
|
+
attr_reader :keys
|
96
|
+
|
33
97
|
# @param [<String, Symbol>] keys
|
34
|
-
def initialize(
|
98
|
+
def initialize(keys)
|
99
|
+
@keys = keys
|
35
100
|
super("unexpected keys #{keys.inspect} in Hash input")
|
36
101
|
end
|
37
102
|
end
|
38
103
|
|
39
|
-
class ConstraintError <
|
104
|
+
class ConstraintError < CoercionError
|
40
105
|
# @return [String, #to_s]
|
41
106
|
attr_reader :result
|
42
107
|
# @return [Object]
|
@@ -56,9 +121,10 @@ module Dry
|
|
56
121
|
end
|
57
122
|
|
58
123
|
# @return [String]
|
59
|
-
def
|
124
|
+
def message
|
60
125
|
"#{input.inspect} violates constraints (#{result} failed)"
|
61
126
|
end
|
127
|
+
alias_method :to_s, :message
|
62
128
|
end
|
63
129
|
end
|
64
130
|
end
|
@@ -1,49 +1,83 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/core/equalizer"
|
4
|
+
require "dry/monads/maybe"
|
5
|
+
require "dry/types/decorator"
|
3
6
|
|
4
7
|
module Dry
|
5
8
|
module Types
|
9
|
+
# Maybe extension provides Maybe types where values are wrapped using `Either` monad
|
10
|
+
#
|
11
|
+
# @api public
|
6
12
|
class Maybe
|
7
13
|
include Type
|
8
|
-
include Dry::Equalizer(:type, :options)
|
14
|
+
include ::Dry::Equalizer(:type, :options, inspect: false, immutable: true)
|
9
15
|
include Decorator
|
10
16
|
include Builder
|
11
|
-
include
|
17
|
+
include Printable
|
18
|
+
include ::Dry::Monads::Maybe::Mixin
|
19
|
+
|
20
|
+
# @param [Dry::Monads::Maybe, Object] input
|
21
|
+
#
|
22
|
+
# @return [Dry::Monads::Maybe]
|
23
|
+
#
|
24
|
+
# @api private
|
25
|
+
def call_unsafe(input = Undefined)
|
26
|
+
case input
|
27
|
+
when ::Dry::Monads::Maybe
|
28
|
+
input
|
29
|
+
when Undefined
|
30
|
+
None()
|
31
|
+
else
|
32
|
+
Maybe(type.call_unsafe(input))
|
33
|
+
end
|
34
|
+
end
|
12
35
|
|
13
36
|
# @param [Dry::Monads::Maybe, Object] input
|
37
|
+
#
|
14
38
|
# @return [Dry::Monads::Maybe]
|
15
|
-
|
39
|
+
#
|
40
|
+
# @api private
|
41
|
+
def call_safe(input = Undefined)
|
16
42
|
case input
|
17
|
-
when Dry::Monads::Maybe
|
43
|
+
when ::Dry::Monads::Maybe
|
18
44
|
input
|
19
45
|
when Undefined
|
20
46
|
None()
|
21
47
|
else
|
22
|
-
Maybe(type
|
48
|
+
Maybe(type.call_safe(input) { |output = input| return yield(output) })
|
23
49
|
end
|
24
50
|
end
|
25
|
-
alias_method :[], :call
|
26
51
|
|
27
52
|
# @param [Object] input
|
53
|
+
#
|
28
54
|
# @return [Result::Success]
|
55
|
+
#
|
56
|
+
# @api public
|
29
57
|
def try(input = Undefined)
|
30
|
-
|
31
|
-
None()
|
32
|
-
else
|
33
|
-
Maybe(type[input])
|
34
|
-
end
|
58
|
+
result = type.try(input)
|
35
59
|
|
36
|
-
|
60
|
+
if result.success?
|
61
|
+
Result::Success.new(Maybe(result.input))
|
62
|
+
else
|
63
|
+
result
|
64
|
+
end
|
37
65
|
end
|
38
66
|
|
39
67
|
# @return [true]
|
68
|
+
#
|
69
|
+
# @api public
|
40
70
|
def default?
|
41
71
|
true
|
42
72
|
end
|
43
73
|
|
44
74
|
# @param [Object] value
|
75
|
+
#
|
45
76
|
# @see Dry::Types::Builder#default
|
77
|
+
#
|
46
78
|
# @raise [ArgumentError] if nil provided as default value
|
79
|
+
#
|
80
|
+
# @api public
|
47
81
|
def default(value)
|
48
82
|
if value.nil?
|
49
83
|
raise ArgumentError, "nil cannot be used as a default of a maybe type"
|
@@ -54,15 +88,39 @@ module Dry
|
|
54
88
|
end
|
55
89
|
|
56
90
|
module Builder
|
91
|
+
# Turn a type into a maybe type
|
92
|
+
#
|
57
93
|
# @return [Maybe]
|
94
|
+
#
|
95
|
+
# @api public
|
96
|
+
def maybe
|
97
|
+
Maybe.new(Types["nil"] | self)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# @api private
|
102
|
+
class Schema::Key
|
103
|
+
# @api private
|
58
104
|
def maybe
|
59
|
-
|
105
|
+
__new__(type.maybe)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# @api private
|
110
|
+
class Printer
|
111
|
+
MAPPING[Maybe] = :visit_maybe
|
112
|
+
|
113
|
+
# @api private
|
114
|
+
def visit_maybe(maybe)
|
115
|
+
visit(maybe.type) do |type|
|
116
|
+
yield "Maybe<#{type}>"
|
117
|
+
end
|
60
118
|
end
|
61
119
|
end
|
62
120
|
|
63
121
|
# Register non-coercible maybe types
|
64
122
|
NON_NIL.each_key do |name|
|
65
|
-
register("maybe.strict.#{name}", self[
|
123
|
+
register("maybe.strict.#{name}", self[name.to_s].maybe)
|
66
124
|
end
|
67
125
|
|
68
126
|
# Register coercible maybe types
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/monads/result"
|
4
|
+
|
5
|
+
module Dry
|
6
|
+
module Types
|
7
|
+
# Monad extension for Result
|
8
|
+
#
|
9
|
+
# @api public
|
10
|
+
class Result
|
11
|
+
include Dry::Monads::Result::Mixin
|
12
|
+
|
13
|
+
# Turn result into a monad
|
14
|
+
#
|
15
|
+
# This makes result objects work with dry-monads (or anything with a compatible interface)
|
16
|
+
#
|
17
|
+
# @return [Dry::Monads::Success,Dry::Monads::Failure]
|
18
|
+
#
|
19
|
+
# @api public
|
20
|
+
def to_monad
|
21
|
+
if success?
|
22
|
+
Success(input)
|
23
|
+
else
|
24
|
+
Failure([error, input])
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/dry/types/extensions.rb
CHANGED
@@ -1,7 +1,12 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/types/container"
|
2
4
|
|
3
5
|
module Dry
|
4
6
|
module Types
|
7
|
+
# Internal container for constructor functions used by the built-in types
|
8
|
+
#
|
9
|
+
# @api private
|
5
10
|
class FnContainer
|
6
11
|
# @api private
|
7
12
|
def self.container
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/types/constructor"
|
4
|
+
|
5
|
+
module Dry
|
6
|
+
module Types
|
7
|
+
# Hash type exposes additional APIs for working with schema hashes
|
8
|
+
#
|
9
|
+
# @api public
|
10
|
+
class Hash < Nominal
|
11
|
+
class Constructor < ::Dry::Types::Constructor
|
12
|
+
# @api private
|
13
|
+
def constructor_type
|
14
|
+
::Dry::Types::Hash::Constructor
|
15
|
+
end
|
16
|
+
|
17
|
+
# @return [Lax]
|
18
|
+
#
|
19
|
+
# @api public
|
20
|
+
def lax
|
21
|
+
type.lax.constructor(fn, meta: meta)
|
22
|
+
end
|
23
|
+
|
24
|
+
# @see Dry::Types::Array#of
|
25
|
+
#
|
26
|
+
# @api public
|
27
|
+
def schema(*args)
|
28
|
+
type.schema(*args).constructor(fn, meta: meta)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/dry/types/hash.rb
CHANGED
@@ -1,34 +1,44 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/types/hash/constructor"
|
2
4
|
|
3
5
|
module Dry
|
4
6
|
module Types
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
7
|
+
# Hash types can be used to define maps and schemas
|
8
|
+
#
|
9
|
+
# @api public
|
10
|
+
class Hash < Nominal
|
11
|
+
NOT_REQUIRED = {required: false}.freeze
|
12
|
+
|
13
|
+
# @overload schema(type_map, meta = EMPTY_HASH)
|
14
|
+
# @param [{Symbol => Dry::Types::Nominal}] type_map
|
15
|
+
# @param [Hash] meta
|
16
|
+
# @return [Dry::Types::Schema]
|
17
|
+
#
|
18
|
+
# @overload schema(keys)
|
19
|
+
# @param [Array<Dry::Types::Schema::Key>] key List of schema keys
|
20
|
+
# @param [Hash] meta
|
21
|
+
# @return [Dry::Types::Schema]
|
22
|
+
#
|
23
|
+
# @api public
|
24
|
+
def schema(keys_or_map, meta = EMPTY_HASH)
|
25
|
+
if keys_or_map.is_a?(::Array)
|
26
|
+
keys = keys_or_map
|
16
27
|
else
|
17
|
-
|
18
|
-
primitive,
|
19
|
-
**options,
|
20
|
-
member_types: member_types,
|
21
|
-
meta: meta,
|
22
|
-
hash_type: constructor
|
23
|
-
)
|
28
|
+
keys = build_keys(keys_or_map)
|
24
29
|
end
|
30
|
+
|
31
|
+
Schema.new(primitive, keys: keys, **options, meta: self.meta.merge(meta))
|
25
32
|
end
|
26
33
|
|
27
34
|
# Build a map type
|
28
35
|
#
|
29
36
|
# @param [Type] key_type
|
30
37
|
# @param [Type] value_type
|
38
|
+
#
|
31
39
|
# @return [Map]
|
40
|
+
#
|
41
|
+
# @api public
|
32
42
|
def map(key_type, value_type)
|
33
43
|
Map.new(
|
34
44
|
primitive,
|
@@ -38,81 +48,90 @@ module Dry
|
|
38
48
|
)
|
39
49
|
end
|
40
50
|
|
41
|
-
# @param [{Symbol => Definition}] type_map
|
42
|
-
# @return [Schema]
|
43
|
-
def weak(type_map)
|
44
|
-
schema(type_map, :weak)
|
45
|
-
end
|
46
|
-
|
47
|
-
# @param [{Symbol => Definition}] type_map
|
48
|
-
# @return [Schema]
|
49
|
-
def permissive(type_map)
|
50
|
-
schema(type_map, :permissive)
|
51
|
-
end
|
52
|
-
|
53
|
-
# @param [{Symbol => Definition}] type_map
|
54
|
-
# @return [Schema]
|
55
|
-
def strict(type_map)
|
56
|
-
schema(type_map, :strict)
|
57
|
-
end
|
58
|
-
|
59
|
-
# @param [{Symbol => Definition}] type_map
|
60
|
-
# @return [Schema]
|
61
|
-
def strict_with_defaults(type_map)
|
62
|
-
schema(type_map, :strict_with_defaults)
|
63
|
-
end
|
64
|
-
|
65
|
-
# @param [{Symbol => Definition}] type_map
|
66
|
-
# @return [Schema]
|
67
|
-
def symbolized(type_map)
|
68
|
-
schema(type_map, :symbolized)
|
69
|
-
end
|
70
|
-
|
71
|
-
# Build a schema from an AST
|
72
51
|
# @api private
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
SCHEMA_BUILDER.instantiate(primitive, **options, member_types: member_types)
|
52
|
+
def weak(*)
|
53
|
+
raise "Support for old hash schemas was removed, please refer to the CHANGELOG "\
|
54
|
+
"on how to proceed with the new API https://github.com/dry-rb/dry-types/blob/master/CHANGELOG.md"
|
77
55
|
end
|
56
|
+
alias_method :permissive, :weak
|
57
|
+
alias_method :strict, :weak
|
58
|
+
alias_method :strict_with_defaults, :weak
|
59
|
+
alias_method :symbolized, :weak
|
78
60
|
|
79
61
|
# Injects a type transformation function for building schemas
|
62
|
+
#
|
80
63
|
# @param [#call,nil] proc
|
81
64
|
# @param [#call,nil] block
|
65
|
+
#
|
82
66
|
# @return [Hash]
|
67
|
+
#
|
68
|
+
# @api public
|
83
69
|
def with_type_transform(proc = nil, &block)
|
84
70
|
fn = proc || block
|
85
71
|
|
86
|
-
if fn.nil?
|
87
|
-
raise ArgumentError, "a block or callable argument is required"
|
88
|
-
end
|
72
|
+
raise ArgumentError, "a block or callable argument is required" if fn.nil?
|
89
73
|
|
90
74
|
handle = Dry::Types::FnContainer.register(fn)
|
91
|
-
|
75
|
+
with(type_transform_fn: handle)
|
76
|
+
end
|
77
|
+
|
78
|
+
# @api private
|
79
|
+
def constructor_type
|
80
|
+
::Dry::Types::Hash::Constructor
|
81
|
+
end
|
82
|
+
|
83
|
+
# Whether the type transforms types of schemas created by {Dry::Types::Hash#schema}
|
84
|
+
#
|
85
|
+
# @return [Boolean]
|
86
|
+
#
|
87
|
+
# @api public
|
88
|
+
def transform_types?
|
89
|
+
!options[:type_transform_fn].nil?
|
90
|
+
end
|
91
|
+
|
92
|
+
# @param meta [Boolean] Whether to dump the meta to the AST
|
93
|
+
#
|
94
|
+
# @return [Array] An AST representation
|
95
|
+
#
|
96
|
+
# @api public
|
97
|
+
def to_ast(meta: true)
|
98
|
+
[:hash, [options.slice(:type_transform_fn), meta ? self.meta : EMPTY_HASH]]
|
92
99
|
end
|
93
100
|
|
94
101
|
private
|
95
102
|
|
96
103
|
# @api private
|
97
|
-
def
|
98
|
-
type_fn =
|
104
|
+
def build_keys(type_map)
|
105
|
+
type_fn = options.fetch(:type_transform_fn, Schema::NO_TRANSFORM)
|
99
106
|
type_transform = Dry::Types::FnContainer[type_fn]
|
100
107
|
|
101
|
-
type_map.
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
}
|
108
|
+
type_map.map do |map_key, type|
|
109
|
+
name, options = key_name(map_key)
|
110
|
+
key = Schema::Key.new(resolve_type(type), name, **options)
|
111
|
+
type_transform.(key)
|
112
|
+
end
|
107
113
|
end
|
108
114
|
|
109
115
|
# @api private
|
110
116
|
def resolve_type(type)
|
111
117
|
case type
|
112
|
-
when
|
118
|
+
when Type then type
|
119
|
+
when ::Class, ::String then Types[type]
|
113
120
|
else type
|
114
121
|
end
|
115
122
|
end
|
123
|
+
|
124
|
+
# @api private
|
125
|
+
def key_name(key)
|
126
|
+
if key.to_s.end_with?("?")
|
127
|
+
[key.to_s.chop.to_sym, NOT_REQUIRED]
|
128
|
+
else
|
129
|
+
[key, EMPTY_HASH]
|
130
|
+
end
|
131
|
+
end
|
116
132
|
end
|
117
133
|
end
|
118
134
|
end
|
135
|
+
|
136
|
+
require "dry/types/schema/key"
|
137
|
+
require "dry/types/schema"
|