domainic-type 0.1.0.alpha.3.2.0 → 0.1.0.alpha.3.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,12 +4,12 @@ module Domainic
4
4
  module Type
5
5
  # @rbs!
6
6
  # type accessor = :abs | :begin | :chars | :class | :count | :end | :entries | :first | :keys | :last | :length |
7
- # :self | :size | :values
7
+ # :real | :self | :size | :values
8
8
 
9
9
  # A list of valid access methods that can be used to retrieve values for constraint validation.
10
10
  # These methods represent common Ruby interfaces for accessing collection sizes, ranges, and values.
11
11
  #
12
- # - :abs - For absolute values
12
+ # - :abs, :real - For absolute values
13
13
  # - :begin, :end - For Range-like objects
14
14
  # - :class - For type checking
15
15
  # - :count, :length, :size - For measuring collections
@@ -27,6 +27,7 @@ module Domainic
27
27
  entries
28
28
  chars
29
29
  abs
30
+ real
30
31
  count
31
32
  size
32
33
  length
@@ -28,13 +28,89 @@ module Domainic
28
28
  # @author {https://aaronmallen.me Aaron Allen}
29
29
  # @since 0.1.0
30
30
  module DateTimeBehavior
31
+ # The supported date/time patterns for parsing date/time strings
32
+ #
33
+ # @note This list is ordered from most specific to least specific to ensure that the most specific patterns are
34
+ # tried first. This is important because some patterns are more lenient than others and may match a wider range
35
+ # of input strings.
36
+ #
37
+ # @return [Array<String>] the supported date/time patterns
38
+ DATETIME_PATTERNS = [
39
+ # ISO 8601 variants (most specific first)
40
+ '%Y-%m-%dT%H:%M:%S.%N%:z', # 2024-01-01T12:00:00.000+00:00
41
+ '%Y-%m-%dT%H:%M:%S%:z', # 2024-01-01T12:00:00+00:00
42
+ '%Y-%m-%dT%H:%M:%S.%N', # 2024-01-01T12:00:00.000
43
+ '%Y-%m-%dT%H:%M:%S', # 2024-01-01T12:00:00
44
+ '%Y%m%dT%H%M%S%z', # 20240101T120000+0000 (basic format)
45
+
46
+ # RFC formats
47
+ '%a, %d %b %Y %H:%M:%S %z', # Thu, 31 Jan 2024 13:30:00 +0000
48
+ '%d %b %Y %H:%M:%S %z', # 31 Jan 2024 13:30:00 +0000
49
+
50
+ # Common datetime formats with timezone
51
+ '%Y-%m-%d %H:%M:%S %z', # 2024-01-01 12:00:00 +0000
52
+ '%d/%m/%Y %H:%M:%S %z', # 31/01/2024 12:00:00 +0000
53
+
54
+ # Full date + time formats (24h)
55
+ '%Y-%m-%d %H:%M:%S', # 2024-01-01 12:00:00
56
+ '%Y-%m-%d %H:%M', # 2024-01-01 12:00
57
+ '%d/%m/%Y %H:%M:%S', # 31/01/2024 12:00:00
58
+ '%d/%m/%Y %H:%M', # 31/01/2024 12:00
59
+ '%d-%m-%Y %H:%M:%S', # 31-01-2024 12:00:00
60
+ '%d-%m-%Y %H:%M', # 31-01-2024 12:00
61
+ '%Y/%m/%d %H:%M:%S', # 2024/01/31 12:00:00
62
+ '%Y/%m/%d %H:%M', # 2024/01/31 12:00
63
+
64
+ # Full date + time formats (12h)
65
+ '%Y-%m-%d %I:%M:%S %p', # 2024-01-01 01:30:00 PM
66
+ '%Y-%m-%d %I:%M %p', # 2024-01-01 01:30 PM
67
+ '%d/%m/%Y %I:%M:%S %p', # 31/01/2024 01:30:00 PM
68
+ '%d/%m/%Y %I:%M %p', # 31/01/2024 01:30 PM
69
+
70
+ # Full month name formats
71
+ '%B %d, %Y %H:%M:%S', # January 31, 2024 12:00:00
72
+ '%B %d, %Y %H:%M', # January 31, 2024 12:00
73
+ '%d %B %Y %H:%M:%S', # 31 January 2024 12:00:00
74
+ '%d %B %Y %H:%M', # 31 January 2024 12:00
75
+
76
+ # Abbreviated month name formats
77
+ '%b %d, %Y %H:%M:%S', # Jan 31, 2024 12:00:00
78
+ '%b %d, %Y %H:%M', # Jan 31, 2024 12:00
79
+ '%d %b %Y %H:%M:%S', # 31 Jan 2024 12:00:00
80
+ '%d %b %Y %H:%M', # 31 Jan 2024 12:00
81
+
82
+ # Date-only formats (in order of specificity)
83
+ '%Y-%m-%d', # 2024-01-31
84
+ '%Y%m%d', # 20240131
85
+ '%B %d, %Y', # January 31, 2024
86
+ '%d %B %Y', # 31 January 2024
87
+ '%b %d, %Y', # Jan 31, 2024
88
+ '%d %b %Y', # 31 Jan 2024
89
+ '%d/%m/%Y', # 31/01/2024
90
+ '%d-%m-%Y', # 31-01-2024
91
+ '%Y/%m/%d', # 2024/01/31
92
+ '%m/%d/%Y' # 01/31/2024 (US format - last to avoid ambiguity)
93
+ ].freeze #: Array[String]
94
+
95
+ # Coerce a value to a Date, DateTime, or Time object
96
+ #
97
+ # @return [Proc] a lambda that coerces a value to a Date, DateTime, or Time object
31
98
  TO_DATETIME_COERCER = lambda { |value|
32
- if [Date, DateTime, Time].any? { |type| value.is_a?(type) }
99
+ case value
100
+ when Date, DateTime, Time
33
101
  value
102
+ when Integer
103
+ Time.at(value).to_datetime
104
+ when String
105
+ DATETIME_PATTERNS.each do |pattern|
106
+ return DateTime.strptime(value, pattern)
107
+ rescue ArgumentError
108
+ next
109
+ end
34
110
  else
35
- DateTime.parse(value.to_s)
111
+ DateTime.parse(value) # Fallback to Ruby's built-in parser and allow it to raise.
36
112
  end
37
- } #: Proc
113
+ } #: ^(Date | DateTime | Integer | String | Time value) -> (Date | DateTime | Time)
38
114
 
