domainic-type 0.1.0.alpha.2.1.0 → 0.1.0.alpha.3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +14 -0
  3. data/LICENSE +1 -1
  4. data/README.md +28 -4
  5. data/lib/domainic/type/accessors.rb +41 -0
  6. data/lib/domainic/type/behavior/enumerable_behavior.rb +262 -0
  7. data/lib/domainic/type/behavior/numeric_behavior.rb +340 -0
  8. data/lib/domainic/type/behavior/sizable_behavior.rb +246 -0
  9. data/lib/domainic/type/behavior/string_behavior.rb +379 -0
  10. data/lib/domainic/type/behavior.rb +239 -0
  11. data/lib/domainic/type/config/registry.yml +101 -0
  12. data/lib/domainic/type/constraint/behavior.rb +342 -0
  13. data/lib/domainic/type/constraint/constraints/all_constraint.rb +81 -0
  14. data/lib/domainic/type/constraint/constraints/and_constraint.rb +105 -0
  15. data/lib/domainic/type/constraint/constraints/any_constraint.rb +83 -0
  16. data/lib/domainic/type/constraint/constraints/case_constraint.rb +104 -0
  17. data/lib/domainic/type/constraint/constraints/character_set_constraint.rb +111 -0
  18. data/lib/domainic/type/constraint/constraints/divisibility_constraint.rb +126 -0
  19. data/lib/domainic/type/constraint/constraints/emptiness_constraint.rb +69 -0
  20. data/lib/domainic/type/constraint/constraints/equality_constraint.rb +75 -0
  21. data/lib/domainic/type/constraint/constraints/finiteness_constraint.rb +123 -0
  22. data/lib/domainic/type/constraint/constraints/inclusion_constraint.rb +74 -0
  23. data/lib/domainic/type/constraint/constraints/match_pattern_constraint.rb +87 -0
  24. data/lib/domainic/type/constraint/constraints/method_presence_constraint.rb +72 -0
  25. data/lib/domainic/type/constraint/constraints/none_constraint.rb +83 -0
  26. data/lib/domainic/type/constraint/constraints/nor_constraint.rb +105 -0
  27. data/lib/domainic/type/constraint/constraints/not_constraint.rb +76 -0
  28. data/lib/domainic/type/constraint/constraints/or_constraint.rb +106 -0
  29. data/lib/domainic/type/constraint/constraints/ordering_constraint.rb +75 -0
  30. data/lib/domainic/type/constraint/constraints/parity_constraint.rb +102 -0
  31. data/lib/domainic/type/constraint/constraints/polarity_constraint.rb +147 -0
  32. data/lib/domainic/type/constraint/constraints/range_constraint.rb +135 -0
  33. data/lib/domainic/type/constraint/constraints/type_constraint.rb +110 -0
  34. data/lib/domainic/type/constraint/constraints/uniqueness_constraint.rb +69 -0
  35. data/lib/domainic/type/constraint/resolver.rb +172 -0
  36. data/lib/domainic/type/constraint/set.rb +266 -0
  37. data/lib/domainic/type/definitions.rb +364 -0
  38. data/lib/domainic/type/types/core/array_type.rb +48 -0
  39. data/lib/domainic/type/types/core/float_type.rb +39 -0
  40. data/lib/domainic/type/types/core/hash_type.rb +143 -0
  41. data/lib/domainic/type/types/core/integer_type.rb +38 -0
  42. data/lib/domainic/type/types/core/string_type.rb +51 -0
  43. data/lib/domainic/type/types/core/symbol_type.rb +51 -0
  44. data/lib/domainic/type/types/specification/anything_type.rb +22 -0
  45. data/lib/domainic/type/types/specification/duck_type.rb +55 -0
  46. data/lib/domainic/type/types/specification/enum_type.rb +26 -0
  47. data/lib/domainic/type/types/specification/union_type.rb +26 -0
  48. data/lib/domainic/type/types/specification/void_type.rb +12 -0
  49. data/lib/domainic/type.rb +7 -0
  50. data/lib/domainic-type.rb +3 -0
  51. data/sig/domainic/type/accessors.rbs +22 -0
  52. data/sig/domainic/type/behavior/enumerable_behavior.rbs +238 -0
  53. data/sig/domainic/type/behavior/numeric_behavior.rbs +299 -0
  54. data/sig/domainic/type/behavior/sizable_behavior.rbs +218 -0
  55. data/sig/domainic/type/behavior/string_behavior.rbs +315 -0
  56. data/sig/domainic/type/behavior.rbs +153 -0
  57. data/sig/domainic/type/constraint/behavior.rbs +258 -0
  58. data/sig/domainic/type/constraint/constraints/all_constraint.rbs +55 -0
  59. data/sig/domainic/type/constraint/constraints/and_constraint.rbs +72 -0
  60. data/sig/domainic/type/constraint/constraints/any_constraint.rbs +57 -0
  61. data/sig/domainic/type/constraint/constraints/case_constraint.rbs +73 -0
  62. data/sig/domainic/type/constraint/constraints/character_set_constraint.rbs +82 -0
  63. data/sig/domainic/type/constraint/constraints/divisibility_constraint.rbs +91 -0
  64. data/sig/domainic/type/constraint/constraints/emptiness_constraint.rbs +54 -0
  65. data/sig/domainic/type/constraint/constraints/equality_constraint.rbs +60 -0
  66. data/sig/domainic/type/constraint/constraints/finiteness_constraint.rbs +82 -0
  67. data/sig/domainic/type/constraint/constraints/inclusion_constraint.rbs +59 -0
  68. data/sig/domainic/type/constraint/constraints/match_pattern_constraint.rbs +66 -0
  69. data/sig/domainic/type/constraint/constraints/method_presence_constraint.rbs +51 -0
  70. data/sig/domainic/type/constraint/constraints/none_constraint.rbs +57 -0
  71. data/sig/domainic/type/constraint/constraints/nor_constraint.rbs +72 -0
  72. data/sig/domainic/type/constraint/constraints/not_constraint.rbs +56 -0
  73. data/sig/domainic/type/constraint/constraints/or_constraint.rbs +74 -0
  74. data/sig/domainic/type/constraint/constraints/ordering_constraint.rbs +60 -0
  75. data/sig/domainic/type/constraint/constraints/parity_constraint.rbs +71 -0
  76. data/sig/domainic/type/constraint/constraints/polarity_constraint.rbs +101 -0
  77. data/sig/domainic/type/constraint/constraints/range_constraint.rbs +88 -0
  78. data/sig/domainic/type/constraint/constraints/type_constraint.rbs +86 -0
  79. data/sig/domainic/type/constraint/constraints/uniqueness_constraint.rbs +54 -0
  80. data/sig/domainic/type/constraint/resolver.rbs +117 -0
  81. data/sig/domainic/type/constraint/set.rbs +159 -0
  82. data/sig/domainic/type/definitions.rbs +304 -0
  83. data/sig/domainic/type/types/core/array_type.rbs +42 -0
  84. data/sig/domainic/type/types/core/float_type.rbs +33 -0
  85. data/sig/domainic/type/types/core/hash_type.rbs +107 -0
  86. data/sig/domainic/type/types/core/integer_type.rbs +32 -0
  87. data/sig/domainic/type/types/core/string_type.rbs +45 -0
  88. data/sig/domainic/type/types/core/symbol_type.rbs +45 -0
  89. data/sig/domainic/type/types/specification/anything_type.rbs +14 -0
  90. data/sig/domainic/type/types/specification/duck_type.rbs +41 -0
  91. data/sig/domainic/type/types/specification/enum_type.rbs +14 -0
  92. data/sig/domainic/type/types/specification/union_type.rbs +14 -0
  93. data/sig/domainic/type/types/specification/void_type.rbs +8 -0
  94. data/sig/domainic/type.rbs +5 -0
  95. data/sig/domainic-type.rbs +1 -0
  96. data/sig/manifest.yaml +2 -0
  97. metadata +108 -71
