domainic-type 0.1.0.alpha.3.2.0 → 0.1.0.alpha.3.4.0
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/.yardopts +11 -0
- data/README.md +66 -10
- data/docs/USAGE.md +787 -0
- data/lib/domainic/type/accessors.rb +3 -2
- data/lib/domainic/type/behavior/date_time_behavior.rb +121 -37
- data/lib/domainic/type/behavior.rb +16 -0
- data/lib/domainic/type/config/registry.yml +24 -0
- data/lib/domainic/type/constraint/constraints/nor_constraint.rb +1 -1
- data/lib/domainic/type/constraint/constraints/predicate_constraint.rb +76 -0
- data/lib/domainic/type/definitions.rb +212 -0
- data/lib/domainic/type/types/core/complex_type.rb +122 -0
- data/lib/domainic/type/types/core/range_type.rb +47 -0
- data/lib/domainic/type/types/core/rational_type.rb +38 -0
- data/lib/domainic/type/types/core_extended/big_decimal_type.rb +34 -0
- data/lib/domainic/type/types/core_extended/set_type.rb +34 -0
- data/lib/domainic/type/types/datetime/date_time_string_type.rb +156 -0
- data/lib/domainic/type/types/datetime/timestamp_type.rb +50 -0
- data/sig/domainic/type/accessors.rbs +2 -2
- data/sig/domainic/type/behavior/date_time_behavior.rbs +35 -23
- data/sig/domainic/type/behavior.rbs +9 -0
- data/sig/domainic/type/constraint/constraints/predicate_constraint.rbs +56 -0
- data/sig/domainic/type/definitions.rbs +165 -0
- data/sig/domainic/type/types/core/complex_type.rbs +96 -0
- data/sig/domainic/type/types/core/range_type.rbs +41 -0
- data/sig/domainic/type/types/core/rational_type.rbs +32 -0
- data/sig/domainic/type/types/core_extended/big_decimal_type.rbs +27 -0
- data/sig/domainic/type/types/core_extended/set_type.rbs +27 -0
- data/sig/domainic/type/types/datetime/date_time_string_type.rbs +124 -0
- data/sig/domainic/type/types/datetime/timestamp_type.rbs +44 -0
- metadata +25 -6
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'domainic/type/behavior'
|
4
|
+
require 'domainic/type/behavior/date_time_behavior'
|
5
|
+
|
6
|
+
module Domainic
|
7
|
+
module Type
|
8
|
+
# A type for validating Unix timestamps (seconds since the Unix epoch).
|
9
|
+
#
|
10
|
+
# This type ensures the value is an `Integer` representing a valid Unix
|
11
|
+
# timestamp. It integrates with `DateTimeBehavior` to provide a rich set of
|
12
|
+
# validation capabilities, including chronological constraints and range checks.
|
13
|
+
#
|
14
|
+
# Key features:
|
15
|
+
# - Ensures the value is an `Integer` representing a Unix timestamp.
|
16
|
+
# - Supports chronological relationship constraints (e.g., before, after).
|
17
|
+
# - Provides range, equality, and nilable checks.
|
18
|
+
#
|
19
|
+
# @example Basic usage
|
20
|
+
# type = TimestampType.new
|
21
|
+
# type.validate(Time.now.to_i) # => true
|
22
|
+
# type.validate(Date.today.to_time.to_i) # => true
|
23
|
+
# type.validate('invalid') # => false
|
24
|
+
#
|
25
|
+
# @example Range validation
|
26
|
+
# type = TimestampType.new
|
27
|
+
# .being_between(Time.now.to_i, (Time.now + 3600).to_i)
|
28
|
+
# type.validate((Time.now + 1800).to_i) # => true
|
29
|
+
# type.validate((Time.now + 7200).to_i) # => false
|
30
|
+
#
|
31
|
+
# @example Historical timestamps
|
32
|
+
# type = TimestampType.new
|
33
|
+
# type.validate(-1234567890) # => true (date before 1970-01-01)
|
34
|
+
#
|
35
|
+
# @example Nilable timestamp
|
36
|
+
# nilable_type = _Nilable(TimestampType.new)
|
37
|
+
# nilable_type.validate(nil) # => true
|
38
|
+
#
|
39
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
40
|
+
# @since 0.1.0
|
41
|
+
class TimestampType
|
42
|
+
# @rbs! extend Behavior::ClassMethods
|
43
|
+
|
44
|
+
include Behavior
|
45
|
+
include Behavior::DateTimeBehavior
|
46
|
+
|
47
|
+
intrinsically_constrain :self, :type, Integer, abort_on_failure: true, description: :not_described
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module Domainic
|
2
2
|
module Type
|
3
|
-
type accessor = :abs | :begin | :chars | :class | :count | :end | :entries | :first | :keys | :last | :length | :self | :size | :values
|
3
|
+
type accessor = :abs | :begin | :chars | :class | :count | :end | :entries | :first | :keys | :last | :length | :real | :self | :size | :values
|
4
4
|
|
5
5
|
# A list of valid access methods that can be used to retrieve values for constraint validation.
|
6
6
|
# These methods represent common Ruby interfaces for accessing collection sizes, ranges, and values.
|
7
7
|
#
|
8
|
-
# - :abs
|
8
|
+
# - :abs, :real - For absolute values
|
9
9
|
# - :begin, :end - For Range-like objects
|
10
10
|
# - :class - For type checking
|
11
11
|
# - :count, :length, :size - For measuring collections
|
@@ -24,73 +24,85 @@ module Domainic
|
|
24
24
|
# @author {https://aaronmallen.me Aaron Allen}
|
25
25
|
# @since 0.1.0
|
26
26
|
module DateTimeBehavior
|
27
|
-
|
27
|
+
# The supported date/time patterns for parsing date/time strings
|
28
|
+
#
|
29
|
+
# @note This list is ordered from most specific to least specific to ensure that the most specific patterns are
|
30
|
+
# tried first. This is important because some patterns are more lenient than others and may match a wider range
|
31
|
+
# of input strings.
|
32
|
+
#
|
33
|
+
# @return [Array<String>] the supported date/time patterns
|
34
|
+
DATETIME_PATTERNS: Array[String]
|
35
|
+
|
36
|
+
# Coerce a value to a Date, DateTime, or Time object
|
37
|
+
#
|
38
|
+
# @return [Proc] a lambda that coerces a value to a Date, DateTime, or Time object
|
39
|
+
TO_DATETIME_COERCER: ^(Date | DateTime | Integer | String | Time value) -> (Date | DateTime | Time)
|
28
40
|
|
29
41
|
# Parse arguments for being_between
|
30
42
|
#
|
31
43
|
# @note this in my opinion is better than polluting the namespace of the including class even with a private
|
32
44
|
# method. This way, the method is only available within the module itself. See {#being_between}.
|
33
45
|
#
|
34
|
-
# @param after [Date, DateTime, String, Time, nil] minimum size value from positional args
|
35
|
-
# @param before [Date, DateTime, String, Time, nil] maximum size value from positional args
|
46
|
+
# @param after [Date, DateTime, Integer, String, Time, nil] minimum size value from positional args
|
47
|
+
# @param before [Date, DateTime, Integer, String, Time, nil] maximum size value from positional args
|
36
48
|
# @param options [Hash] keyword arguments containing after/before values
|
37
49
|
#
|
38
50
|
# @raise [ArgumentError] if minimum or maximum value can't be determined
|
39
|
-
# @return [Array<Date, DateTime, String, Time, nil>] parsed [after, before] values
|
40
|
-
private def self.parse_being_between_arguments!: ((Date | DateTime | String | Time)? after, (Date | DateTime | String | Time)? before, Hash[Symbol, (Date | DateTime | String | Time)?] options) -> Array[(Date | DateTime | String | Time)?]
|
51
|
+
# @return [Array<Date, DateTime, Integer, String, Time, nil>] parsed [after, before] values
|
52
|
+
private def self.parse_being_between_arguments!: ((Date | DateTime | Integer | String | Time)? after, (Date | DateTime | Integer | String | Time)? before, Hash[Symbol, (Date | DateTime | Integer | String | Time)?] options) -> Array[(Date | DateTime | Integer | String | Time)?]
|
41
53
|
|
42
54
|
# Raise appropriate ArgumentError for being_between
|
43
55
|
#
|
44
56
|
# @param original_caller [Array<String>] caller stack for error
|
45
|
-
# @param after [Date, DateTime, String, Time, nil] after value from positional args
|
46
|
-
# @param before [Date, DateTime, String, Time, nil] before value from positional args
|
57
|
+
# @param after [Date, DateTime, Integer, String, Time, nil] after value from positional args
|
58
|
+
# @param before [Date, DateTime, Integer, String, Time, nil] before value from positional args
|
47
59
|
# @param options [Hash] keyword arguments containing after/before values
|
48
60
|
#
|
49
61
|
# @raise [ArgumentError] with appropriate message
|
50
62
|
# @return [void]
|
51
|
-
private def self.raise_being_between_argument_error!: (Array[String] original_caller, (Date | DateTime | String | Time)? after, (Date | DateTime | String | Time)? before, Hash[Symbol, (Date | DateTime | String | Time)?] options) -> void
|
63
|
+
private def self.raise_being_between_argument_error!: (Array[String] original_caller, (Date | DateTime | Integer | String | Time)? after, (Date | DateTime | Integer | String | Time)? before, Hash[Symbol, (Date | DateTime | Integer | String | Time)?] options) -> void
|
52
64
|
|
53
65
|
# Constrain the value to be chronologically after a given date/time
|
54
66
|
#
|
55
|
-
# @param other [Date, DateTime, String, Time] the date/time to compare against
|
67
|
+
# @param other [Date, DateTime, Integer, String, Time] the date/time to compare against
|
56
68
|
# @return [self] self for method chaining
|
57
|
-
def being_after: (Date | DateTime | String | Time other) -> Behavior
|
69
|
+
def being_after: (Date | DateTime | Integer | String | Time other) -> Behavior
|
58
70
|
|
59
71
|
alias after being_after
|
60
72
|
|
61
73
|
# Constrain the value to be chronologically before a given date/time
|
62
74
|
#
|
63
|
-
# @param other [Date, DateTime, String, Time] the date/time to compare against
|
75
|
+
# @param other [Date, DateTime, Integer, String, Time] the date/time to compare against
|
64
76
|
# @return [self] self for method chaining
|
65
|
-
def being_before: (Date | DateTime | String | Time other) -> Behavior
|
77
|
+
def being_before: (Date | DateTime | Integer | String | Time other) -> Behavior
|
66
78
|
|
67
79
|
alias before being_before
|
68
80
|
|
69
81
|
# Constrain the value to be chronologically between two date/times
|
70
82
|
#
|
71
|
-
# @param after [Date, DateTime, String, Time] the earliest allowed date/time
|
72
|
-
# @param before [Date, DateTime, String, Time] the latest allowed date/time
|
83
|
+
# @param after [Date, DateTime, Integer, String, Time] the earliest allowed date/time
|
84
|
+
# @param before [Date, DateTime, Integer, String, Time] the latest allowed date/time
|
73
85
|
# @param options [Hash] alternative way to specify after/before via keywords
|
74
|
-
# @option options [Date, DateTime, String, Time] :after earliest allowed date/time
|
75
|
-
# @option options [Date, DateTime, String, Time] :before latest allowed date/time
|
86
|
+
# @option options [Date, DateTime, Integer, String, Time] :after earliest allowed date/time
|
87
|
+
# @option options [Date, DateTime, Integer, String, Time] :before latest allowed date/time
|
76
88
|
# @return [self] self for method chaining
|
77
|
-
def being_between: (Date | DateTime | String | Time after, Date | DateTime | String | Time before) -> Behavior
|
89
|
+
def being_between: (Date | DateTime | Integer | String | Time after, Date | DateTime | Integer | String | Time before) -> Behavior
|
78
90
|
|
79
91
|
alias between being_between
|
80
92
|
|
81
93
|
# Constrain the value to be exactly equal to a given date/time
|
82
94
|
#
|
83
|
-
# @param other [Date, DateTime, String, Time] the date/time to compare against
|
95
|
+
# @param other [Date, DateTime, Integer, String, Time] the date/time to compare against
|
84
96
|
# @return [self] self for method chaining
|
85
|
-
def being_equal_to: (Date | DateTime | String | Time other) -> Behavior
|
97
|
+
def being_equal_to: (Date | DateTime | Integer | String | Time other) -> Behavior
|
86
98
|
|
87
99
|
alias at being_equal_to
|
88
100
|
|
89
101
|
# Constrain the value to be chronologically on or after a given date/time
|
90
102
|
#
|
91
|
-
# @param other [Date, DateTime, String, Time] the date/time to compare against
|
103
|
+
# @param other [Date, DateTime, Integer, String, Time] the date/time to compare against
|
92
104
|
# @return [self] self for method chaining
|
93
|
-
def being_on_or_after: (Date | DateTime | String | Time other) -> Behavior
|
105
|
+
def being_on_or_after: (Date | DateTime | Integer | String | Time other) -> Behavior
|
94
106
|
|
95
107
|
alias at_or_after being_on_or_after
|
96
108
|
|
@@ -100,9 +112,9 @@ module Domainic
|
|
100
112
|
|
101
113
|
# Constrain the value to be chronologically on or before a given date/time
|
102
114
|
#
|
103
|
-
# @param other [Date, DateTime, String, Time] the date/time to compare against
|
115
|
+
# @param other [Date, DateTime, Integer, String, Time] the date/time to compare against
|
104
116
|
# @return [self] self for method chaining
|
105
|
-
def being_on_or_before: (Date | DateTime | String | Time other) -> Behavior
|
117
|
+
def being_on_or_before: (Date | DateTime | Integer | String | Time other) -> Behavior
|
106
118
|
|
107
119
|
alias at_or_before being_on_or_before
|
108
120
|
|
@@ -125,6 +125,15 @@ module Domainic
|
|
125
125
|
# @return [void]
|
126
126
|
def initialize: (**untyped) -> void
|
127
127
|
|
128
|
+
# Add a custom constraint to this type.
|
129
|
+
#
|
130
|
+
# @param proc [Proc] the constraint to add
|
131
|
+
# @param accessor [Type::Accessor] the accessor to constrain
|
132
|
+
# @param options [Hash{Symbol => Object}] additional constraint options
|
133
|
+
#
|
134
|
+
# @return [self] for chaining constraints
|
135
|
+
def satisfies: (Proc proc, ?accessor: Type::accessor, **untyped options) -> Behavior
|
136
|
+
|
128
137
|
# Convert the type to a String representation.
|
129
138
|
#
|
130
139
|
# @return [String] The type as a String
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Domainic
|
2
|
+
module Type
|
3
|
+
module Constraint
|
4
|
+
# A constraint for validating values using a custom predicate function.
|
5
|
+
#
|
6
|
+
# This constraint allows for custom validation logic through a Proc that returns
|
7
|
+
# a boolean value. It enables users to create arbitrary validation rules when
|
8
|
+
# the built-in constraints don't cover their specific needs.
|
9
|
+
#
|
10
|
+
# @example Basic usage
|
11
|
+
# constraint = PredicateConstraint.new(:self, ->(x) { x > 0 })
|
12
|
+
# constraint.satisfied?(1) # => true
|
13
|
+
# constraint.satisfied?(-1) # => false
|
14
|
+
#
|
15
|
+
# @example With custom violation description
|
16
|
+
# constraint = PredicateConstraint.new(:self, ->(x) { x > 0 }, violation_description: 'not greater than zero')
|
17
|
+
# constraint.satisfied?(-1) # => false
|
18
|
+
# constraint.short_violation_description # => "not greater than zero"
|
19
|
+
#
|
20
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
21
|
+
# @since 0.1.0
|
22
|
+
class PredicateConstraint
|
23
|
+
type expected = ^(untyped value) -> bool
|
24
|
+
|
25
|
+
type options = { ?violation_description: String }
|
26
|
+
|
27
|
+
include Behavior[expected, untyped, options]
|
28
|
+
|
29
|
+
# Get a description of what the constraint expects.
|
30
|
+
#
|
31
|
+
# @note This constraint type does not provide a description as predicates are arbitrary.
|
32
|
+
#
|
33
|
+
# @return [String] an empty string
|
34
|
+
def short_description: ...
|
35
|
+
|
36
|
+
# Get a description of why the predicate validation failed.
|
37
|
+
#
|
38
|
+
# @return [String] the custom violation description if provided
|
39
|
+
def short_violation_description: ...
|
40
|
+
|
41
|
+
# Check if the value satisfies the predicate function.
|
42
|
+
#
|
43
|
+
# @return [Boolean] true if the predicate returns true
|
44
|
+
def satisfies_constraint?: ...
|
45
|
+
|
46
|
+
# Validate that the expectation is a Proc.
|
47
|
+
#
|
48
|
+
# @param expectation [Object] the expectation to validate
|
49
|
+
#
|
50
|
+
# @raise [ArgumentError] if the expectation is not a Proc
|
51
|
+
# @return [void]
|
52
|
+
def validate_expectation!: ...
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -64,6 +64,29 @@ module Domainic
|
|
64
64
|
|
65
65
|
alias _List? _Array?
|
66
66
|
|
67
|
+
# Creates a BigDecimalType instance.
|
68
|
+
#
|
69
|
+
# @example
|
70
|
+
# type = _BigDecimal
|
71
|
+
# type.validate(BigDecimal('123.45')) # => true
|
72
|
+
#
|
73
|
+
# @param options [Hash] additional configuration options
|
74
|
+
#
|
75
|
+
# @return [Domainic::Type::BigDecimalType] the created type
|
76
|
+
def _BigDecimal: (**__todo__ options) -> BigDecimalType
|
77
|
+
|
78
|
+
# Creates a nilable BigDecimalType instance.
|
79
|
+
#
|
80
|
+
# @example
|
81
|
+
# type = _BigDecimal?
|
82
|
+
# type.validate(BigDecimal('123.45')) # => true
|
83
|
+
# type.validate(nil) # => true
|
84
|
+
#
|
85
|
+
# @param options [Hash] additional configuration options
|
86
|
+
#
|
87
|
+
# @return [Domainic::Type::UnionType] the created type (BigDecimal or NilClass)
|
88
|
+
def _BigDecimal?: (**__todo__ options) -> UnionType
|
89
|
+
|
67
90
|
# Creates a Boolean type.
|
68
91
|
#
|
69
92
|
# Represents a union of TrueClass and FalseClass.
|
@@ -111,6 +134,28 @@ module Domainic
|
|
111
134
|
|
112
135
|
alias _Cuid? _CUID?
|
113
136
|
|
137
|
+
# Creates a ComplexType instance.
|
138
|
+
#
|
139
|
+
# @example
|
140
|
+
# type = _Complex
|
141
|
+
# type.validate(Complex(1, 2)) # => true
|
142
|
+
#
|
143
|
+
# @param options [Hash] additional configuration options
|
144
|
+
#
|
145
|
+
# @return [Domainic::Type::ComplexType] the created type
|
146
|
+
def _Complex: (**__todo__ options) -> ComplexType
|
147
|
+
|
148
|
+
# Creates a nilable ComplexType instance.
|
149
|
+
#
|
150
|
+
# @example
|
151
|
+
# type = _Complex?
|
152
|
+
# type.validate(Complex(1, 2)) # => true
|
153
|
+
#
|
154
|
+
# @param options [Hash] additional configuration options
|
155
|
+
#
|
156
|
+
# @return [Domainic::Type::UnionType] the created type (Complex or NilClass)
|
157
|
+
def _Complex?: (**__todo__ options) -> UnionType
|
158
|
+
|
114
159
|
# Creates a DateType instance.
|
115
160
|
#
|
116
161
|
# DateType restricts values to valid `Date` objects.
|
@@ -159,6 +204,34 @@ module Domainic
|
|
159
204
|
# @return [Domainic::Type::UnionType] the created type (DateTimeType or NilClass)
|
160
205
|
def _DateTime?: (**__todo__ options) -> UnionType
|
161
206
|
|
207
|
+
# Creates a DateTimeStringType instance.
|
208
|
+
#
|
209
|
+
# DateTimeStringType restricts values to valid date-time strings.
|
210
|
+
#
|
211
|
+
# @example
|
212
|
+
# type = _DateTimeString
|
213
|
+
# type.validate('2024-01-01T12:00:00Z') # => true
|
214
|
+
#
|
215
|
+
# @param options [Hash] additional configuration options
|
216
|
+
#
|
217
|
+
# @return [Domainic::Type::DateTimeStringType] the created type
|
218
|
+
def _DateTimeString: (**__todo__ options) -> DateTimeStringType
|
219
|
+
|
220
|
+
alias _DateString _DateTimeString
|
221
|
+
|
222
|
+
# Creates a nilable DateTimeStringType instance.
|
223
|
+
#
|
224
|
+
# @example
|
225
|
+
# _DateTimeString? === '2024-01-01T12:00:00Z' # => true
|
226
|
+
# _DateTimeString? === nil # => true
|
227
|
+
#
|
228
|
+
# @param options [Hash] additional configuration options
|
229
|
+
#
|
230
|
+
# @return [Domainic::Type::UnionType] the created type (DateTimeStringType or NilClass)
|
231
|
+
def _DateTimeString?: (**__todo__ options) -> UnionType
|
232
|
+
|
233
|
+
alias _DateString? _DateTimeString?
|
234
|
+
|
162
235
|
# Creates a DuckType instance.
|
163
236
|
#
|
164
237
|
# DuckType allows specifying behavior based on method availability.
|
@@ -395,6 +468,74 @@ module Domainic
|
|
395
468
|
|
396
469
|
alias _Nullable _Nilable
|
397
470
|
|
471
|
+
# Creates a RangeType instance.
|
472
|
+
#
|
473
|
+
# @example
|
474
|
+
# type = _Range
|
475
|
+
# type.validate(1..10) # => true
|
476
|
+
#
|
477
|
+
# @param options [Hash] additional configuration options
|
478
|
+
#
|
479
|
+
# @return [Domainic::Type::RangeType] the created type
|
480
|
+
def _Range: (**__todo__ options) -> RangeType
|
481
|
+
|
482
|
+
# Creates a nilable RangeType instance.
|
483
|
+
#
|
484
|
+
# @example
|
485
|
+
# type = _Range?
|
486
|
+
# type.validate(1..10) # => true
|
487
|
+
#
|
488
|
+
# @param options [Hash] additional configuration options
|
489
|
+
#
|
490
|
+
# @return [Domainic::Type::UnionType] the created type (Range or NilClass)
|
491
|
+
def _Range?: (**__todo__ options) -> UnionType
|
492
|
+
|
493
|
+
# Creates a RationalType instance.
|
494
|
+
#
|
495
|
+
# @example
|
496
|
+
# type = _Rational
|
497
|
+
# type.validate(Rational(1, 2)) # => true
|
498
|
+
#
|
499
|
+
# @param options [Hash] additional configuration options
|
500
|
+
#
|
501
|
+
# @return [Domainic::Type::RationalType] the created type
|
502
|
+
def _Rational: (**__todo__ options) -> RationalType
|
503
|
+
|
504
|
+
# Creates a nilable RationalType instance.
|
505
|
+
#
|
506
|
+
# @example
|
507
|
+
# type = _Rational?
|
508
|
+
# type.validate(Rational(1, 2)) # => true
|
509
|
+
# type.validate(nil) # => true
|
510
|
+
#
|
511
|
+
# @param options [Hash] additional configuration options
|
512
|
+
#
|
513
|
+
# @return [Domainic::Type::UnionType] the created type (Rational or NilClass)
|
514
|
+
def _Rational?: (**__todo__ options) -> UnionType
|
515
|
+
|
516
|
+
# Creates a SetType instance.
|
517
|
+
#
|
518
|
+
# @example
|
519
|
+
# type = _Set
|
520
|
+
# type.validate(Set[1, 2, 3]) # => true
|
521
|
+
#
|
522
|
+
# @param options [Hash] additional configuration options
|
523
|
+
#
|
524
|
+
# @return [Domainic::Type::SetType] the created type
|
525
|
+
def _Set: (**__todo__ options) -> SetType
|
526
|
+
|
527
|
+
# Creates a nilable SetType instance.
|
528
|
+
#
|
529
|
+
# @example
|
530
|
+
# type = _Set?
|
531
|
+
# type.validate(Set[1, 2, 3]) # => true
|
532
|
+
# type.validate(nil) # => true
|
533
|
+
#
|
534
|
+
# @param options [Hash] additional configuration options
|
535
|
+
#
|
536
|
+
# @return [Domainic::Type::UnionType] the created type (Set or NilClass)
|
537
|
+
def _Set?: (**__todo__ options) -> UnionType
|
538
|
+
|
398
539
|
# Creates a StringType instance.
|
399
540
|
#
|
400
541
|
# @example
|
@@ -467,6 +608,30 @@ module Domainic
|
|
467
608
|
# @return [Domainic::Type::UnionType] the created type (TimeType or NilClass)
|
468
609
|
def _Time?: (**__todo__ options) -> UnionType
|
469
610
|
|
611
|
+
# Creates a TimestampType instance.
|
612
|
+
#
|
613
|
+
# TimestampType restricts values to valid timestamps.
|
614
|
+
#
|
615
|
+
# @example
|
616
|
+
# type = _Timestamp
|
617
|
+
# type.validate(1640995200) # => true
|
618
|
+
#
|
619
|
+
# @param options [Hash] additional configuration options
|
620
|
+
#
|
621
|
+
# @return [Domainic::Type::TimestampType] the created type
|
622
|
+
def _Timestamp: (**__todo__ options) -> TimestampType
|
623
|
+
|
624
|
+
# Creates a nilable TimestampType instance.
|
625
|
+
#
|
626
|
+
# @example
|
627
|
+
# _Timestamp? === 1640995200 # => true
|
628
|
+
# _Timestamp? === nil # => true
|
629
|
+
#
|
630
|
+
# @param options [Hash] additional configuration options
|
631
|
+
#
|
632
|
+
# @return [Domainic::Type::UnionType] the created type (TimestampType or NilClass)
|
633
|
+
def _Timestamp?: (**__todo__ options) -> UnionType
|
634
|
+
|
470
635
|
# Creates a URIType instance.
|
471
636
|
#
|
472
637
|
# URIType restricts values to valid URIs.
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module Domainic
|
2
|
+
module Type
|
3
|
+
# A type for validating and constraining `Complex` numbers.
|
4
|
+
#
|
5
|
+
# This type extends `NumericBehavior` to provide a fluent interface for numeric-specific validations such as
|
6
|
+
# polarity and divisibility checks.
|
7
|
+
#
|
8
|
+
# @example Validating a `Complex` value
|
9
|
+
# type = Domainic::Type::ComplexType.new
|
10
|
+
# type.validate!(Complex(3, 4)) # => true
|
11
|
+
#
|
12
|
+
# @example Enforcing constraints
|
13
|
+
# type = Domainic::Type::ComplexType.new
|
14
|
+
# type.being_positive.validate!(Complex(42, 0)) # => raises TypeError
|
15
|
+
#
|
16
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
17
|
+
# @since 0.1.0
|
18
|
+
class ComplexType
|
19
|
+
extend Behavior::ClassMethods
|
20
|
+
|
21
|
+
include Behavior
|
22
|
+
|
23
|
+
include Behavior::NumericBehavior
|
24
|
+
|
25
|
+
# Constrain the Complex real to be divisible by a given divisor.
|
26
|
+
#
|
27
|
+
# @param arguments [Array<Numeric>] a list of arguments, typically one divisor
|
28
|
+
# @param options [Hash] additional options such as tolerance for floating-point checks
|
29
|
+
# @option options [Numeric] :divisor the divisor to check for divisibility
|
30
|
+
# @option options [Numeric] :tolerance the tolerance for floating-point checks
|
31
|
+
#
|
32
|
+
# @return [self] the current instance for chaining
|
33
|
+
def being_divisible_by: (*Numeric arguments, ?divisor: Numeric, ?tolerance: Numeric) -> Behavior
|
34
|
+
|
35
|
+
alias being_multiple_of being_divisible_by
|
36
|
+
|
37
|
+
alias divisible_by being_divisible_by
|
38
|
+
|
39
|
+
alias multiple_of being_divisible_by
|
40
|
+
|
41
|
+
# Constrain the Complex real to be even.
|
42
|
+
#
|
43
|
+
# @return [self] the current instance for chaining
|
44
|
+
def being_even: () -> Behavior
|
45
|
+
|
46
|
+
alias even being_even
|
47
|
+
|
48
|
+
alias not_being_odd being_even
|
49
|
+
|
50
|
+
# Constrain the Complex real to be negative.
|
51
|
+
#
|
52
|
+
# @return [self] the current instance for chaining
|
53
|
+
def being_negative: () -> Behavior
|
54
|
+
|
55
|
+
alias negative being_negative
|
56
|
+
|
57
|
+
alias not_being_positive being_negative
|
58
|
+
|
59
|
+
# Constrain the Complex real value to be odd.
|
60
|
+
#
|
61
|
+
# @return [self] the current instance for chaining
|
62
|
+
def being_odd: () -> Behavior
|
63
|
+
|
64
|
+
alias odd being_odd
|
65
|
+
|
66
|
+
alias not_being_even being_odd
|
67
|
+
|
68
|
+
# Constrain the Complex real to be positive.
|
69
|
+
#
|
70
|
+
# @return [self] the current instance for chaining
|
71
|
+
def being_positive: () -> Behavior
|
72
|
+
|
73
|
+
alias positive being_positive
|
74
|
+
|
75
|
+
alias not_being_negative being_positive
|
76
|
+
|
77
|
+
# Constrain the Complex real to not be divisible by a specific divisor.
|
78
|
+
#
|
79
|
+
# @note the divisor MUST be provided as an argument or in the options Hash.
|
80
|
+
#
|
81
|
+
# @param arguments [Array<Numeric>] a list of arguments, typically one divisor
|
82
|
+
# @param options [Hash] additional options such as tolerance for floating-point checks
|
83
|
+
# @option options [Numeric] :divisor the divisor to check for divisibility
|
84
|
+
# @option options [Numeric] :tolerance the tolerance for floating-point checks
|
85
|
+
#
|
86
|
+
# @return [self] the current instance for chaining
|
87
|
+
def not_being_divisible_by: (*Numeric arguments, ?divisor: Numeric, ?tolerance: Numeric) -> Behavior
|
88
|
+
|
89
|
+
alias not_being_multiple_of not_being_divisible_by
|
90
|
+
|
91
|
+
alias not_divisible_by not_being_divisible_by
|
92
|
+
|
93
|
+
alias not_multiple_of not_being_divisible_by
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Domainic
|
2
|
+
module Type
|
3
|
+
# A type for validating `Range` objects with comprehensive constraints.
|
4
|
+
#
|
5
|
+
# This class allows flexible validation of ranges, supporting type checks,
|
6
|
+
# inclusion/exclusion of values, and range-specific behaviors such as bounds validation.
|
7
|
+
# It integrates with `EnumerableBehavior` for enumerable-style validations
|
8
|
+
# (e.g., size constraints, element presence).
|
9
|
+
#
|
10
|
+
# Key features:
|
11
|
+
# - Ensures the value is a `Range`.
|
12
|
+
# - Supports constraints for range boundaries (`begin` and `end`).
|
13
|
+
# - Provides validations for inclusion and exclusion of values.
|
14
|
+
# - Leverages `EnumerableBehavior` for size and collection-style constraints.
|
15
|
+
#
|
16
|
+
# @example Basic usage
|
17
|
+
# type = RangeType.new
|
18
|
+
# type.having_bounds(1, 10) # Validates range bounds (inclusive or exclusive).
|
19
|
+
# type.containing(5) # Ensures value is within the range.
|
20
|
+
# type.not_containing(15) # Ensures value is not within the range.
|
21
|
+
#
|
22
|
+
# @example Integration with EnumerableBehavior
|
23
|
+
# type = RangeType.new
|
24
|
+
# type.having_size(10) # Validates size (total elements in the range).
|
25
|
+
# type.containing_exactly(3, 7) # Validates specific values within the range.
|
26
|
+
#
|
27
|
+
# @example Flexible boundaries
|
28
|
+
# type = RangeType.new
|
29
|
+
# type.having_bounds(1, 10, exclusive: true) # Upper and lower bounds are exclusive.
|
30
|
+
#
|
31
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
32
|
+
# @since 0.1.0
|
33
|
+
class RangeType
|
34
|
+
extend Behavior::ClassMethods
|
35
|
+
|
36
|
+
include Behavior
|
37
|
+
|
38
|
+
include Behavior::EnumerableBehavior
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Domainic
|
2
|
+
module Type
|
3
|
+
# A type for validating Rational numbers.
|
4
|
+
#
|
5
|
+
# This type ensures values are of type `Rational` and supports a range of
|
6
|
+
# constraints for numerical validation, such as positivity, negativity,
|
7
|
+
# and divisibility. It integrates with `NumericBehavior` to provide a
|
8
|
+
# consistent and fluent interface for numeric constraints.
|
9
|
+
#
|
10
|
+
# @example Validating a positive Rational number
|
11
|
+
# type = Domainic::Type::RationalType.new
|
12
|
+
# type.being_positive.validate!(Rational(3, 4)) # => true
|
13
|
+
#
|
14
|
+
# @example Validating divisibility
|
15
|
+
# type = Domainic::Type::RationalType.new
|
16
|
+
# type.being_divisible_by(1).validate!(Rational(3, 1)) # => true
|
17
|
+
#
|
18
|
+
# @example Using constraints with chaining
|
19
|
+
# type = Domainic::Type::RationalType.new
|
20
|
+
# type.being_greater_than(0).being_less_than(1).validate!(Rational(1, 2)) # => true
|
21
|
+
#
|
22
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
23
|
+
# @since 0.1.0
|
24
|
+
class RationalType
|
25
|
+
extend Behavior::ClassMethods
|
26
|
+
|
27
|
+
include Behavior
|
28
|
+
|
29
|
+
include Behavior::NumericBehavior
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Domainic
|
2
|
+
module Type
|
3
|
+
# A type for validating and constraining `BigDecimal` objects.
|
4
|
+
#
|
5
|
+
# This type extends `NumericBehavior` to provide a fluent interface for numeric-specific validations such as being
|
6
|
+
# positive, being within a range, or satisfying divisibility rules.
|
7
|
+
#
|
8
|
+
# @example Validating a `BigDecimal` value
|
9
|
+
# type = Domainic::Type::BigDecimalType.new
|
10
|
+
# type.validate!(BigDecimal('3.14')) # => true
|
11
|
+
#
|
12
|
+
# @example Enforcing constraints
|
13
|
+
# type = Domainic::Type::BigDecimalType.new
|
14
|
+
# type.being_positive.validate!(BigDecimal('42')) # => true
|
15
|
+
# type.being_positive.validate!(BigDecimal('-42')) # raises TypeError
|
16
|
+
#
|
17
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
18
|
+
# @since 0.1.0
|
19
|
+
class BigDecimalType
|
20
|
+
extend Behavior::ClassMethods
|
21
|
+
|
22
|
+
include Behavior
|
23
|
+
|
24
|
+
include Behavior::NumericBehavior
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|