39
115
  class << self
40
116
  private
@@ -44,39 +120,39 @@ module Domainic
44
120
  # @note this in my opinion is better than polluting the namespace of the including class even with a private
45
121
  # method. This way, the method is only available within the module itself. See {#being_between}.
46
122
  #
47
- # @param after [Date, DateTime, String, Time, nil] minimum size value from positional args
48
- # @param before [Date, DateTime, String, Time, nil] maximum size value from positional args
123
+ # @param after [Date, DateTime, Integer, String, Time, nil] minimum size value from positional args
124
+ # @param before [Date, DateTime, Integer, String, Time, nil] maximum size value from positional args
49
125
  # @param options [Hash] keyword arguments containing after/before values
50
126
  #
51
127
  # @raise [ArgumentError] if minimum or maximum value can't be determined
52
- # @return [Array<Date, DateTime, String, Time, nil>] parsed [after, before] values
128
+ # @return [Array<Date, DateTime, Integer, String, Time, nil>] parsed [after, before] values
53
129
  # @rbs (
54
- # (Date | DateTime | String | Time)? after,
55
- # (Date | DateTime | String | Time)? before,
56
- # Hash[Symbol, (Date | DateTime | String | Time)?] options
57
- # ) -> Array[(Date | DateTime | String | Time)?]
130
+ # (Date | DateTime | Integer | String | Time)? after,
131
+ # (Date | DateTime | Integer | String | Time)? before,
132
+ # Hash[Symbol, (Date | DateTime | Integer | String | Time)?] options
133
+ # ) -> Array[(Date | DateTime | Integer | String | Time)?]
58
134
  def parse_being_between_arguments!(after, before, options)