@@ -0,0 +1,364 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Domainic
4
+ module Type
5
+ # A module providing convenient factory methods for creating type instances.
6
+ #
7
+ # This module serves as a temporary access point for type creation in the Domainic::Type
8
+ # system, offering a collection of factory methods with consistent naming patterns.
9
+ # Each method creates and configures a specific type instance, with optional nilable
10
+ # variants and aliases for common use cases.
11
+ #
12
+ # @note This module is considered temporary and may be significantly altered or removed
13
+ # before the final release. It should not be considered part of the stable API.
14
+ #
15
+ # @example Basic type creation
16
+ # include Domainic::Type::Definitions
17
+ #
18
+ # string_type = _String()
19
+ # array_type = _Array()
20
+ # hash_type = _Hash()
21
+ #
22
+ # @example Creating nilable types
23
+ # nullable_string = _String?()
24
+ # nullable_array = _Array?()
25
+ #
26
+ # @example Using union types
27
+ # string_or_symbol = _Union(String, Symbol)
28
+ # boolean = _Boolean() # Union of TrueClass and FalseClass
29
+ #
30
+ # @author {https://aaronmallen.me Aaron Allen}
31
+ # @since 0.1.0
32
+ module Definitions
33
+ # rubocop:disable Naming/MethodName
34
+
35
+ # Creates an AnythingType instance.
36
+ #
37
+ # @example
38
+ # type = _Anything
39
+ #
40
+ # @param options [Hash] additional configuration options
41
+ #
42
+ # @return [Domainic::Type::AnythingType] the created type
43
+ # @rbs (**__todo__ options) -> AnythingType
44
+ def _Anything(**options)
45
+ require 'domainic/type/types/specification/anything_type'
46
+ Domainic::Type::AnythingType.new(**options)
47
+ end
48
+ alias _Any _Anything
49
+
50
+ # Creates an ArrayType instance.
51
+ #
52
+ # @example
53
+ # type = _Array
54
+ #
55
+ # @param options [Hash] additional configuration options
56
+ #
57
+ # @return [Domainic::Type::ArrayType] the created type
58
+ # @rbs (**__todo__ options) -> ArrayType
59
+ def _Array(**options)
60
+ require 'domainic/type/types/core/array_type'
61
+ Domainic::Type::ArrayType.new(**options)
62
+ end
63
+ alias _List _Array
64
+
65
+ # Creates a nilable ArrayType instance.
66
+ #
67
+ # @example
68
+ # type = _Array?
69
+ #
70
+ # @param options [Hash] additional configuration options
71
+ #
72
+ # @return [Domainic::Type::UnionType] the created type (Array or NilClass)
73
+ # @rbs (**__todo__ options) -> UnionType
74
+ def _Array?(**options)
75
+ array = _Array(**options)
76
+ _Nilable(array)
77
+ end
78
+ alias _List? _Array?
79
+
80
+ # Creates a Boolean type.
81
+ #
82
+ # Represents a union of TrueClass and FalseClass.
83
+ #
84
+ # @example
85
+ # type = _Boolean
86
+ #
87
+ # @return [Domainic::Type::UnionType] the created type
88
+ # @rbs () -> UnionType
89
+ def _Boolean
90
+ _Union(TrueClass, FalseClass).freeze
91
+ end
92
+ alias _Bool _Boolean
93
+
94
+ # Creates a nilable Boolean type.
95
+ #
96
+ # @example
97
+ # type = _Boolean?
98
+ #
99
+ # @return [Domainic::Type::UnionType] the created type (TrueClass, FalseClass, or NilClass)
100
+ # @rbs () -> UnionType
101
+ def _Boolean?
102
+ _Nilable(_Boolean)
103
+ end
104
+ alias _Bool? _Boolean?
105
+
106
+ # Creates a DuckType instance.
107
+ #
108
+ # DuckType allows specifying behavior based on method availability.
109
+ #
110
+ # @example
111
+ # type = _Duck(respond_to: :to_s)
112
+ #
113
+ # @param options [Hash] additional configuration options
114
+ #
115
+ # @return [Domainic::Type::DuckType] the created type
116
+ # @rbs (**__todo__ options) -> DuckType
117
+ def _Duck(**options)
118
+ require 'domainic/type/types/specification/duck_type'
119
+ Domainic::Type::DuckType.new(**options)
120
+ end
121
+ alias _Interface _Duck
122
+ alias _Protocol _Duck
123
+ alias _RespondingTo _Duck
124
+
125
+ # Creates an EnumType instance.
126
+ #
127
+ # EnumType restricts values to a specific set of literals.
128
+ #
129
+ # @example
130
+ # type = _Enum(:red, :green, :blue)
131
+ #
132
+ # @param literals [Array<Object>] the allowed literals
133
+ # @param options [Hash] additional configuration options
134
+ #
135
+ # @return [Domainic::Type::EnumType] the created type
136
+ # @rbs (*untyped literals, **__todo__ options) -> EnumType
137
+ def _Enum(*literals, **options)
138
+ require 'domainic/type/types/specification/enum_type'
139
+ Domainic::Type::EnumType.new(*literals, **options)
140
+ end
141
+ alias _Literal _Enum
142
+
143
+ # Creates a nilable EnumType instance.
144
+ #
145
+ # @example
146
+ # type = _Enum?(:red, :green, :blue)
147
+ #
148
+ # @param literals [Array<Object>] the allowed literals
149
+ # @param options [Hash] additional configuration options
150
+ #
151
+ # @return [Domainic::Type::UnionType] the created type (Enum or NilClass)
152
+ # @rbs (*untyped literals, **__todo__ options) -> UnionType
153
+ def _Enum?(*literals, **options)
154
+ enum = _Enum(*literals, **options)
155
+ _Nilable(enum)
156
+ end
157
+ alias _Literal? _Enum?
158
+
159
+ # Creates a FloatType instance.
160
+ #
161
+ # @example
162
+ # type = _Float
163
+ #
164
+ # @param options [Hash] additional configuration options
165
+ #
166
+ # @return [Domainic::Type::FloatType] the created type
167
+ # @rbs (**__todo__ options) -> FloatType
168
+ def _Float(**options)
169
+ require 'domainic/type/types/core/float_type'
170
+ Domainic::Type::FloatType.new(**options)
171
+ end
172
+ alias _Decimal _Float
173
+ alias _Real _Float
174
+
175
+ # Creates a nilable FloatType instance.
176
+ #
177
+ # @example
178
+ # type = _Float?
179
+ #
180
+ # @param options [Hash] additional configuration options
181
+ #
182
+ # @return [Domainic::Type::UnionType] the created type (Float or NilClass)
183
+ # @rbs (**__todo__ options) -> UnionType
184
+ def _Float?(**options)
185
+ float = _Float(**options)
186
+ _Nilable(float)
187
+ end
188
+ alias _Decimal? _Float?
189
+ alias _Real? _Float?
190
+
191
+ # Creates a HashType instance.
192
+ #
193
+ # @example
194
+ # type = _Hash
195
+ #
196
+ # @param options [Hash] additional configuration options
197
+ #
198
+ # @return [Domainic::Type::HashType] the created type
199
+ # @rbs (**__todo__ options) -> HashType
200
+ def _Hash(**options)
201
+ require 'domainic/type/types/core/hash_type'
202
+ Domainic::Type::HashType.new(**options)
203
+ end
204
+ alias _Map _Hash
205
+
206
+ # Creates a nilable HashType instance.
207
+ #
208
+ # @example
209
+ # type = _Hash?
210
+ #
211
+ # @param options [Hash] additional configuration options
212
+ #
213
+ # @return [Domainic::Type::UnionType] the created type (Hash or NilClass)
214
+ # @rbs (**__todo__ options) -> UnionType
215
+ def _Hash?(**options)
216
+ hash = _Hash(**options)
217
+ _Nilable(hash)
218
+ end
219
+ alias _Map? _Hash?
220
+
221
+ # Creates an IntegerType instance.
222
+ #
223
+ # @example
224
+ # type = _Integer
225
+ #
226
+ # @param options [Hash] additional configuration options
227
+ #
228
+ # @return [Domainic::Type::IntegerType] the created type
229
+ # @rbs (**__todo__ options) -> IntegerType
230
+ def _Integer(**options)
231
+ require 'domainic/type/types/core/integer_type'
232
+ Domainic::Type::IntegerType.new(**options)
233
+ end
234
+ alias _Int _Integer
235
+ alias _Number _Integer
236
+
237
+ # Creates a nilable IntegerType instance.
238
+ #
239
+ # @example
240
+ # type = _Integer?
241
+ #
242
+ # @param options [Hash] additional configuration options
243
+ #
244
+ # @return [Domainic::Type::UnionType] the created type (Integer or NilClass)
245
+ # @rbs (**__todo__ options) -> UnionType
246
+ def _Integer?(**options)
247
+ integer = _Integer(**options)
248
+ _Nilable(integer)
249
+ end
250
+ alias _Int? _Integer?
251
+ alias _Number? _Integer?
252
+
253
+ # Creates a Nilable (nullable) type.
254
+ #
255
+ # Combines one or more types with `NilClass` to allow nil values.
256
+ #
257
+ # @example
258
+ # type = _Nilable(String, Symbol)
259
+ #
260
+ # @param types [Array<Class, Module, Behavior>] the base types
261
+ # @param options [Hash] additional configuration options
262
+ #
263
+ # @return [Domainic::Type::UnionType] the created type (NilClass or other specified types)
264
+ # @rbs (*Class | Module | Behavior[untyped, untyped, untyped] types, **__todo__ options) -> UnionType
265
+ def _Nilable(*types, **options)
266
+ _Union(NilClass, *types, **options)
267
+ end
268
+ alias _Nullable _Nilable
269
+
270
+ # Creates a StringType instance.
271
+ #
272
+ # @example
273
+ # type = _String
274
+ #
275
+ # @param options [Hash] additional configuration options
276
+ #
277
+ # @return [Domainic::Type::StringType] the created type
278
+ # @rbs (**__todo__ options) -> StringType
279
+ def _String(**options)
280
+ require 'domainic/type/types/core/string_type'
281
+ Domainic::Type::StringType.new(**options)
282
+ end
283
+ alias _Text _String
284
+
285
+ # Creates a nilable StringType instance.
286
+ #
287
+ # @example
288
+ # type = _String?
289
+ #
290
+ # @param options [Hash] additional configuration options
291
+ #
292
+ # @return [Domainic::Type::UnionType] the created type (String or NilClass)
293
+ # @rbs (**__todo__ options) -> UnionType
294
+ def _String?(**options)
295
+ string = _String(**options)
296
+ _Nilable(string)
297
+ end
298
+ alias _Text? _String?
299
+
300
+ # Creates a SymbolType instance.
301
+ #
302
+ # @example
303
+ # type = _Symbol
304
+ #
305
+ # @param options [Hash] additional configuration options
306
+ #
307
+ # @return [Domainic::Type::SymbolType] the created type
308
+ # @rbs (**__todo__ options) -> SymbolType
309
+ def _Symbol(**options)
310
+ require 'domainic/type/types/core/symbol_type'
311
+ Domainic::Type::SymbolType.new(**options)
312
+ end
313
+ alias _Interned _Symbol
314
+
315
+ # Creates a nilable SymbolType instance.
316
+ #
317
+ # @example
318
+ # type = _Symbol?
319
+ #
320
+ # @param options [Hash] additional configuration options
321
+ #
322
+ # @return [Domainic::Type::UnionType] the created type (Symbol or NilClass)
323
+ # @rbs (**__todo__ options) -> UnionType
324
+ def _Symbol?(**options)
325
+ symbol = _Symbol(**options)
326
+ _Nilable(symbol)
327
+ end
328
+ alias _Interned? _Symbol?
329
+
330
+ # Creates a UnionType instance.
331
+ #
332
+ # Allows combining multiple types into a single union type.
333
+ #
334
+ # @example
335
+ # type = _Union(String, Symbol)
336
+ #
337
+ # @param types [Array<Class, Module, Behavior>] the types included in the union
338
+ # @param options [Hash] additional configuration options
339
+ #
340
+ # @return [Domainic::Type::UnionType] the created type
341
+ # @rbs (*Class | Module | Behavior[untyped, untyped, untyped] types, **__todo__ options) -> UnionType
342
+ def _Union(*types, **options)
343
+ require 'domainic/type/types/specification/union_type'
344
+ Domainic::Type::UnionType.new(*types, **options)
345
+ end
346
+ alias _Either _Union
347
+
348
+ # Creates a VoidType instance.
349
+ #
350
+ # Represents an operation that returns no value.
351
+ #
352
+ # @example
353
+ # type = _Void
354
+ #
355
+ # @return [Domainic::Type::VoidType] the created type
356
+ # @rbs () -> VoidType
357
+ def _Void
358
+ require 'domainic/type/types/specification/void_type'
359
+ Domainic::Type::VoidType.new
360
+ end
361
+ # rubocop:enable Naming/MethodName
362
+ end
363
+ end
364
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'domainic/type/behavior'
4
+ require 'domainic/type/behavior/enumerable_behavior'
5
+
6
+ module Domainic
7
+ module Type
8
+ # A type for validating Array objects with flexible element and size constraints
9
+ #
10
+ # This class provides a comprehensive set of validations specifically designed for Array
11
+ # objects, including element type checking, value inclusion/exclusion, ordering, and all
12
+ # standard enumerable validations.
13
+ #
14
+ # Key features:
15
+ # - Element type validation
16
+ # - Element presence/absence validation
17
+ # - Uniqueness constraints
18
+ # - Order constraints
19
+ # - Size constraints (via EnumerableBehavior)
20
+ # - Standard collection validations (via EnumerableBehavior)
21
+ #
22
+ # @example Basic usage
23
+ # type = ArrayType.new
24
+ # type.of(String) # enforce element type
25
+ # type.containing(1, 2) # require specific elements
26
+ # type.having_size(3) # exact size constraint
27
+ # type.being_distinct # unique elements
28
+ #
29
+ # @example Complex constraints
30
+ # type = ArrayType.new
31
+ # type
32
+ # .of(Integer) # type constraints
33
+ # .being_ordered # must be sorted
34
+ # .having_size_between(2, 5) # size range
35
+ # .starting_with(1) # first element
36
+ #
37
+ # @author {https://aaronmallen.me Aaron Allen}
38
+ # @since 0.1.0
39
+ class ArrayType
40
+ # @rbs! extend Behavior::ClassMethods
41
+
42
+ include Behavior
43
+ include Behavior::EnumerableBehavior
44
+
45
+ intrinsic :self, :type, Array, abort_on_failure: true, description: :not_described
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'domainic/type/behavior'
4
+ require 'domainic/type/behavior/numeric_behavior'
5
+
6
+ module Domainic
7
+ module Type
8
+ # A type for validating Float objects with extensive numeric validation capabilities.
9
+ #
10
+ # This class provides a comprehensive set of validations specifically designed for
11
+ # floating-point values, including basic type checking and all numeric validations
12
+ # like finiteness, polarity, and range constraints. It properly handles floating-point
13
+ # arithmetic by using appropriate tolerances in comparisons.
14
+ #
15
+ # @example Basic usage
16
+ # type = FloatType.new
17
+ # type.validate(3.14) # => true
18
+ # type.validate(42) # => false
19
+ # type.validate("3.14") # => false
20
+ #
21
+ # @example With numeric constraints
22
+ # type = FloatType.new
23
+ # type
24
+ # .being_positive
25
+ # .being_finite
26
+ # .being_less_than(10.0)
27
+ #
28
+ # @author {https://aaronmallen.me Aaron Allen}
29
+ # @since 0.1.0
30
+ class FloatType
31
+ # @rbs! extend Behavior::ClassMethods
32
+
33
+ include Behavior
34
+ include Behavior::NumericBehavior
35
+
36
+ intrinsic :self, :type, Float, abort_on_failure: true, description: :not_described
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,143 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'domainic/type/behavior'
4
+ require 'domainic/type/behavior/enumerable_behavior'
5
+
6
+ module Domainic
7
+ module Type
8
+ # A type for validating Hash objects with flexible key and value constraints
9
+ #
10
+ # This class provides a comprehensive set of validations specifically designed
11
+ # for Hash objects, including key/value type checking, inclusion/exclusion of
12
+ # specific keys or values, and all standard enumerable validations.
13
+ #
14
+ # Key features:
15
+ # - Key type validation
16
+ # - Value type validation
17
+ # - Key presence/absence checking
18
+ # - Value presence/absence checking
19
+ # - Size constraints (via EnumerableBehavior)
20
+ # - Standard collection validations (via EnumerableBehavior)
21
+ #
22
+ # @example Basic usage
23
+ # type = HashType.new
24
+ # type.of(String => Integer) # enforce key/value types
25
+ # type.containing_keys('a', 'b') # require specific keys
26
+ # type.containing_values(1, 2) # require specific values
27
+ # type.having_size(2) # exact size constraint
28
+ #
29
+ # @example Complex constraints
30
+ # type = HashType.new
31
+ # type
32
+ # .of(Symbol => String) # type constraints
33
+ # .containing_keys(:name, :email) # required keys
34
+ # .excluding_values(nil, '') # no empty values
35
+ # .having_size_between(2, 5) # size range
36
+ #
37
+ # @author {https://aaronmallen.me Aaron Allen}
38
+ # @since 0.1.0
39
+ class HashType
40
+ # @rbs! extend Behavior::ClassMethods
41
+
42
+ include Behavior
43
+ include Behavior::EnumerableBehavior
44
+
45
+ intrinsic :self, :type, Hash, abort_on_failure: true, description: :not_described
46
+
47
+ # Validate that the hash contains specific keys
48
+ #
49
+ # @example
50
+ # type.containing_keys(:name, :email)
51
+ # type.validate({ name: 'John', email: 'john@example.com' }) # => true
52
+ # type.validate({ name: 'John' }) # => false
53
+ #
54
+ # @param keys [Array<Object>] the keys that must be present
55
+ # @return [self] self for method chaining
56
+ # @rbs (*untyped keys) -> self
57
+ def containing_keys(*keys)
58
+ including = keys.map do |key|
59
+ @constraints.prepare :entries, :inclusion, key
60
+ end
61
+ constrain :keys, :and, including, concerning: :key_inclusion, description: 'keys'
62
+ end
63
+ alias including_keys containing_keys
64
+
65
+ # Validate that the hash contains specific values
66
+ #
67
+ # @example
68
+ # type.containing_values('active', 'pending')
69
+ # type.validate({ status: 'active' }) # => true
70
+ # type.validate({ status: 'inactive' }) # => false
71
+ #
72
+ # @param values [Array<Object>] the values that must be present
73
+ # @return [self] self for method chaining
74
+ # @rbs (*untyped values) -> self
75
+ def containing_values(*values)
76
+ including = values.map do |value|
77
+ @constraints.prepare :entries, :inclusion, value
78
+ end
79
+ constrain :values, :and, including, concerning: :values_inclusion, description: 'values'
80
+ end
81
+ alias including_values containing_values
82
+
83
+ # Validate that the hash does not contain specific keys
84
+ #
85
+ # @example
86
+ # type.excluding_keys(:admin, :superuser)
87
+ # type.validate({ user: 'John' }) # => true
88
+ # type.validate({ admin: true }) # => false
89
+ #
90
+ # @param keys [Array<Object>] the keys that must not be present
91
+ # @return [self] self for method chaining
92
+ # @rbs (*untyped keys) -> self
93
+ def excluding_keys(*keys)
94
+ including = keys.map do |key|
95
+ @constraints.prepare :entries, :inclusion, key
96
+ end
97
+ constrain :keys, :nor, including, concerning: :key_exclusion, description: 'keys'
98
+ end
99
+ alias omitting_keys excluding_keys
100
+
101
+ # Validate that the hash does not contain specific values
102
+ #
103
+ # @example
104
+ # type.excluding_values(nil, '')
105
+ # type.validate({ name: 'John' }) # => true
106
+ # type.validate({ name: nil }) # => false
107
+ #
108
+ # @param values [Array<Object>] the values that must not be present
109
+ # @return [self] self for method chaining
110
+ # @rbs (*untyped values) -> self
111
+ def excluding_values(*values)
112
+ including = values.map do |value|
113
+ @constraints.prepare :entries, :inclusion, value
114
+ end
115
+ constrain :values, :nor, including, concerning: :values_exclusion, description: 'values'
116
+ end
117
+ alias omitting_values excluding_values
118
+
119
+ # Validate the hash to have the given key type and value type.
120
+ #
121
+ # @example
122
+ # type.of(String => Integer)
123
+ # type.validate({ 'a' => 1 }) # => true
124
+ # type.validate({ 1 => 'a' }) # => false
125
+ #
126
+ # @param key_to_value_type [Hash{Object => Object}] the key type and value type that the hash must have
127
+ #
128
+ # @raise [ArgumentError] if the key_to_value_type pair is not a Hash or does not have exactly one entry
129
+ # @return [self] self for method chaining
130
+ # @rbs (Hash[untyped, untyped] key_to_value_type) -> self
131
+ def of(key_to_value_type)
132
+ raise ArgumentError, 'The key_to_value_type pair must be a Hash' unless key_to_value_type.is_a?(Hash)
133
+ raise ArgumentError, 'The key_to_value_type pair must have exactly one entry' unless key_to_value_type.size == 1
134
+
135
+ key_type = @constraints.prepare :self, :type, key_to_value_type.keys.first
136
+ value_type = @constraints.prepare :self, :type, key_to_value_type.values.first
137
+
138
+ constrain :keys, :all, key_type, concerning: :key_type, description: 'having keys of'
139
+ constrain :values, :all, value_type, concerning: :value_type, description: 'having values of'
140
+ end
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'domainic/type/behavior'
4
+ require 'domainic/type/behavior/numeric_behavior'
5
+
6
+ module Domainic
7
+ module Type
8
+ # A type for validating Integer objects with extensive numeric validation capabilities.
9
+ #
10
+ # This class provides a comprehensive set of validations specifically designed for
11
+ # integer values, including basic type checking and all numeric validations like
12
+ # divisibility, parity, polarity, and range constraints.
13
+ #
14
+ # @example Basic usage
15
+ # type = IntegerType.new
16
+ # type.validate(42) # => true
17
+ # type.validate(3.14) # => false
18
+ # type.validate("42") # => false
19
+ #
20
+ # @example With numeric constraints
21
+ # type = IntegerType.new
22
+ # type
23
+ # .being_positive
24
+ # .being_even
25
+ # .being_less_than(100)
26
+ #
27
+ # @author {https://aaronmallen.me Aaron Allen}
28
+ # @since 0.1.0
29
+ class IntegerType
30
+ # @rbs! extend Behavior::ClassMethods
31
+
32
+ include Behavior
33
+ include Behavior::NumericBehavior
34
+
35
+ intrinsic :self, :type, Integer, abort_on_failure: true, description: :not_described
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'domainic/type/behavior'
4
+ require 'domainic/type/behavior/string_behavior'
5
+
6
+ module Domainic
7
+ module Type
8
+ # A type for validating String objects with comprehensive string-specific constraints
9
+ #
10
+ # This type provides a complete set of string validation capabilities including case
11
+ # formatting, character set validation, pattern matching, and size constraints. It
12
+ # combines core string type checking with rich string-specific behaviors.
13
+ #
14
+ # Key features:
15
+ # - Basic string type validation
16
+ # - Case checking (upper, lower, mixed, title)
17
+ # - Character set validation (ASCII, alphanumeric, etc.)
18
+ # - Pattern matching with regular expressions
19
+ # - Size/length constraints
20
+ # - String content validation
21
+ #
22
+ # @example Basic usage
23
+ # type = StringType.new
24
+ # type.validate("hello") # => true
25
+ # type.validate(123) # => false
26
+ #
27
+ # @example Complex string validation
28
+ # type = StringType.new
29
+ # .being_ascii
30
+ # .being_alphanumeric
31
+ # .having_size_between(3, 20)
32
+ # .not_matching(/[^a-z0-9]/)
33
+ #
34
+ # @example Case validation
35
+ # type = StringType.new
36
+ # .being_titlecase
37
+ # .matching(/^[A-Z]/)
38
+ # .having_minimum_size(2)
39
+ #
40
+ # @author {https://aaronmallen.me Aaron Allen}
41
+ # @since 0.1.0
42
+ class StringType
43
+ # @rbs! extend Behavior::ClassMethods
44
+
45
+ include Behavior
46
+ include Behavior::StringBehavior
47
+
48
+ intrinsic :self, :type, String, abort_on_failure: true, description: :not_described
49
+ end
50
+ end
51
+ end