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

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,315 @@
1
+ module Domainic
2
+ module Type
3
+ module Behavior
4
+ # A module providing string-specific validation behaviors for types.
5
+ #
6
+ # This module extends the base Type::Behavior with methods specifically designed for
7
+ # validating string values. It provides a fluent interface for common string validations
8
+ # such as case checking, character set validation, equality, and pattern matching.
9
+ #
10
+ # Key capabilities:
11
+ # - Case validation (upper, lower, mixed, title case)
12
+ # - Character set checking (ASCII, alphanumeric, letters, numbers)
13
+ # - Pattern matching with regular expressions
14
+ # - Substring inclusion/exclusion
15
+ # - Character ordering checks
16
+ # - Length constraints (via SizableBehavior)
17
+ #
18
+ # @example Basic string validation
19
+ # class StringType
20
+ # include Domainic::Type::Behavior::StringBehavior
21
+ #
22
+ # def initialize
23
+ # super
24
+ # being_ascii # validates ASCII characters only
25
+ # being_alphanumeric # validates letters and numbers only
26
+ # having_minimum_size(5) # validates minimum length
27
+ # end
28
+ # end
29
+ #
30
+ # @example Complex string validation
31
+ # class UsernameType
32
+ # include Domainic::Type::Behavior::StringBehavior
33
+ #
34
+ # def initialize
35
+ # super
36
+ # being_lowercase
37
+ # being_alphanumeric
38
+ # having_size_between(3, 20)
39
+ # not_matching(/^admin/i) # prevent admin-like usernames
40
+ # end
41
+ # end
42
+ #
43
+ # @example Building constraints dynamically
44
+ # type = StringType.new
45
+ # .being_ascii
46
+ # .being_titlecase
47
+ # .having_size_between(5, 50)
48
+ # .matching(/^[A-Z]/)
49
+ #
50
+ # @author {https://aaronmallen.me Aaron Allen}
51
+ # @since 0.1.0
52
+ module StringBehavior
53
+ include SizableBehavior
54
+
55
+ # Validate string contains only alphanumeric characters.
56
+ #
57
+ # @example
58
+ # type.being_alphanumeric
59
+ # type.validate("abc123") # => true
60
+ # type.validate("abc-123") # => false
61
+ #
62
+ # @return [Behavior] self for method chaining
63
+ def being_alphanumeric: () -> Behavior
64
+
65
+ alias alphanumeric being_alphanumeric
66
+
67
+ # Validate string contains only ASCII characters.
68
+ #
69
+ # @example
70
+ # type.being_ascii
71
+ # type.validate("hello") # => true
72
+ # type.validate("héllo") # => false
73
+ #
74
+ # @return [Behavior] self for method chaining
75
+ def being_ascii: () -> Behavior
76
+
77
+ alias ascii being_ascii
78
+
79
+ alias ascii_only being_ascii
80
+
81
+ # Validate string is empty.
82
+ #
83
+ # @example
84
+ # type.being_empty
85
+ # type.validate("") # => true
86
+ # type.validate("a") # => false
87
+ #
88
+ # @return [Behavior] self for method chaining
89
+ def being_empty: () -> Behavior
90
+
91
+ alias empty being_empty
92
+
93
+ # Validate string equals a specific value.
94
+ #
95
+ # @example
96
+ # type.being_equal_to("hello")
97
+ # type.validate("hello") # => true
98
+ # type.validate("world") # => false
99
+ #
100
+ # @param literal [String, Symbol] the value to compare against
101
+ # @return [Behavior] self for method chaining
102
+ def being_equal_to: (String | Symbol literal) -> Behavior
103
+
104
+ alias eql being_equal_to
105
+
106
+ alias equal_to being_equal_to
107
+
108
+ alias equaling being_equal_to
109
+
110
+ # Validate string is lowercase.
111
+ #
112
+ # @example
113
+ # type.being_lowercase
114
+ # type.validate("hello") # => true
115
+ # type.validate("Hello") # => false
116
+ #
117
+ # @return [Behavior] self for method chaining
118
+ def being_lowercase: () -> Behavior
119
+
120
+ alias lowercase being_lowercase
121
+
122
+ alias not_being_uppercase being_lowercase
123
+
124
+ # Validate string contains both uppercase and lowercase characters.
125
+ #
126
+ # @example
127
+ # type.being_mixedcase
128
+ # type.validate("helloWORLD") # => true
129
+ # type.validate("hello") # => false
130
+ #
131
+ # @return [Behavior] self for method chaining
132
+ def being_mixedcase: () -> Behavior
133
+
134
+ alias mixedcase being_mixedcase
135
+
136
+ # Validate string contains only letters.
137
+ #
138
+ # @example
139
+ # type.being_only_letters
140
+ # type.validate("hello") # => true
141
+ # type.validate("hello123") # => false
142
+ #
143
+ # @return [Behavior] self for method chaining
144
+ def being_only_letters: () -> Behavior
145
+
146
+ alias alpha being_only_letters
147
+
148
+ alias letters_only being_only_letters
149
+
150
+ alias only_letters being_only_letters
151
+
152
+ # Validate string contains only numbers.
153
+ #
154
+ # @example
155
+ # type.being_only_numbers
156
+ # type.validate("123") # => true
157
+ # type.validate("abc123") # => false
158
+ #
159
+ # @return [Behavior] self for method chaining
160
+ def being_only_numbers: () -> Behavior
161
+
162
+ alias digits_only being_only_numbers
163
+
164
+ alias numbers_only being_only_numbers
165
+
166
+ alias numeric being_only_numbers
167
+
168
+ alias only_digits being_only_numbers
169
+
170
+ alias only_numbers being_only_numbers
171
+
172
+ # Validate string characters are in sorted order.
173
+ #
174
+ # @example
175
+ # type.being_ordered
176
+ # type.validate("abcd") # => true
177
+ # type.validate("dcba") # => false
178
+ #
179
+ # @return [Behavior] self for method chaining
180
+ def being_ordered: () -> Behavior
181
+
182
+ alias not_being_unordered being_ordered
183
+
184
+ alias ordered being_ordered
185
+
186
+ # Validate string contains only printable characters.
187
+ #
188
+ # @example
189
+ # type.being_printable
190
+ # type.validate("Hello!") # => true
191
+ # type.validate("Hello\x00World") # => false
192
+ #
193
+ # @return [Behavior] self for method chaining
194
+ def being_printable: () -> Behavior
195
+
196
+ alias printable being_printable
197
+
198
+ # Validate string is in title case (first letter of each word capitalized).
199
+ #
200
+ # @example
201
+ # type.being_titlecase
202
+ # type.validate("Hello World") # => true
203
+ # type.validate("hello world") # => false
204
+ #
205
+ # @return [Behavior] self for method chaining
206
+ def being_titlecase: () -> Behavior
207
+
208
+ alias titlecase being_titlecase
209
+
210
+ # Validate string characters are not in sorted order.
211
+ #
212
+ # @example
213
+ # type.being_unordered
214
+ # type.validate("dcba") # => true
215
+ # type.validate("abcd") # => false
216
+ #
217
+ # @return [Behavior] self for method chaining
218
+ def being_unordered: () -> Behavior
219
+
220
+ alias not_being_ordered being_unordered
221
+
222
+ alias unordered being_unordered
223
+
224
+ # Validate string is uppercase.
225
+ #
226
+ # @example
227
+ # type.being_uppercase
228
+ # type.validate("HELLO") # => true
229
+ # type.validate("Hello") # => false
230
+ #
231
+ # @return [Behavior] self for method chaining
232
+ def being_uppercase: () -> Behavior
233
+
234
+ alias not_being_lowercase being_uppercase
235
+
236
+ alias uppercase being_uppercase
237
+
238
+ # Validate string contains all specified substrings.
239
+ #
240
+ # @example
241
+ # type.containing("hello", "world")
242
+ # type.validate("hello world") # => true
243
+ # type.validate("hello") # => false
244
+ #
245
+ # @param literals [Array<String, Symbol>] the substrings to look for
246
+ # @return [Behavior] self for method chaining
247
+ def containing: (*String | Symbol literals) -> Behavior
248
+
249
+ alias including containing
250
+
251
+ # Validate string does not contain any specified substrings.
252
+ #
253
+ # @example
254
+ # type.excluding("foo", "bar")
255
+ # type.validate("hello world") # => true
256
+ # type.validate("foo bar") # => false
257
+ #
258
+ # @param literals [Array<String, Symbol>] the substrings to exclude
259
+ # @return [Behavior] self for method chaining
260
+ def excluding: (*String | Symbol literals) -> Behavior
261
+
262
+ alias omitting excluding
263
+
264
+ # Validate string matches all specified patterns.
265
+ #
266
+ # @example
267
+ # type.matching(/^\w+$/, /\d/)
268
+ # type.validate("hello123") # => true
269
+ # type.validate("hello") # => false
270
+ #
271
+ # @param patterns [Array<String, Regexp>] the patterns to match against
272
+ # @return [Behavior] self for method chaining
273
+ def matching: (*String | Regexp patterns) -> Behavior
274
+
275
+ # Validate string is not empty.
276
+ #
277
+ # @example
278
+ # type.not_being_empty
279
+ # type.validate("a") # => true
280
+ # type.validate("") # => false
281
+ #
282
+ # @return [Behavior] self for method chaining
283
+ def not_being_empty: () -> Behavior
284
+
285
+ # Validate string does not equal a specific value.
286
+ #
287
+ # @example
288
+ # type.not_being_equal_to("admin")
289
+ # type.validate("user") # => true
290
+ # type.validate("admin") # => false
291
+ #
292
+ # @param literal [String, Symbol] the value to compare against
293
+ # @return [Behavior] self for method chaining
294
+ def not_being_equal_to: (String | Symbol literal) -> Behavior
295
+
296
+ alias not_eql not_being_equal_to
297
+
298
+ alias not_equal_to not_being_equal_to
299
+
300
+ alias not_equaling not_being_equal_to
301
+
302
+ # Validate string does not match any specified patterns.
303
+ #
304
+ # @example
305
+ # type.not_matching(/\d/, /[A-Z]/)
306
+ # type.validate("hello") # => true
307
+ # type.validate("Hello123") # => false
308
+ #
309
+ # @param patterns [Array<String, Regexp>] the patterns to avoid matching
310
+ # @return [Behavior] self for method chaining
311
+ def not_matching: (*String | Regexp patterns) -> Behavior
312
+ end
313
+ end
314
+ end
315
+ end
@@ -0,0 +1,153 @@
1
+ module Domainic
2
+ module Type
3
+ # A module providing core type validation behavior.
4
+ #
5
+ # The Behavior module provides the foundation for type validation in the Domainic
6
+ # system. It manages a set of constraints that define what makes a value valid
7
+ # for a particular type and provides methods to validate values against these
8
+ # constraints.
9
+ #
10
+ # Key features:
11
+ # - Intrinsic constraints defined at the class level
12
+ # - Instance-level constraint customization
13
+ # - Support for both silent and exception-raising validation
14
+ # - Case equality operator integration (===)
15
+ #
16
+ # @example Defining a custom type
17
+ # class MyType
18
+ # include Domainic::Type::Behavior
19
+ #
20
+ # private
21
+ #
22
+ # def initialize(**options)
23
+ # super
24
+ # constrain(:self, :string_check, :string)
25
+ # constrain(:length, :minimum, :range, minimum: 5)
26
+ # end
27
+ # end
28
+ #
29
+ # @example Using a custom type
30
+ # type = MyType.new
31
+ # type.validate("hello") # => true
32
+ # type.validate("hi") # => false
33
+ # type.validate!(123) # raises TypeError
34
+ #
35
+ # case "hello"
36
+ # when MyType then puts "Valid!"
37
+ # end
38
+ #
39
+ # @author {https://aaronmallen.me Aaron Allen}
40
+ # @since 0.1.0
41
+ module Behavior
42
+ @constraint_set: Constraint::Set
43
+
44
+ # Configure class methods when module is included.
45
+ #
46
+ # @param base [Class] The class including this module
47
+ #
48
+ # @return [void]
49
+ def self.included: (Class | Module base) -> void
50
+
51
+ # Class methods for types including the Behavior module.
52
+ #
53
+ # These methods provide class-level validation capabilities and constraint
54
+ # management.
55
+ #
56
+ # @since 0.1.0
57
+ module ClassMethods
58
+ @intrinsic_constraints: Constraint::Set
59
+
60
+ # Convert the type to a String representation.
61
+ #
62
+ # @return [String] The type as a String
63
+ def to_s: () -> String
64
+
65
+ alias inspect to_s
66
+
67
+ # Validate a value against this type.
68
+ #
69
+ # @param value [Object] The value to validate
70
+ #
71
+ # @return [Boolean] true if the value is valid
72
+ def validate: (untyped value) -> bool
73
+
74
+ alias === validate
75
+
76
+ # Validate a value against this type, raising an error on failure.
77
+ #
78
+ # @param value [Object] The value to validate
79
+ #
80
+ # @raise [TypeError] if the value is invalid
81
+ # @return [Boolean] true if the value is valid
82
+ def validate!: (untyped value) -> bool
83
+
84
+ private
85
+
86
+ # Add an intrinsic constraint to this type.
87
+ #
88
+ # @see Constraint::Set#add
89
+ #
90
+ # @return [void]
91
+ def intrinsic: (Type::accessor accessor, String | Symbol constraint_type, ?untyped expectation, **untyped options) -> void
92
+
93
+ # Get the set of intrinsic constraints for this type.
94
+ #
95
+ # @return [Constraint::Set] The constraint set
96
+ def intrinsic_constraints: () -> Constraint::Set
97
+
98
+ # Delegate unknown methods to a new instance.
99
+ #
100
+ # @return [Object] The result of calling the method on a new instance
101
+ def method_missing: (Symbol method_name, *untyped arguments, **untyped keyword_arguments) -> Behavior
102
+
103
+ # Check if an unknown method can be delegated.
104
+ #
105
+ # @param method_name [Symbol] The name of the method
106
+ # @param _include_private [Boolean] Whether to include private methods
107
+ #
108
+ # @return [Boolean] true if the method can be delegated
109
+ def respond_to_missing?: (Symbol method_name, ?bool _include_private) -> bool
110
+ end
111
+
112
+ # Initialize a new type instance.
113
+ #
114
+ # @param options [Hash] Configuration options for constraints
115
+ #
116
+ # @return [void]
117
+ def initialize: (**untyped) -> void
118
+
119
+ # Convert the type to a String representation.
120
+ #
121
+ # @return [String] The type as a String
122
+ def to_s: () -> String
123
+
124
+ alias inspect to_s
125
+
126
+ # Validate a value against this type's constraints.
127
+ #
128
+ # @param value [Object] The value to validate
129
+ #
130
+ # @return [Boolean] true if the value satisfies all constraints
131
+ def validate: (untyped value) -> bool
132
+
133
+ alias === validate
134
+
135
+ # Validate a value against this type's constraints, raising an error on failure.
136
+ #
137
+ # @param value [Object] The value to validate
138
+ #
139
+ # @raise [TypeError] if the value fails any constraints
140
+ # @return [Boolean] true if the value satisfies all constraints
141
+ def validate!: (untyped value) -> bool
142
+
143
+ private
144
+
145
+ # Add a constraint to this type instance.
146
+ #
147
+ # @see Constraint::Set#add
148
+ #
149
+ # @return [self]
150
+ def constrain: (Type::accessor accessor, String | Symbol constraint_type, ?untyped expectation, **untyped options) -> self
151
+ end
152
+ end
153
+ end