59
135
  after ||= options[:after]
60
136
  before ||= options[:before]
61
137
  raise_being_between_argument_error!(caller, after, before, options) if after.nil? || before.nil?
62
138
 
63
- [after, before] #: Array[(Date | DateTime | String | Time)?]
139
+ [after, before] #: Array[(Date | DateTime | Integer | String | Time)?]
64
140
  end
65
141
 
66
142
  # Raise appropriate ArgumentError for being_between
67
143
  #
68
144
  # @param original_caller [Array<String>] caller stack for error
69
- # @param after [Date, DateTime, String, Time, nil] after value from positional args
70
- # @param before [Date, DateTime, String, Time, nil] before value from positional args
145
+ # @param after [Date, DateTime, Integer, String, Time, nil] after value from positional args
146
+ # @param before [Date, DateTime, Integer, String, Time, nil] before value from positional args
71
147
  # @param options [Hash] keyword arguments containing after/before values
72
148
  #
73
149
  # @raise [ArgumentError] with appropriate message
74
150
  # @return [void]
75
151
  # @rbs (
76
152
  # Array[String] original_caller,
77
- # (Date | DateTime | String | Time)? after,
78
- # (Date | DateTime | String | Time)? before,
79
- # Hash[Symbol, (Date | DateTime | String | Time)?] options
153
+ # (Date | DateTime | Integer | String | Time)? after,
154
+ # (Date | DateTime | Integer | String | Time)? before,
155
+ # Hash[Symbol, (Date | DateTime | Integer | String | Time)?] options
80
156
  # ) -> void
81
157
  def raise_being_between_argument_error!(original_caller, after, before, options)
82
158
  message = if options.empty?
@@ -93,66 +169,70 @@ module Domainic
93
169
 
94
170
  # Constrain the value to be chronologically after a given date/time
95
171
  #
96
- # @param other [Date, DateTime, String, Time] the date/time to compare against
172
+ # @param other [Date, DateTime, Integer, String, Time] the date/time to compare against
97
173
  # @return [self] self for method chaining
98
- # @rbs (Date | DateTime | String | Time other) -> Behavior
174
+ # @rbs (Date | DateTime | Integer | String | Time other) -> Behavior
99
175
  def being_after(other)
100
176
  # @type self: Object & Behavior
101
- constrain :self, :range, { minimum: other },
177
+ constrain :self, :range, { minimum: TO_DATETIME_COERCER.call(other) },
102
178
  coerce_with: TO_DATETIME_COERCER, description: 'being', inclusive: false
103
179
  end
104
180
  alias after being_after
105
181
 
106
182
  # Constrain the value to be chronologically before a given date/time
107
183
  #
108
- # @param other [Date, DateTime, String, Time] the date/time to compare against
184
+ # @param other [Date, DateTime, Integer, String, Time] the date/time to compare against
109
185
  # @return [self] self for method chaining
110
- # @rbs (Date | DateTime | String | Time other) -> Behavior
186
+ # @rbs (Date | DateTime | Integer | String | Time other) -> Behavior
111
187
  def being_before(other)
112
188
  # @type self: Object & Behavior
113
- constrain :self, :range, { maximum: other },
189
+ constrain :self, :range, { maximum: TO_DATETIME_COERCER.call(other) },
114
190
  coerce_with: TO_DATETIME_COERCER, description: 'being', inclusive: false
115
191
  end
116
192
  alias before being_before
117
193
 
118
194
  # Constrain the value to be chronologically between two date/times
119
195
  #
