super-smart-tool 0.0.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.
Files changed (63) hide show
  1. checksums.yaml +7 -0
  2. data/dry-types-1.9.1/CHANGELOG.md +1145 -0
  3. data/dry-types-1.9.1/LICENSE +20 -0
  4. data/dry-types-1.9.1/README.md +17 -0
  5. data/dry-types-1.9.1/dry-types.gemspec +45 -0
  6. data/dry-types-1.9.1/lib/dry/types/any.rb +41 -0
  7. data/dry-types-1.9.1/lib/dry/types/array/constructor.rb +24 -0
  8. data/dry-types-1.9.1/lib/dry/types/array/member.rb +118 -0
  9. data/dry-types-1.9.1/lib/dry/types/array.rb +32 -0
  10. data/dry-types-1.9.1/lib/dry/types/builder.rb +221 -0
  11. data/dry-types-1.9.1/lib/dry/types/builder_methods.rb +138 -0
  12. data/dry-types-1.9.1/lib/dry/types/coercions/json.rb +57 -0
  13. data/dry-types-1.9.1/lib/dry/types/coercions/params.rb +168 -0
  14. data/dry-types-1.9.1/lib/dry/types/coercions.rb +105 -0
  15. data/dry-types-1.9.1/lib/dry/types/compat.rb +1 -0
  16. data/dry-types-1.9.1/lib/dry/types/compiler.rb +138 -0
  17. data/dry-types-1.9.1/lib/dry/types/composition.rb +138 -0
  18. data/dry-types-1.9.1/lib/dry/types/constrained/coercible.rb +59 -0
  19. data/dry-types-1.9.1/lib/dry/types/constrained.rb +146 -0
  20. data/dry-types-1.9.1/lib/dry/types/constraints.rb +30 -0
  21. data/dry-types-1.9.1/lib/dry/types/constructor/function.rb +203 -0
  22. data/dry-types-1.9.1/lib/dry/types/constructor/wrapper.rb +88 -0
  23. data/dry-types-1.9.1/lib/dry/types/constructor.rb +195 -0
  24. data/dry-types-1.9.1/lib/dry/types/container.rb +12 -0
  25. data/dry-types-1.9.1/lib/dry/types/core.rb +106 -0
  26. data/dry-types-1.9.1/lib/dry/types/decorator.rb +94 -0
  27. data/dry-types-1.9.1/lib/dry/types/default.rb +122 -0
  28. data/dry-types-1.9.1/lib/dry/types/enum.rb +121 -0
  29. data/dry-types-1.9.1/lib/dry/types/errors.rb +138 -0
  30. data/dry-types-1.9.1/lib/dry/types/extensions/maybe.rb +128 -0
  31. data/dry-types-1.9.1/lib/dry/types/extensions/monads.rb +34 -0
  32. data/dry-types-1.9.1/lib/dry/types/extensions.rb +9 -0
  33. data/dry-types-1.9.1/lib/dry/types/fn_container.rb +37 -0
  34. data/dry-types-1.9.1/lib/dry/types/hash/constructor.rb +25 -0
  35. data/dry-types-1.9.1/lib/dry/types/hash.rb +134 -0
  36. data/dry-types-1.9.1/lib/dry/types/implication.rb +64 -0
  37. data/dry-types-1.9.1/lib/dry/types/inflector.rb +9 -0
  38. data/dry-types-1.9.1/lib/dry/types/intersection.rb +102 -0
  39. data/dry-types-1.9.1/lib/dry/types/json.rb +35 -0
  40. data/dry-types-1.9.1/lib/dry/types/lax.rb +66 -0
  41. data/dry-types-1.9.1/lib/dry/types/map.rb +134 -0
  42. data/dry-types-1.9.1/lib/dry/types/meta.rb +53 -0
  43. data/dry-types-1.9.1/lib/dry/types/module.rb +127 -0
  44. data/dry-types-1.9.1/lib/dry/types/nominal.rb +201 -0
  45. data/dry-types-1.9.1/lib/dry/types/options.rb +34 -0
  46. data/dry-types-1.9.1/lib/dry/types/params.rb +38 -0
  47. data/dry-types-1.9.1/lib/dry/types/predicate_inferrer.rb +235 -0
  48. data/dry-types-1.9.1/lib/dry/types/predicate_registry.rb +32 -0
  49. data/dry-types-1.9.1/lib/dry/types/primitive_inferrer.rb +75 -0
  50. data/dry-types-1.9.1/lib/dry/types/printable.rb +14 -0
  51. data/dry-types-1.9.1/lib/dry/types/printer/composition.rb +44 -0
  52. data/dry-types-1.9.1/lib/dry/types/printer.rb +313 -0
  53. data/dry-types-1.9.1/lib/dry/types/result.rb +72 -0
  54. data/dry-types-1.9.1/lib/dry/types/schema/key.rb +138 -0
  55. data/dry-types-1.9.1/lib/dry/types/schema.rb +408 -0
  56. data/dry-types-1.9.1/lib/dry/types/spec/types.rb +164 -0
  57. data/dry-types-1.9.1/lib/dry/types/sum.rb +105 -0
  58. data/dry-types-1.9.1/lib/dry/types/type.rb +53 -0
  59. data/dry-types-1.9.1/lib/dry/types/version.rb +7 -0
  60. data/dry-types-1.9.1/lib/dry/types.rb +259 -0
  61. data/dry-types-1.9.1/lib/dry-types.rb +3 -0
  62. data/super-smart-tool.gemspec +11 -0
  63. metadata +101 -0
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015-2026 Hanakai team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,17 @@
1
+ <!--- This file is synced from hanakai-rb/repo-sync -->
2
+
3
+ [rubygem]: https://rubygems.org/gems/dry-types
4
+ [actions]: https://github.com/dry-rb/dry-types/actions
5
+
6
+ # dry-types [![Gem Version](https://badge.fury.io/rb/dry-types.svg)][rubygem] [![CI Status](https://github.com/dry-rb/dry-types/workflows/CI/badge.svg)][actions]
7
+
8
+ ## Links
9
+
10
+ - [User documentation](https://dry-rb.org/gems/dry-types)
11
+ - [API documentation](http://rubydoc.info/gems/dry-types)
12
+ - [Forum](https://discourse.dry-rb.org)
13
+
14
+ ## License
15
+
16
+ See `LICENSE` file.
17
+
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file is synced from hanakai-rb/repo-sync. To update it, edit repo-sync.yml.
4
+
5
+ lib = File.expand_path("lib", __dir__)
6
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
7
+ require "dry/types/version"
8
+
9
+ Gem::Specification.new do |spec|
10
+ spec.name = "dry-types"
11
+ spec.authors = ["Hanakai team"]
12
+ spec.email = ["info@hanakai.org"]
13
+ spec.license = "MIT"
14
+ spec.version = Dry::Types::VERSION.dup
15
+
16
+ spec.summary = "Type system for Ruby supporting coercions, constraints and complex types like structs, value objects, enums etc"
17
+ spec.description = spec.summary
18
+ spec.homepage = "https://dry-rb.org/gems/dry-types"
19
+ spec.files = Dir["CHANGELOG.md", "LICENSE", "README.md", "dry-types.gemspec", "lib/**/*"]
20
+ spec.bindir = "exe"
21
+ spec.executables = Dir["exe/*"].map { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.extra_rdoc_files = ["README.md", "CHANGELOG.md", "LICENSE"]
25
+
26
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
27
+ spec.metadata["changelog_uri"] = "https://github.com/dry-rb/dry-types/blob/main/CHANGELOG.md"
28
+ spec.metadata["source_code_uri"] = "https://github.com/dry-rb/dry-types"
29
+ spec.metadata["bug_tracker_uri"] = "https://github.com/dry-rb/dry-types/issues"
30
+ spec.metadata["funding_uri"] = "https://github.com/sponsors/hanami"
31
+
32
+ spec.required_ruby_version = ">= 3.2"
33
+
34
+ spec.add_runtime_dependency "bigdecimal", ">= 3.0"
35
+ spec.add_runtime_dependency "concurrent-ruby", "~> 1.0"
36
+ spec.add_runtime_dependency "dry-core", "~> 1.0"
37
+ spec.add_runtime_dependency "dry-inflector", "~> 1.0"
38
+ spec.add_runtime_dependency "dry-logic", "~> 1.4"
39
+ spec.add_runtime_dependency "zeitwerk", "~> 2.6"
40
+ spec.add_development_dependency "bundler"
41
+ spec.add_development_dependency "rake"
42
+ spec.add_development_dependency "rspec"
43
+ spec.add_development_dependency "yard"
44
+ end
45
+
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dry
4
+ module Types
5
+ # Any is a nominal type that defines Object as the primitive class
6
+ #
7
+ # This type is useful in places where you can't be specific about the type
8
+ # and anything is acceptable.
9
+ #
10
+ # @api public
11
+ class AnyClass < Nominal
12
+ def self.name = "Any"
13
+
14
+ # @api private
15
+ def initialize(**options)
16
+ super(::Object, **options)
17
+ end
18
+
19
+ # @return [String]
20
+ #
21
+ # @api public
22
+ def name = "Any"
23
+
24
+ # @param [Hash] new_options
25
+ #
26
+ # @return [Type]
27
+ #
28
+ # @api public
29
+ def with(**new_options)
30
+ self.class.new(**options, meta: @meta, **new_options)
31
+ end
32
+
33
+ # @return [Array]
34
+ #
35
+ # @api public
36
+ def to_ast(meta: true) = [:any, meta_ast(meta)]
37
+ end
38
+
39
+ Any = AnyClass.new
40
+ end
41
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dry
4
+ module Types
5
+ # @api public
6
+ class Array < Nominal
7
+ # @api private
8
+ class Constructor < ::Dry::Types::Constructor
9
+ # @api private
10
+ def constructor_type = ::Dry::Types::Array::Constructor
11
+
12
+ # @return [Lax]
13
+ #
14
+ # @api public
15
+ def lax = Lax.new(type.lax.constructor(fn, meta: meta))
16
+
17
+ # @see Dry::Types::Array#of
18
+ #
19
+ # @api public
20
+ def of(member) = type.of(member).constructor(fn, meta: meta)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dry
4
+ module Types
5
+ class Array < Nominal
6
+ # Member arrays define their member type that is applied to each element
7
+ #
8
+ # @api public
9
+ class Member < Array
10
+ # @return [Type]
11
+ attr_reader :member
12
+
13
+ # @param [Class] primitive
14
+ # @param [Hash] options
15
+ #
16
+ # @option options [Type] :member
17
+ #
18
+ # @api private
19
+ def initialize(primitive, **options)
20
+ @member = options.fetch(:member)
21
+ super
22
+ end
23
+
24
+ # @param [Object] input
25
+ #
26
+ # @return [Array]
27
+ #
28
+ # @api private
29
+ def call_unsafe(input)
30
+ if primitive?(input)
31
+ input.each_with_object([]) do |el, output|
32
+ coerced = member.call_unsafe(el)
33
+
34
+ output << coerced unless Undefined.equal?(coerced)
35
+ end
36
+ else
37
+ super
38
+ end
39
+ end
40
+
41
+ # @param [Object] input
42
+ # @return [Array]
43
+ #
44
+ # @api private
45
+ def call_safe(input, &block)
46
+ if primitive?(input)
47
+ failed = false
48
+
49
+ result = input.each_with_object([]) do |el, output|
50
+ coerced = member.call_safe(el) { |out = el|
51
+ failed = true
52
+ out
53
+ }
54
+
55
+ output << coerced unless Undefined.equal?(coerced)
56
+ end
57
+
58
+ failed ? block.call(result) : result
59
+ else
60
+ block.call
61
+ end
62
+ end
63
+
64
+ # @param [Array, Object] input
65
+ # @param [#call,nil] block
66
+ #
67
+ # @yieldparam [Failure] failure
68
+ # @yieldreturn [Result]
69
+ #
70
+ # @return [Result,Logic::Result]
71
+ #
72
+ # @api public
73
+ def try(input, &block) # rubocop:disable Metrics/PerceivedComplexity
74
+ if primitive?(input)
75
+ output = []
76
+
77
+ result = input.map { |el| member.try(el) }
78
+ result.each do |r|
79
+ output << r.input unless Undefined.equal?(r.input)
80
+ end
81
+
82
+ if result.all?(&:success?)
83
+ success(output)
84
+ else
85
+ error = result.find(&:failure?).error
86
+ failure = failure(output, error)
87
+ block ? yield(failure) : failure
88
+ end
89
+ else
90
+ failure = failure(input, CoercionError.new("#{input} is not an array"))
91
+ block ? yield(failure) : failure
92
+ end
93
+ end
94
+
95
+ # Build a lax type
96
+ #
97
+ # @return [Lax]
98
+ #
99
+ # @api public
100
+ def lax = Lax.new(Member.new(primitive, **options, member: member.lax, meta: meta))
101
+
102
+ # @see Nominal#to_ast
103
+ #
104
+ # @api public
105
+ def to_ast(meta: true)
106
+ if member.respond_to?(:to_ast)
107
+ [:array, [member.to_ast(meta: meta), meta_ast(meta)]]
108
+ else
109
+ [:array, [member, meta_ast(meta)]]
110
+ end
111
+ end
112
+
113
+ # @api private
114
+ def constructor_type = ::Dry::Types::Array::Constructor
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dry
4
+ module Types
5
+ # Array type can be used to define an array with optional member type
6
+ #
7
+ # @api public
8
+ class Array < Nominal
9
+ # Build an array type with a member type
10
+ #
11
+ # @param [Type,#call] type
12
+ #
13
+ # @return [Array::Member]
14
+ #
15
+ # @api public
16
+ def of(type)
17
+ member =
18
+ case type
19
+ when ::String then Types[type]
20
+ else type
21
+ end
22
+
23
+ Array::Member.new(primitive, **options, member: member)
24
+ end
25
+
26
+ # @api private
27
+ def constructor_type
28
+ ::Dry::Types::Array::Constructor
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,221 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dry
4
+ module Types
5
+ # Common API for building types and composition
6
+ #
7
+ # @api public
8
+ module Builder
9
+ include ::Dry::Core::Constants
10
+
11
+ # @return [Class]
12
+ #
13
+ # @api private
14
+ def constrained_type = Constrained
15
+
16
+ # @return [Class]
17
+ #
18
+ # @api private
19
+ def constructor_type = Constructor
20
+
21
+ # Compose two types into a Sum type
22
+ #
23
+ # @param [Type] other
24
+ #
25
+ # @return [Sum, Sum::Constrained]
26
+ #
27
+ # @api private
28
+ def |(other) = compose(other, Sum)
29
+
30
+ # Compose two types into an Intersection type
31
+ #
32
+ # @param [Type] other
33
+ #
34
+ # @return [Intersection, Intersection::Constrained]
35
+ #
36
+ # @api private
37
+ def &(other) = compose(other, Intersection)
38
+
39
+ # Compose two types into an Implication type
40
+ #
41
+ # @param [Type] other
42
+ #
43
+ # @return [Implication, Implication::Constrained]
44
+ #
45
+ # @api private
46
+ def >(other) = compose(other, Implication)
47
+
48
+ # Turn a type into an optional type
49
+ #
50
+ # @return [Sum]
51
+ #
52
+ # @api public
53
+ def optional
54
+ nil_type =
55
+ if Types.use_namespaced_optionals && respond_to?(:namespace) && namespace
56
+ Types["#{namespace}.nil"]
57
+ else
58
+ Types["nil"]
59
+ end
60
+
61
+ nil_type | self
62
+ end
63
+
64
+ # Turn a type into a constrained type
65
+ #
66
+ # @param [Hash] options constraining rule (see {Types.Rule})
67
+ #
68
+ # @return [Constrained]
69
+ #
70
+ # @api public
71
+ def constrained(...)
72
+ constrained_type.new(self, rule: Types.Rule(...))
73
+ end
74
+
75
+ # Turn a type into a type with a default value
76
+ #
77
+ # @param [Object] input
78
+ # @option [Boolean] shared Whether it's safe to share the value across type applications
79
+ # @param [#call,nil] block
80
+ #
81
+ # @raise [ConstraintError]
82
+ #
83
+ # @return [Default]
84
+ #
85
+ # @api public
86
+ def default(input = Undefined, options = EMPTY_HASH, &block)
87
+ unless input.frozen? || options[:shared]
88
+ where = Core::Deprecations::STACK.()
89
+
90
+ # There is a weird behaviour in JRuby where the source_location is mutated upon
91
+ # calling `inspect` on proc (see: https://github.com/jruby/jruby/issues/9110)
92
+ # To bypass this, we call inspect on the clone (but only for proc and JRuby).
93
+ # This should be fixes in JRuby 10.0.3.0.
94
+ obj = input.is_a?(Proc) && RUBY_ENGINE == "jruby" ? input.dup : input
95
+
96
+ Core::Deprecations.warn(
97
+ "#{obj.inspect} is mutable. " \
98
+ "Be careful: types will return the same instance of the default " \
99
+ "value every time. Call `.freeze` when setting the default " \
100
+ "or pass `shared: true` to discard this warning." \
101
+ "\n#{where}",
102
+ tag: :"dry-types"
103
+ )
104
+ end
105
+
106
+ value = Undefined.default(input, block)
107
+ type = Default[value].new(self, value)
108
+
109
+ if !type.callable? && !valid?(value)
110
+ raise ConstraintError.new(
111
+ "default value #{value.inspect} violates constraints",
112
+ value
113
+ )
114
+ else
115
+ type
116
+ end
117
+ end
118
+
119
+ # Define an enum on top of the existing type
120
+ #
121
+ # @param [Array] values
122
+ #
123
+ # @return [Enum]
124
+ #
125
+ # @api public
126
+ def enum(*values)
127
+ mapping =
128
+ if values.length == 1 && values[0].is_a?(::Hash)
129
+ values[0]
130
+ else
131
+ values.zip(values).to_h
132
+ end
133
+
134
+ Enum.new(constrained(included_in: mapping.keys), mapping: mapping)
135
+ end
136
+
137
+ # Turn a type into a lax type that will rescue from type-errors and
138
+ # return the original input
139
+ #
140
+ # @return [Lax]
141
+ #
142
+ # @api public
143
+ def lax = Lax.new(self)
144
+
145
+ # Define a constructor for the type
146
+ #
147
+ # @param [#call,nil] constructor
148
+ # @param [Hash] options
149
+ # @param [#call,nil] block
150
+ #
151
+ # @return [Constructor]
152
+ #
153
+ # @api public
154
+ def constructor(constructor = nil, **options, &block)
155
+ constructor_type[with(**options), fn: constructor || block]
156
+ end
157
+ alias_method :append, :constructor
158
+ alias_method :prepend, :constructor
159
+ alias_method :>>, :constructor
160
+ alias_method :<<, :constructor
161
+
162
+ # Use the given value on type mismatch
163
+ #
164
+ # @param [Object] value
165
+ # @option [Boolean] shared Whether it's safe to share the value across type applications
166
+ # @param [#call,nil] fallback
167
+ #
168
+ # @return [Constructor]
169
+ #
170
+ # @api public
171
+ def fallback(value = Undefined, shared: false, &_fallback) # rubocop:disable Metrics/PerceivedComplexity
172
+ if Undefined.equal?(value) && !block_given?
173
+ raise ::ArgumentError, "fallback value or a block must be given"
174
+ end
175
+
176
+ if !block_given? && !valid?(value)
177
+ raise ConstraintError.new(
178
+ "fallback value #{value.inspect} violates constraints",
179
+ value
180
+ )
181
+ end
182
+
183
+ unless value.frozen? || shared
184
+ where = Core::Deprecations::STACK.()
185
+ Core::Deprecations.warn(
186
+ "#{value.inspect} is mutable. " \
187
+ "Be careful: types will return the same instance of the fallback " \
188
+ "value every time. Call `.freeze` when setting the fallback " \
189
+ "or pass `shared: true` to discard this warning." \
190
+ "\n#{where}",
191
+ tag: :"dry-types"
192
+ )
193
+ end
194
+
195
+ constructor do |input, type, &|
196
+ type.(input) do |output = input|
197
+ if block_given?
198
+ yield(output)
199
+ else
200
+ value
201
+ end
202
+ end
203
+ end
204
+ end
205
+
206
+ private
207
+
208
+ # @api private
209
+ def compose(other, composition_class)
210
+ klass =
211
+ if constrained? && other.constrained?
212
+ composition_class::Constrained
213
+ else
214
+ composition_class
215
+ end
216
+
217
+ klass.new(self, other)
218
+ end
219
+ end
220
+ end
221
+ end
@@ -0,0 +1,138 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dry
4
+ module Types
5
+ # Common API for building type objects in a convenient way
6
+ #
7
+ #
8
+ # @api public
9
+ module BuilderMethods
10
+ # @api private
11
+ def included(base)
12
+ super
13
+ base.extend(BuilderMethods)
14
+ end
15
+
16
+ # Build an array type.
17
+ #
18
+ # Shortcut for Array#of.
19
+ #
20
+ # @example
21
+ # Types::Strings = Types.Array(Types::String)
22
+ #
23
+ # @param [Dry::Types::Type] type
24
+ #
25
+ # @return [Dry::Types::Array]
26
+ def Array(type) = Strict(::Array).of(type)
27
+
28
+ # Build a hash schema
29
+ #
30
+ # @param [Hash{Symbol => Dry::Types::Type}] type_map
31
+ #
32
+ # @return [Dry::Types::Array]
33
+ def Hash(type_map) = Strict(::Hash).schema(type_map)
34
+
35
+ # Build a type which values are instances of a given class
36
+ # Values are checked using `is_a?` call
37
+ #
38
+ # @example
39
+ # Types::Error = Types.Instance(StandardError)
40
+ # Types::Error = Types.Strict(StandardError)
41
+ # Types.Strict(Integer) == Types::Strict::Int # => true
42
+ #
43
+ # @param [Class,Module] klass Class or module
44
+ #
45
+ # @return [Dry::Types::Type]
46
+ def Instance(klass)
47
+ unless klass.is_a?(::Module)
48
+ raise ::ArgumentError, "Expected a class or module, got #{klass.inspect}"
49
+ end
50
+
51
+ Nominal(klass).constrained(type: klass)
52
+ end
53
+
54
+ alias_method :Strict, :Instance
55
+
56
+ # Build a type with a single value
57
+ # The equality check done with `eql?`
58
+ #
59
+ # @param [Object] value
60
+ #
61
+ # @return [Dry::Types::Type]
62
+ def Value(value) = Nominal(value.class).constrained(eql: value)
63
+
64
+ # Build a type with a single value
65
+ # The equality check done with `equal?`
66
+ #
67
+ # @param [Object] object
68
+ #
69
+ # @return [Dry::Types::Type]
70
+ def Constant(object) = Nominal(object.class).constrained(is: object)
71
+
72
+ # Build a constructor type
73
+ # If no constructor block given it uses .new method
74
+ #
75
+ # @param [Class] klass
76
+ # @param [#call,nil] cons Value constructor
77
+ # @param [#call,nil] block Value constructor
78
+ #
79
+ # @return [Dry::Types::Type]
80
+ def Constructor(klass, cons = nil, &block) # rubocop:disable Metrics/PerceivedComplexity:
81
+ if klass.is_a?(Type)
82
+ if cons || block
83
+ klass.constructor(cons || block)
84
+ else
85
+ klass
86
+ end
87
+ else
88
+ Nominal(klass).constructor(cons || block || klass.method(:new))
89
+ end
90
+ end
91
+
92
+ # Build a nominal type
93
+ #
94
+ # @param [Class] klass
95
+ #
96
+ # @return [Dry::Types::Type]
97
+ def Nominal(klass)
98
+ if klass <= ::Array
99
+ Array.new(klass)
100
+ elsif klass <= ::Hash
101
+ Hash.new(klass)
102
+ else
103
+ Nominal.new(klass)
104
+ end
105
+ end
106
+
107
+ # Build a map type
108
+ #
109
+ # @example
110
+ # Types::IntMap = Types.Map(Types::Strict::Integer, 'any')
111
+ # Types::IntStringMap = Types.Map(Types::Strict::Integer, Types::Strict::String)
112
+ #
113
+ # @param [Type] key_type Key type
114
+ # @param [Type] value_type Value type
115
+ #
116
+ # @return [Dry::Types::Map]
117
+ def Map(key_type, value_type)
118
+ Nominal(::Hash).map(key_type, value_type)
119
+ end
120
+
121
+ # Builds a constrained nominal type accepting any value that
122
+ # responds to given methods
123
+ #
124
+ # @example
125
+ # Types::Callable = Types.Interface(:call)
126
+ # Types::Contact = Types.Interface(:name, :address)
127
+ #
128
+ # @param methods [Array<String, Symbol>] Method names
129
+ #
130
+ # @return [Dry::Types::Contrained]
131
+ def Interface(*methods)
132
+ methods.reduce(Types["nominal.any"]) do |type, method|
133
+ type.constrained(respond_to: method)
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end