domainic-type 0.1.0.alpha.3.0.2 → 0.1.0.alpha.3.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/lib/domainic/type/behavior/string_behavior/matching_behavior.rb +115 -0
  3. data/lib/domainic/type/behavior/string_behavior.rb +2 -111
  4. data/lib/domainic/type/behavior/uri_behavior.rb +97 -0
  5. data/lib/domainic/type/behavior.rb +21 -1
  6. data/lib/domainic/type/config/registry.yml +15 -0
  7. data/lib/domainic/type/definitions.rb +182 -1
  8. data/lib/domainic/type/types/core/array_type.rb +1 -1
  9. data/lib/domainic/type/types/core/float_type.rb +1 -1
  10. data/lib/domainic/type/types/core/hash_type.rb +1 -1
  11. data/lib/domainic/type/types/core/integer_type.rb +1 -1
  12. data/lib/domainic/type/types/core/string_type.rb +1 -1
  13. data/lib/domainic/type/types/core/symbol_type.rb +1 -1
  14. data/lib/domainic/type/types/identifier/cuid_type.rb +140 -0
  15. data/lib/domainic/type/types/identifier/uuid_type.rb +513 -0
  16. data/lib/domainic/type/types/network/email_address_type.rb +149 -0
  17. data/lib/domainic/type/types/network/hostname_type.rb +107 -0
  18. data/lib/domainic/type/types/network/uri_type.rb +224 -0
  19. data/sig/domainic/type/behavior/string_behavior/matching_behavior.rbs +84 -0
  20. data/sig/domainic/type/behavior/string_behavior.rbs +2 -82
  21. data/sig/domainic/type/behavior/uri_behavior.rbs +95 -0
  22. data/sig/domainic/type/behavior.rbs +9 -0
  23. data/sig/domainic/type/definitions.rbs +149 -1
  24. data/sig/domainic/type/types/identifier/cuid_type.rbs +110 -0
  25. data/sig/domainic/type/types/identifier/uuid_type.rbs +469 -0
  26. data/sig/domainic/type/types/network/email_address_type.rbs +127 -0
  27. data/sig/domainic/type/types/network/hostname_type.rbs +76 -0
  28. data/sig/domainic/type/types/network/uri_type.rbs +159 -0
  29. metadata +20 -6