120
- # @param after [Date, DateTime, String, Time] the earliest allowed date/time
121
- # @param before [Date, DateTime, String, Time] the latest allowed date/time
196
+ # @param after [Date, DateTime, Integer, String, Time] the earliest allowed date/time
197
+ # @param before [Date, DateTime, Integer, String, Time] the latest allowed date/time
122
198
  # @param options [Hash] alternative way to specify after/before via keywords
123
- # @option options [Date, DateTime, String, Time] :after earliest allowed date/time
124
- # @option options [Date, DateTime, String, Time] :before latest allowed date/time
199
+ # @option options [Date, DateTime, Integer, String, Time] :after earliest allowed date/time
200
+ # @option options [Date, DateTime, Integer, String, Time] :before latest allowed date/time
125
201
  # @return [self] self for method chaining
126
- # @rbs (Date | DateTime | String | Time after, Date | DateTime | String | Time before) -> Behavior
202
+ # @rbs (
203
+ # Date | DateTime | Integer | String | Time after,
204
+ # Date | DateTime | Integer | String | Time before
205
+ # ) -> Behavior
127
206
  def being_between(after = nil, before = nil, **options)
128
207
  # @type self: Object & Behavior
129
208
  after, before =
130
209
  DateTimeBehavior.send(:parse_being_between_arguments!, after, before, options.transform_keys(&:to_sym))
131
- constrain :self, :range, { minimum: after, maximum: before },
210
+ constrain :self, :range,
211
+ { minimum: TO_DATETIME_COERCER.call(after), maximum: TO_DATETIME_COERCER.call(before) },
132
212
  coerce_with: TO_DATETIME_COERCER, description: 'being', inclusive: false
133
213
  end
134
214
  alias between being_between
135
215
 
136
216
  # Constrain the value to be exactly equal to a given date/time
137
217
  #
138
- # @param other [Date, DateTime, String, Time] the date/time to compare against
218
+ # @param other [Date, DateTime, Integer, String, Time] the date/time to compare against
139
219
  # @return [self] self for method chaining
140
- # @rbs (Date | DateTime | String | Time other) -> Behavior
220
+ # @rbs (Date | DateTime | Integer | String | Time other) -> Behavior
141
221
  def being_equal_to(other)
142
222
  # @type self: Object & Behavior
143
- constrain :self, :equality, other,
223
+ constrain :self, :equality, TO_DATETIME_COERCER.call(other),
144
224
  coerce_with: TO_DATETIME_COERCER, description: 'being'
145
225
  end
146
226
  alias at being_equal_to
147
227
 
148
228
  # Constrain the value to be chronologically on or after a given date/time
149
229
  #
150
- # @param other [Date, DateTime, String, Time] the date/time to compare against
230
+ # @param other [Date, DateTime, Integer, String, Time] the date/time to compare against
151
231
  # @return [self] self for method chaining
152
- # @rbs (Date | DateTime | String | Time other) -> Behavior
232
+ # @rbs (Date | DateTime | Integer | String | Time other) -> Behavior
153
233
  def being_on_or_after(other)
154
234
  # @type self: Object & Behavior
155
- constrain :self, :range, { minimum: other },
235
+ constrain :self, :range, { minimum: TO_DATETIME_COERCER.call(other) },
156
236
  coerce_with: TO_DATETIME_COERCER, description: 'being'
157
237
  end
158
238
  alias at_or_after being_on_or_after
@@ -161,12 +241,12 @@ module Domainic
161
241
 
162
242
  # Constrain the value to be chronologically on or before a given date/time
163
243
  #
164
- # @param other [Date, DateTime, String, Time] the date/time to compare against
244
+ # @param other [Date, DateTime, Integer, String, Time] the date/time to compare against
165
245
  # @return [self] self for method chaining
166
- # @rbs (Date | DateTime | String | Time other) -> Behavior
246
+ # @rbs (Date | DateTime | Integer | String | Time other) -> Behavior
167
247
  def being_on_or_before(other)
168
248
  # @type self: Object & Behavior
169
- constrain :self, :range, { maximum: other },
249
+ constrain :self, :range, { maximum: TO_DATETIME_COERCER.call(other) },
170
250
  coerce_with: TO_DATETIME_COERCER, description: 'being'
171
251
  end
172
252
  alias at_or_before being_on_or_before
@@ -78,6 +78,12 @@ types:
78
78
  anything:
79
79
  constant: Domainic::Type::AnythingType
80
80
  require_path: domainic/type/types/specification/anything_type
81
+ big_decimal:
82
+ constant: Domainic::Type::BigDecimalType
83
+ require_path: domainic/type/types/core_extended/big_decimal_type
84
+ complex:
85
+ constant: Domainic::Type::ComplexType
86
+ require_path: domainic/type/types/core/complex_type
81
87
  cuid:
82
88
  constant: Domainic::Type::CUIDType
83
89
  require_path: domainic/type/types/identifier/cuid_type
@@ -87,6 +93,9 @@ types:
87
93
  date_time:
88
94
  constant: Domainic::Type::DateTimeType
89
95
  require_path: domainic/type/types/datetime/date_time_type
96
+ date_time_string:
97
+ constant: Domainic::Type::DateTimeStringType
98
+ require_path: domainic/type/types/datetime/date_time_string_type
90
99
  duck:
91
100
  constant: Domainic::Type::DuckType
92
101
  require_path: domainic/type/types/specification/duck_type
@@ -111,6 +120,15 @@ types:
111
120
  integer:
112
121
  constant: Domainic::Type::IntegerType
113
122
  require_path: domainic/type/types/core/integer_type
123
+ range:
124
+ constant: Domainic::Type::RangeType
125
+ require_path: domainic/type/types/core/range_type
126
+ rational:
127
+ constant: Domainic::Type::RationalType
128
+ require_path: domainic/type/types/core/rational_type
129
+ set:
130
+ constant: Domainic::Type::SetType
131
+ require_path: domainic/type/types/core_extended/set_type
114
132
  string:
115
133
  constant: Domainic::Type::StringType
116
134
  require_path: domainic/type/types/core/string_type
@@ -120,6 +138,9 @@ types:
120
138
  time:
121
139
  constant: Domainic::Type::TimeType
122
140
  require_path: domainic/type/types/datetime/time_type
141
+ timestamp:
142
+ constant: Domainic::Type::TimestampType
143
+ require_path: domainic/type/types/datetime/timestamp_type
123
144
  union:
124
145
  constant: Domainic::Type::UnionType
125
146
  require_path: domainic/type/types/specification/union_type
@@ -77,6 +77,36 @@ module Domainic
77
77
  end
78
78
  alias _List? _Array?
79
79
 
80
+ # Creates a BigDecimalType instance.
81
+ #
82
+ # @example
83
+ # type = _BigDecimal
84
+ # type.validate(BigDecimal('123.45')) # => true
85
+ #
86
+ # @param options [Hash] additional configuration options
87
+ #
88
+ # @return [Domainic::Type::BigDecimalType] the created type
89
+ # @rbs (**__todo__ options) -> BigDecimalType
90
+ def _BigDecimal(**options)
91
+ require 'domainic/type/types/core_extended/big_decimal_type'
92
+ Domainic::Type::BigDecimalType.new(**options)
93
+ end
94
+
95
+ # Creates a nilable BigDecimalType instance.
96
+ #
97
+ # @example
98
+ # type = _BigDecimal?
99
+ # type.validate(BigDecimal('123.45')) # => true
100
+ # type.validate(nil) # => true
101
+ #
102
+ # @param options [Hash] additional configuration options
103
+ #
104
+ # @return [Domainic::Type::UnionType] the created type (BigDecimal or NilClass)
105
+ # @rbs (**__todo__ options) -> UnionType
106
+ def _BigDecimal?(**options)
107
+ _Nilable(_BigDecimal(**options))
108
+ end
109
+
80
110
  # Creates a Boolean type.
81
111
  #
82
112
  # Represents a union of TrueClass and FalseClass.