@@ -0,0 +1,469 @@
1
+ module Domainic
2
+ # NOTE: This file is located at lib/domainic/type/types/identifier/uuid_type.rb
3
+ module Type
4
+ # A type for validating UUIDs according to RFC 4122 standards
5
+ #
6
+ # This type provides comprehensive UUID validation following RFC 4122 standards.
7
+ # It supports both standard (hyphenated) and compact formats for all UUID versions
8
+ # (1 through 7), while enforcing proper formatting and version-specific constraints.
9
+ #
10
+ # Key features:
11
+ # - RFC 4122 compliant UUID format validation
12
+ # - Support for versions 1-7
13
+ # - Standard (hyphenated) and compact format support
14
+ # - Length validation (36 chars for standard, 32 for compact)
15
+ # - Version-specific validation
16
+ #
17
+ # @example Basic usage
18
+ # type = UUIDType.new
19
+ # type.validate("123e4567-e89b-12d3-a456-426614174000") # => true
20
+ # type.validate("invalid") # => false
21
+ #
22
+ # @example With version constraints
23
+ # type = UUIDType.new.being_version(4)
24
+ # type.validate("123e4567-e89b-42d3-a456-426614174000") # => true
25
+ #
26
+ # @example With format constraints
27
+ # type = UUIDType.new.being_compact
28
+ # type.validate("123e4567e89b12d3a456426614174000") # => true
29
+ #
30
+ # @author {https://aaronmallen.me Aaron Allen}
31
+ # @since 0.1.0
32
+ class UUIDType
33
+ extend Behavior::ClassMethods
34
+
35
+ include Behavior
36
+
37
+ # Contains UUID validation regular expressions and version-specific modules
38
+ #
39
+ # This module provides both standard (hyphenated) and compact format regular
40
+ # expressions for UUID validation, along with version-specific submodules for
41
+ # more granular validation requirements.
42
+ #
43
+ # @since 0.1.0
44
+ module UUID
45
+ # Regular expression for standard (hyphenated) UUID format
46
+ #
47
+ # Validates UUIDs in the format: 8-4-4-4-12 hexadecimal digits with hyphens
48
+ # Example: "123e4567-e89b-12d3-a456-426614174000"
49
+ #
50
+ # @since 0.1.0
51
+ STANDARD_REGEXP: Regexp
52
+
53
+ # Regular expression for compact (non-hyphenated) UUID format
54
+ #
55
+ # Validates UUIDs in the format: 32 continuous hexadecimal digits
56
+ # Example: "123e4567e89b12d3a456426614174000"
57
+ #
58
+ # @since 0.1.0
59
+ COMPACT_REGEXP: Regexp
60
+
61
+ # Version 1 UUID validation patterns
62
+ #
63
+ # Provides regular expressions for validating time-based Version 1 UUIDs.
64
+ # These UUIDs are generated using a timestamp and node ID.
65
+ #
66
+ # @since 0.1.0
67
+ module V1
68
+ # Standard format regex for Version 1 UUIDs
69
+ # @return [Regexp] Pattern matching hyphenated Version 1 UUIDs
70
+ STANDARD_REGEXP: Regexp
71
+
72
+ # Compact format regex for Version 1 UUIDs
73
+ # @return [Regexp] Pattern matching non-hyphenated Version 1 UUIDs
74
+ COMPACT_REGEXP: Regexp
75
+ end
76
+
77
+ # Version 2 UUID validation patterns
78
+ #
79
+ # Provides regular expressions for validating DCE Security Version 2 UUIDs.
80
+ # These UUIDs incorporate local domain identifiers.
81
+ #
82
+ # @since 0.1.0
83
+ module V2
84
+ # Standard format regex for Version 2 UUIDs
85
+ # @return [Regexp] Pattern matching hyphenated Version 2 UUIDs
86
+ STANDARD_REGEXP: Regexp
87
+
88
+ # Compact format regex for Version 2 UUIDs
89
+ # @return [Regexp] Pattern matching non-hyphenated Version 2 UUIDs
90
+ COMPACT_REGEXP: Regexp
91
+ end
92
+
93
+ # Version 3 UUID validation patterns
94
+ #
95
+ # Provides regular expressions for validating name-based Version 3 UUIDs
96
+ # using MD5 hashing.
97
+ #
98
+ # @since 0.1.0
99
+ module V3
100
+ # Standard format regex for Version 3 UUIDs
101
+ # @return [Regexp] Pattern matching hyphenated Version 3 UUIDs
102
+ STANDARD_REGEXP: Regexp
103
+
104
+ # Compact format regex for Version 3 UUIDs
105
+ # @return [Regexp] Pattern matching non-hyphenated Version 3 UUIDs
106
+ COMPACT_REGEXP: Regexp
107
+ end
108
+
109
+ # Version 4 UUID validation patterns
110
+ #
111
+ # Provides regular expressions for validating randomly generated Version 4
112
+ # UUIDs. These are the most commonly used UUID format.
113
+ #
114
+ # @since 0.1.0
115
+ module V4
116
+ # Standard format regex for Version 4 UUIDs
117
+ # @return [Regexp] Pattern matching hyphenated Version 4 UUIDs
118
+ STANDARD_REGEXP: Regexp
119
+
120
+ # Compact format regex for Version 4 UUIDs
121
+ # @return [Regexp] Pattern matching non-hyphenated Version 4 UUIDs
122
+ COMPACT_REGEXP: Regexp
123
+ end
124
+
125
+ # Version 5 UUID validation patterns
126
+ #
127
+ # Provides regular expressions for validating name-based Version 5 UUIDs
128
+ # using SHA-1 hashing.
129
+ #
130
+ # @since 0.1.0
131
+ module V5
132
+ # Standard format regex for Version 5 UUIDs
133
+ # @return [Regexp] Pattern matching hyphenated Version 5 UUIDs
134
+ STANDARD_REGEXP: Regexp
135
+
136
+ # Compact format regex for Version 5 UUIDs
137
+ # @return [Regexp] Pattern matching non-hyphenated Version 5 UUIDs
138
+ COMPACT_REGEXP: Regexp
139
+ end
140
+
141
+ # Version 6 UUID validation patterns
142
+ #
143
+ # Provides regular expressions for validating ordered-time Version 6 UUIDs.
144
+ # These UUIDs are similar to Version 1 but with improved timestamp ordering.
145
+ #
146
+ # @since 0.1.0
147
+ module V6
148
+ # Standard format regex for Version 6 UUIDs
149
+ # @return [Regexp] Pattern matching hyphenated Version 6 UUIDs
150
+ STANDARD_REGEXP: Regexp
151
+
152
+ # Compact format regex for Version 6 UUIDs
153
+ # @return [Regexp] Pattern matching non-hyphenated Version 6 UUIDs
154
+ COMPACT_REGEXP: Regexp
155
+ end
156
+
157
+ # Version 7 UUID validation patterns
158
+ #
159
+ # Provides regular expressions for validating Unix Epoch time-based Version 7
160
+ # UUIDs. These UUIDs use millisecond precision timestamps.
161
+ #
162
+ # @since 0.1.0
163
+ module V7
164
+ # Standard format regex for Version 7 UUIDs
165
+ # @return [Regexp] Pattern matching hyphenated Version 7 UUIDs
166
+ STANDARD_REGEXP: Regexp
167
+
168
+ # Compact format regex for Version 7 UUIDs
169
+ # @return [Regexp] Pattern matching non-hyphenated Version 7 UUIDs
170
+ COMPACT_REGEXP: Regexp
171
+ end
172
+ end
173
+
174
+ # Constrain UUID to compact format
175
+ #
176
+ # Creates a constraint ensuring the UUID is in compact format (32 characters,
177
+ # no hyphens). Useful when working with systems that prefer compact UUIDs.
178
+ #
179
+ # @example
180
+ # type.being_compact
181
+ # type.validate("123e4567e89b12d3a456426614174000") # => true
182
+ # type.validate("123e4567-e89b-12d3-a456-426614174000") # => false
183
+ #
184
+ # @return [self] self for method chaining
185
+ def being_compact: () -> self
186
+
187
+ alias compact being_compact
188
+
189
+ # Constrain UUID to standard format
190
+ #
191
+ # Creates a constraint ensuring the UUID is in standard format (36 characters,
192
+ # with hyphens). This is the default format per RFC 4122.
193
+ #
194
+ # @example
195
+ # type.being_standard
196
+ # type.validate("123e4567-e89b-12d3-a456-426614174000") # => true
197
+ # type.validate("123e4567e89b12d3a456426614174000") # => false
198
+ #
199
+ # @return [self] self for method chaining
200
+ def being_standard: () -> self
201
+
202
+ alias standard being_standard
203
+
204
+ # Constrain UUID to specific version
205
+ #
206
+ # Creates a constraint ensuring the UUID matches a specific version (1-7) in
207
+ # either standard or compact format.
208
+ #
209
+ # @example
210
+ # type.being_version(4)
211
+ # type.validate("123e4567-e89b-42d3-a456-426614174000") # => true
212
+ # type.validate("123e4567-e89b-12d3-a456-426614174000") # => false
213
+ #
214
+ # @param version [Integer] UUID version (1-7)
215
+ # @param format [Symbol] :standard or :compact
216
+ # @return [self] self for method chaining
217
+ # @raise [ArgumentError] if format is neither :standard nor :compact
218
+ def being_version: (Integer version, ?format: :compact | :standard) -> self
219
+
220
+ # Constrain UUID to Version 5 compact format
221
+ #
222
+ # Creates a constraint ensuring the UUID is a Version 5 UUID in compact format.
223
+ # Version 5 UUIDs are name-based using SHA-1 hashing.
224
+ #
225
+ # @return [self] self for method chaining
226
+ def being_version_five_compact: () -> self
227
+
228
+ alias being_v5_compact being_version_five_compact
229
+
230
+ alias v5_compact being_version_five_compact
231
+
232
+ # Constrain UUID to Version 5 standard format
233
+ #
234
+ # Creates a constraint ensuring the UUID is a Version 5 UUID in standard format.
235
+ # Version 5 UUIDs are name-based using SHA-1 hashing.
236
+ #
237
+ # @example
238
+ # type.being_v5
239
+ # type.validate("123e4567-e89b-52d3-a456-426614174000") # => true
240
+ #
241
+ # @return [self] self for method chaining
242
+ def being_version_five_standard: () -> self
243
+
244
+ alias being_v5 being_version_five_standard
245
+
246
+ alias being_v5_standard being_version_five_standard
247
+
248
+ alias being_version_five being_version_five_standard
249
+
250
+ alias v5 being_version_five_standard
251
+
252
+ # Constrain UUID to Version 4 compact format
253
+ #
254
+ # Creates a constraint ensuring the UUID is a Version 4 UUID in compact format.
255
+ # Version 4 UUIDs are randomly generated and are the most commonly used format.
256
+ #
257
+ # @example
258
+ # type.being_v4_compact
259
+ # type.validate("123e4567e89b42d3a456426614174000") # => true
260
+ #
261
+ # @return [self] self for method chaining
262
+ def being_version_four_compact: () -> self
263
+
264
+ alias being_v4_compact being_version_four_compact
265
+
266
+ alias v4_compact being_version_four_compact
267
+
268
+ # Constrain UUID to Version 4 standard format
269
+ #
270
+ # Creates a constraint ensuring the UUID is a Version 4 UUID in standard format.
271
+ # Version 4 UUIDs are randomly generated and are the most commonly used format.
272
+ #
273
+ # @example
274
+ # type.being_v4
275
+ # type.validate("123e4567-e89b-42d3-a456-426614174000") # => true
276
+ #
277
+ # @return [self] self for method chaining
278
+ def being_version_four_standard: () -> self
279
+
280
+ alias being_v4 being_version_four_standard
281
+
282
+ alias being_v4_standard being_version_four_standard
283
+
284
+ alias being_version_four being_version_four_standard
285
+
286
+ alias v4 being_version_four_standard
287
+
288
+ # Constrain UUID to Version 1 compact format
289
+ #
290
+ # Creates a constraint ensuring the UUID is a Version 1 UUID in compact format.
291
+ # Version 1 UUIDs are time-based using a timestamp and node ID.
292
+ #
293
+ # @example
294
+ # type.being_v1_compact
295
+ # type.validate("123e4567e89b12d3a456426614174000") # => true
296
+ #
297
+ # @return [self] self for method chaining
298
+ def being_version_one_compact: () -> self
299
+
300
+ alias being_v1_compact being_version_one_compact
301
+
302
+ alias v1_compact being_version_one_compact
303
+
304
+ # Constrain UUID to Version 1 standard format
305
+ #
306
+ # Creates a constraint ensuring the UUID is a Version 1 UUID in standard format.
307
+ # Version 1 UUIDs are time-based using a timestamp and node ID.
308
+ #
309
+ # @example
310
+ # type.being_v1
311
+ # type.validate("123e4567-e89b-12d3-a456-426614174000") # => true
312
+ #
313
+ # @return [self] self for method chaining
314
+ def being_version_one_standard: () -> self
315
+
316
+ alias being_v1 being_version_one_standard
317
+
318
+ alias being_v1_standard being_version_one_standard
319
+
320
+ alias being_version_one being_version_one_standard
321
+
322
+ alias v1 being_version_one_standard
323
+
324
+ # Constrain UUID to Version 7 compact format
325
+ #
326
+ # Creates a constraint ensuring the UUID is a Version 7 UUID in compact format.
327
+ # Version 7 UUIDs use Unix Epoch timestamps with millisecond precision.
328
+ #
329
+ # @example
330
+ # type.being_v7_compact
331
+ # type.validate("123e4567e89b72d3a456426614174000") # => true
332
+ #
333
+ # @return [self] self for method chaining
334
+ def being_version_seven_compact: () -> self
335
+
336
+ alias being_v7_compact being_version_seven_compact
337
+
338
+ alias v7_compact being_version_seven_compact
339
+
340
+ # Constrain UUID to Version 7 standard format
341
+ #
342
+ # Creates a constraint ensuring the UUID is a Version 7 UUID in standard format.
343
+ # Version 7 UUIDs use Unix Epoch timestamps with millisecond precision.
344
+ #
345
+ # @example
346
+ # type.being_v7
347
+ # type.validate("123e4567-e89b-72d3-a456-426614174000") # => true
348
+ #
349
+ # @return [self] self for method chaining
350
+ def being_version_seven_standard: () -> self
351
+
352
+ alias being_v7 being_version_seven_standard
353
+
354
+ alias being_v7_standard being_version_seven_standard
355
+
356
+ alias being_version_seven being_version_seven_standard
357
+
358
+ alias v7 being_version_seven_standard
359
+
360
+ # Constrain UUID to Version 6 compact format
361
+ #
362
+ # Creates a constraint ensuring the UUID is a Version 6 UUID in compact format.
363
+ # Version 6 UUIDs are similar to Version 1 but with improved timestamp ordering.
364
+ #
365
+ # @example
366
+ # type.being_v6_compact
367
+ # type.validate("123e4567e89b62d3a456426614174000") # => true
368
+ #
369
+ # @return [self] self for method chaining
370
+ def being_version_six_compact: () -> self
371
+
372
+ alias being_v6_compact being_version_six_compact
373
+
374
+ alias v6_compact being_version_six_compact
375
+
376
+ # Constrain UUID to Version 6 standard format
377
+ #
378
+ # Creates a constraint ensuring the UUID is a Version 6 UUID in standard format.
379
+ # Version 6 UUIDs are similar to Version 1 but with improved timestamp ordering.
380
+ #
381
+ # @example
382
+ # type.being_v6
383
+ # type.validate("123e4567-e89b-62d3-a456-426614174000") # => true
384
+ #
385
+ # @return [self] self for method chaining
386
+ def being_version_six_standard: () -> self
387
+
388
+ alias being_v6 being_version_six_standard
389
+
390
+ alias being_v6_standard being_version_six_standard
391
+
392
+ alias being_version_six being_version_six_standard
393
+
394
+ alias v6 being_version_six_standard
395
+
396
+ # Constrain UUID to Version 3 compact format
397
+ #
398
+ # Creates a constraint ensuring the UUID is a Version 3 UUID in compact format.
399
+ # Version 3 UUIDs are name-based using MD5 hashing.
400
+ #
401
+ # @example
402
+ # type.being_v3_compact
403
+ # type.validate("123e4567e89b32d3a456426614174000") # => true
404
+ #
405
+ # @return [self] self for method chaining
406
+ def being_version_three_compact: () -> self
407
+
408
+ alias being_v3_compact being_version_three_compact
409
+
410
+ alias v3_compact being_version_three_compact
411
+
412
+ # Constrain UUID to Version 3 standard format
413
+ #
414
+ # Creates a constraint ensuring the UUID is a Version 3 UUID in standard format.
415
+ # Version 3 UUIDs are name-based using MD5 hashing.
416
+ #
417
+ # @example
418
+ # type.being_v3
419
+ # type.validate("123e4567-e89b-32d3-a456-426614174000") # => true
420
+ #
421
+ # @return [self] self for method chaining
422
+ def being_version_three_standard: () -> self
423
+
424
+ alias being_v3 being_version_three_standard
425
+
426
+ alias being_v3_standard being_version_three_standard
427
+
428
+ alias being_version_three being_version_three_standard
429
+
430
+ alias v3 being_version_three_standard
431
+
432
+ # Constrain UUID to Version 2 compact format
433
+ #
434
+ # Creates a constraint ensuring the UUID is a Version 2 UUID in compact format.
435
+ # Version 2 UUIDs are DCE Security version that incorporate local domain identifiers.
436
+ #
437
+ # @example
438
+ # type.being_v2_compact
439
+ # type.validate("123e4567e89b22d3a456426614174000") # => true
440
+ #
441
+ # @return [self] self for method chaining
442
+ def being_version_two_compact: () -> self
443
+
444
+ alias being_v2_compact being_version_two_compact
445
+
446
+ alias v2_compact being_version_two_compact
447
+
448
+ # Constrain UUID to Version 2 standard format
449
+ #
450
+ # Creates a constraint ensuring the UUID is a Version 2 UUID in standard format.
451
+ # Version 2 UUIDs are DCE Security version that incorporate local domain identifiers.
452
+ #
453
+ # @example
454
+ # type.being_v2
455
+ # type.validate("123e4567-e89b-22d3-a456-426614174000") # => true
456
+ #
457
+ # @return [self] self for method chaining
458
+ def being_version_two_standard: () -> self
459
+
460
+ alias being_v2 being_version_two_standard
461
+
462
+ alias being_v2_standard being_version_two_standard
463
+
464
+ alias being_version_two being_version_two_standard
465
+
466
+ alias v2 being_version_two_standard
467
+ end
468
+ end
469
+ end
@@ -0,0 +1,127 @@
1
+ module Domainic
2
+ module Type
3
+ # A type for validating email addresses according to RFC standards
4
+ #
5
+ # This type provides comprehensive email address validation following RFC 5321 and 5322
6
+ # standards. It supports constraints on all email components (local part, hostname, TLD)
7
+ # while enforcing basic email requirements like maximum length and character set rules.
8
+ #
9
+ # Key features:
10
+ # - RFC compliant email format validation
11
+ # - Maximum length enforcement (254 characters)
12
+ # - ASCII character set requirement
13
+ # - Hostname and TLD validation
14
+ # - Local part pattern matching
15
+ #
16
+ # @example Basic usage
17
+ # type = EmailAddressType.new
18
+ # type.validate("user@example.com") # => true
19
+ # type.validate("invalid") # => false
20
+ #
21
+ # @example With domain constraints
22
+ # type = EmailAddressType.new
23
+ # .having_hostname("example.com", "company.com")
24
+ # .having_top_level_domain("com", "org")
25
+ #
26
+ # @example With local part validation
27
+ # type = EmailAddressType.new
28
+ # .having_local_matching(/^[a-z]+$/)
29
+ # .not_having_local_matching(/^admin/)
30
+ #
31
+ # @author {https://aaronmallen.me Aaron Allen}
32
+ # @since 0.1.0
33
+ class EmailAddressType
34
+ extend Behavior::ClassMethods
35
+
36
+ include Behavior
37
+
38
+ include Behavior::StringBehavior::MatchingBehavior
39
+
40
+ include Behavior::SizableBehavior
41
+
42
+ include Behavior::URIBehavior
43
+
44
+ # Constrain email to allowed hostnames
45
+ #
46
+ # Creates a constraint ensuring the domain part of the email matches one of the
47
+ # specified hostnames. This is useful for restricting emails to specific domains.
48
+ #
49
+ # @example
50
+ # type.having_hostname("example.com", "company.com")
51
+ # type.validate("user@example.com") # => true
52
+ # type.validate("user@other.com") # => false
53
+ #
54
+ # @param hostnames [Array<String>] List of allowed hostnames
55
+ # @return [self] self for method chaining
56
+ def having_hostname: (*String hostnames) -> self
57
+
58
+ alias allowing_host having_hostname
59
+
60
+ alias allowing_hostname having_hostname
61
+
62
+ alias host having_hostname
63
+
64
+ alias hostname having_hostname
65
+
66
+ alias with_host having_hostname
67
+
68
+ alias with_hostname having_hostname
69
+
70
+ # Constrain email local part to match pattern
71
+ #
72
+ # Creates a constraint requiring the local part (before @) to match the given pattern.
73
+ # Useful for enforcing username conventions or restrictions.
74
+ #
75
+ # @example
76
+ # type.having_local_matching(/^[a-z]+$/)
77
+ # type.validate("user@example.com") # => true
78
+ # type.validate("123@example.com") # => false
79
+ #
80
+ # @param pattern [Regexp] Pattern the local part must match
81
+ # @return [self] self for method chaining
82
+ def having_local_matching: (String | Regexp pattern) -> self
83
+
84
+ alias matching_local having_local_matching
85
+
86
+ alias with_local_matching having_local_matching
87
+
88
+ # Constrain email to exclude specific hostnames
89
+ #
90
+ # Creates a constraint ensuring the domain part of the email does not match any
91
+ # of the specified hostnames. Useful for blacklisting certain domains.
92
+ #
93
+ # @example
94
+ # type.not_having_hostname("example.com")
95
+ # type.validate("user@company.com") # => true
96
+ # type.validate("user@example.com") # => false
97
+ #
98
+ # @param hostnames [Array<String>] List of forbidden hostnames
99
+ # @return [self] self for method chaining
100
+ def not_having_hostname: (*String hostnames) -> self
101
+
102
+ alias forbidding_host not_having_hostname
103
+
104
+ alias forbidding_hostname not_having_hostname
105
+
106
+ alias not_host not_having_hostname
107
+
108
+ alias not_hostname not_having_hostname
109
+
110
+ # Constrain email local part to not match pattern
111
+ #
112
+ # Creates a constraint ensuring the local part (before @) does not match the given
113
+ # pattern. Useful for preventing certain username patterns.
114
+ #
115
+ # @example
116
+ # type.not_having_local_matching(/^admin/)
117
+ # type.validate("user@example.com") # => true
118
+ # type.validate("admin@example.com") # => false
119
+ #
120
+ # @param pattern [Regexp] Pattern the local part must not match
121
+ # @return [self] self for method chaining
122
+ def not_having_local_matching: (String | Regexp pattern) -> self
123
+
124
+ alias not_matching_local not_having_local_matching
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,76 @@
1
+ module Domainic
2
+ module Type
3
+ # A type for validating hostnames according to RFC 1034 and RFC 1123 standards
4
+ #
5
+ # This type provides comprehensive hostname validation, ensuring that values conform to
6
+ # DNS standards for hostnames. It supports constraints on the domain structure, such as
7
+ # top-level domain validation and hostname pattern matching.
8
+ #
9
+ # Key features:
10
+ # - RFC-compliant hostname validation
11
+ # - Maximum length enforcement (253 characters)
12
+ # - ASCII character set requirement
13
+ # - Validation of allowed or disallowed hostnames and TLDs
14
+ #
15
+ # @example Basic usage
16
+ # type = HostNameType.new
17
+ # type.validate("example.com") # => true
18
+ # type.validate("invalid_host") # => false
19
+ #
20
+ # @example With domain constraints
21
+ # type = HostNameType.new
22
+ # .having_top_level_domain("com", "org")
23
+ #
24
+ # @example With hostname inclusion/exclusion
25
+ # type = HostNameType.new
26
+ # .having_hostname("example.com")
27
+ # .not_having_hostname("forbidden.com")
28
+ #
29
+ # @author {https://aaronmallen.me Aaron Allen}
30
+ # @since 0.1.0
31
+ class HostnameType
32
+ extend Behavior::ClassMethods
33
+
34
+ include Behavior
35
+
36
+ include Behavior::StringBehavior::MatchingBehavior
37
+
38
+ include Behavior::SizableBehavior
39
+
40
+ include Behavior::URIBehavior
41
+
42
+ RFC_HOSTNAME_REGEXP: Regexp
43
+
44
+ # Constrain hostname to allowed hostnames
45
+ #
46
+ # Creates a constraint ensuring the hostname matches one of the specified hostnames.
47
+ # This is useful for restricting to specific domains.
48
+ #
49
+ # @example
50
+ # type.having_hostname("example.com", "company.com")
51
+ # type.validate("example.com") # => true
52
+ # type.validate("other.com") # => false
53
+ #
54
+ # @param hostnames [Array<String>] List of allowed hostnames
55
+ # @return [self] self for method chaining
56
+ def matching: (*String hostnames) -> self
57
+
58
+ alias allowing matching
59
+
60
+ # Constrain hostname to exclude specific hostnames
61
+ #
62
+ # Ensures the hostname does not match any of the specified hostnames. Useful for blacklisting.
63
+ #
64
+ # @example
65
+ # type.not_having_hostname("forbidden.com")
66
+ # type.validate("allowed.com") # => true
67
+ # type.validate("forbidden.com") # => false
68
+ #
69
+ # @param hostnames [Array<String>] List of forbidden hostnames
70
+ # @return [self] self for method chaining
71
+ def not_matching: (*String hostnames) -> self
72
+
73
+ alias forbidding not_matching
74
+ end
75
+ end
76
+ end