@@ -133,6 +163,35 @@ module Domainic
133
163
  end
134
164
  alias _Cuid? _CUID?
135
165
 
166
+ # Creates a ComplexType instance.
167
+ #
168
+ # @example
169
+ # type = _Complex
170
+ # type.validate(Complex(1, 2)) # => true
171
+ #
172
+ # @param options [Hash] additional configuration options
173
+ #
174
+ # @return [Domainic::Type::ComplexType] the created type
175
+ # @rbs (**__todo__ options) -> ComplexType
176
+ def _Complex(**options)
177
+ require 'domainic/type/types/core/complex_type'
178
+ Domainic::Type::ComplexType.new(**options)
179
+ end
180
+
181
+ # Creates a nilable ComplexType instance.
182
+ #
183
+ # @example
184
+ # type = _Complex?
185
+ # type.validate(Complex(1, 2)) # => true
186
+ #
187
+ # @param options [Hash] additional configuration options
188
+ #
189
+ # @return [Domainic::Type::UnionType] the created type (Complex or NilClass)
190
+ # @rbs (**__todo__ options) -> UnionType
191
+ def _Complex?(**options)
192
+ _Nilable(_Complex(**options))
193
+ end
194
+
136
195
  # Creates a DateType instance.
137
196
  #
138
197
  # DateType restricts values to valid `Date` objects.
@@ -195,6 +254,39 @@ module Domainic
195
254
  _Nilable(_DateTime(**options))
196
255
  end
197
256
 
257
+ # Creates a DateTimeStringType instance.
258
+ #
259
+ # DateTimeStringType restricts values to valid date-time strings.
260
+ #
261
+ # @example
262
+ # type = _DateTimeString
263
+ # type.validate('2024-01-01T12:00:00Z') # => true
264
+ #
265
+ # @param options [Hash] additional configuration options
266
+ #
267
+ # @return [Domainic::Type::DateTimeStringType] the created type
268
+ # @rbs (**__todo__ options) -> DateTimeStringType
269
+ def _DateTimeString(**options)
270
+ require 'domainic/type/types/datetime/date_time_string_type'
271
+ Domainic::Type::DateTimeStringType.new(**options)
272
+ end
273
+ alias _DateString _DateTimeString
274
+
275
+ # Creates a nilable DateTimeStringType instance.
276
+ #
277
+ # @example
278
+ # _DateTimeString? === '2024-01-01T12:00:00Z' # => true
279
+ # _DateTimeString? === nil # => true
280
+ #
281
+ # @param options [Hash] additional configuration options
282
+ #
283
+ # @return [Domainic::Type::UnionType] the created type (DateTimeStringType or NilClass)
284
+ # @rbs (**__todo__ options) -> UnionType
285
+ def _DateTimeString?(**options)
286
+ _Nilable(_DateTimeString(**options))
287
+ end
288
+ alias _DateString? _DateTimeString?
289
+
198
290
  # Creates a DuckType instance.
199
291
  #
200
292
  # DuckType allows specifying behavior based on method availability.
@@ -477,6 +569,95 @@ module Domainic
477
569
  end
478
570
  alias _Nullable _Nilable
479
571
 
572
+ # Creates a RangeType instance.
573
+ #
574
+ # @example
575
+ # type = _Range
576
+ # type.validate(1..10) # => true
577
+ #
578
+ # @param options [Hash] additional configuration options
579
+ #
580
+ # @return [Domainic::Type::RangeType] the created type
581
+ # @rbs (**__todo__ options) -> RangeType
582
+ def _Range(**options)
583
+ require 'domainic/type/types/core/range_type'
584
+ Domainic::Type::RangeType.new(**options)
585
+ end
586
+
587
+ # Creates a nilable RangeType instance.
588
+ #
589
+ # @example
590
+ # type = _Range?
591
+ # type.validate(1..10) # => true
592
+ #
593
+ # @param options [Hash] additional configuration options
594
+ #
595
+ # @return [Domainic::Type::UnionType] the created type (Range or NilClass)
596
+ # @rbs (**__todo__ options) -> UnionType
597
+ def _Range?(**options)
598
+ _Nilable(_Range(**options))
599
+ end
600
+
601
+ # Creates a RationalType instance.
602
+ #
603
+ # @example
604
+ # type = _Rational
605
+ # type.validate(Rational(1, 2)) # => true
606
+ #
607
+ # @param options [Hash] additional configuration options
608
+ #
609
+ # @return [Domainic::Type::RationalType] the created type
610
+ # @rbs (**__todo__ options) -> RationalType
611
+ def _Rational(**options)
612
+ require 'domainic/type/types/core/rational_type'
613
+ Domainic::Type::RationalType.new(**options)
614
+ end
615
+
616
+ # Creates a nilable RationalType instance.
617
+ #
618
+ # @example
619
+ # type = _Rational?
620
+ # type.validate(Rational(1, 2)) # => true
621
+ # type.validate(nil) # => true
622
+ #
623
+ # @param options [Hash] additional configuration options
624
+ #
625
+ # @return [Domainic::Type::UnionType] the created type (Rational or NilClass)
626
+ # @rbs (**__todo__ options) -> UnionType
627
+ def _Rational?(**options)
628
+ _Nilable(_Rational(**options))
629
+ end
630
+
631
+ # Creates a SetType instance.
632
+ #
633
+ # @example
634
+ # type = _Set
635
+ # type.validate(Set[1, 2, 3]) # => true
636
+ #
637
+ # @param options [Hash] additional configuration options
638
+ #
639
+ # @return [Domainic::Type::SetType] the created type
640
+ # @rbs (**__todo__ options) -> SetType
641
+ def _Set(**options)
642
+ require 'domainic/type/types/core_extended/set_type'
643
+ Domainic::Type::SetType.new(**options)
644
+ end
645
+
646
+ # Creates a nilable SetType instance.
647
+ #
648
+ # @example
649
+ # type = _Set?
650
+ # type.validate(Set[1, 2, 3]) # => true
651
+ # type.validate(nil) # => true
652
+ #
653
+ # @param options [Hash] additional configuration options
654
+ #
655
+ # @return [Domainic::Type::UnionType] the created type (Set or NilClass)
656
+ # @rbs (**__todo__ options) -> UnionType
657
+ def _Set?(**options)
658
+ _Nilable(_Set(**options))
659
+ end
660
+
480
661
  # Creates a StringType instance.
481
662
  #
482
663
  # @example
@@ -568,6 +749,37 @@ module Domainic
568
749
  _Nilable(_Time(**options))
569
750
  end
570
751
 
752
+ # Creates a TimestampType instance.
753
+ #
754
+ # TimestampType restricts values to valid timestamps.
755
+ #
756
+ # @example
757
+ # type = _Timestamp
758
+ # type.validate(1640995200) # => true
759
+ #
760
+ # @param options [Hash] additional configuration options
761
+ #
762
+ # @return [Domainic::Type::TimestampType] the created type
763
+ # @rbs (**__todo__ options) -> TimestampType
764
+ def _Timestamp(**options)
765
+ require 'domainic/type/types/datetime/timestamp_type'
766
+ Domainic::Type::TimestampType.new(**options)
767
+ end
768
+
769
+ # Creates a nilable TimestampType instance.
770
+ #
771
+ # @example
772
+ # _Timestamp? === 1640995200 # => true
773
+ # _Timestamp? === nil # => true
774
+ #
775
+ # @param options [Hash] additional configuration options
776
+ #
777
+ # @return [Domainic::Type::UnionType] the created type (TimestampType or NilClass)
778
+ # @rbs (**__todo__ options) -> UnionType
779
+ def _Timestamp?(**options)
780
+ _Nilable(_Timestamp(**options))
781
+ end
782
+
571
783
  # Creates a URIType instance.
572
784
  #
573
785
  # URIType restricts values to valid URIs.