treaty 0.0.1 → 0.2.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.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +106 -17
  3. data/Rakefile +4 -2
  4. data/config/locales/en.yml +96 -0
  5. data/lib/treaty/attribute/base.rb +174 -0
  6. data/lib/treaty/attribute/builder/base.rb +143 -0
  7. data/lib/treaty/attribute/collection.rb +65 -0
  8. data/lib/treaty/attribute/helper_mapper.rb +72 -0
  9. data/lib/treaty/attribute/option/base.rb +160 -0
  10. data/lib/treaty/attribute/option/modifiers/as_modifier.rb +88 -0
  11. data/lib/treaty/attribute/option/modifiers/default_modifier.rb +103 -0
  12. data/lib/treaty/attribute/option/registry.rb +128 -0
  13. data/lib/treaty/attribute/option/registry_initializer.rb +90 -0
  14. data/lib/treaty/attribute/option/validators/inclusion_validator.rb +80 -0
  15. data/lib/treaty/attribute/option/validators/required_validator.rb +92 -0
  16. data/lib/treaty/attribute/option/validators/type_validator.rb +159 -0
  17. data/lib/treaty/attribute/option_normalizer.rb +151 -0
  18. data/lib/treaty/attribute/option_orchestrator.rb +187 -0
  19. data/lib/treaty/attribute/validation/attribute_validator.rb +144 -0
  20. data/lib/treaty/attribute/validation/base.rb +92 -0
  21. data/lib/treaty/attribute/validation/nested_array_validator.rb +199 -0
  22. data/lib/treaty/attribute/validation/nested_object_validator.rb +103 -0
  23. data/lib/treaty/attribute/validation/nested_transformer.rb +246 -0
  24. data/lib/treaty/attribute/validation/orchestrator/base.rb +194 -0
  25. data/lib/treaty/base.rb +9 -0
  26. data/lib/treaty/configuration.rb +17 -0
  27. data/lib/treaty/context/callable.rb +24 -0
  28. data/lib/treaty/context/dsl.rb +12 -0
  29. data/lib/treaty/context/workspace.rb +28 -0
  30. data/lib/treaty/controller/dsl.rb +38 -0
  31. data/lib/treaty/engine.rb +37 -0
  32. data/lib/treaty/exceptions/base.rb +47 -0
  33. data/lib/treaty/exceptions/class_name.rb +50 -0
  34. data/lib/treaty/exceptions/deprecated.rb +54 -0
  35. data/lib/treaty/exceptions/execution.rb +66 -0
  36. data/lib/treaty/exceptions/method_name.rb +55 -0
  37. data/lib/treaty/exceptions/nested_attributes.rb +65 -0
  38. data/lib/treaty/exceptions/not_implemented.rb +32 -0
  39. data/lib/treaty/exceptions/strategy.rb +63 -0
  40. data/lib/treaty/exceptions/unexpected.rb +70 -0
  41. data/lib/treaty/exceptions/validation.rb +97 -0
  42. data/lib/treaty/info/builder.rb +122 -0
  43. data/lib/treaty/info/dsl.rb +26 -0
  44. data/lib/treaty/info/result.rb +13 -0
  45. data/lib/treaty/request/attribute/attribute.rb +24 -0
  46. data/lib/treaty/request/attribute/builder.rb +22 -0
  47. data/lib/treaty/request/attribute/validation/orchestrator.rb +27 -0
  48. data/lib/treaty/request/attribute/validator.rb +50 -0
  49. data/lib/treaty/request/factory.rb +32 -0
  50. data/lib/treaty/request/scope/collection.rb +21 -0
  51. data/lib/treaty/request/scope/factory.rb +42 -0
  52. data/lib/treaty/response/attribute/attribute.rb +24 -0
  53. data/lib/treaty/response/attribute/builder.rb +22 -0
  54. data/lib/treaty/response/attribute/validation/orchestrator.rb +27 -0
  55. data/lib/treaty/response/attribute/validator.rb +44 -0
  56. data/lib/treaty/response/factory.rb +38 -0
  57. data/lib/treaty/response/scope/collection.rb +21 -0
  58. data/lib/treaty/response/scope/factory.rb +42 -0
  59. data/lib/treaty/result.rb +22 -0
  60. data/lib/treaty/strategy.rb +31 -0
  61. data/lib/treaty/support/loader.rb +24 -0
  62. data/lib/treaty/version.rb +8 -1
  63. data/lib/treaty/versions/collection.rb +15 -0
  64. data/lib/treaty/versions/dsl.rb +30 -0
  65. data/lib/treaty/versions/execution/request.rb +147 -0
  66. data/lib/treaty/versions/executor.rb +14 -0
  67. data/lib/treaty/versions/factory.rb +92 -0
  68. data/lib/treaty/versions/resolver.rb +69 -0
  69. data/lib/treaty/versions/semantic.rb +22 -0
  70. data/lib/treaty/versions/workspace.rb +40 -0
  71. data/lib/treaty.rb +3 -3
  72. metadata +200 -27
  73. data/.standard.yml +0 -3
  74. data/CHANGELOG.md +0 -5
  75. data/CODE_OF_CONDUCT.md +0 -84
  76. data/LICENSE.txt +0 -21
  77. data/sig/treaty.rbs +0 -4
  78. data/treaty.gemspec +0 -35
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Treaty
4
+ module Attribute
5
+ # Maps DSL helper symbols to their simple mode option equivalents.
6
+ #
7
+ # ## Purpose
8
+ #
9
+ # Helpers provide the most concise syntax for common options.
10
+ # They are syntactic sugar that gets converted to simple mode options.
11
+ #
12
+ # ## Available Helpers
13
+ #
14
+ # - `:required` → `required: true`
15
+ # - `:optional` → `required: false`
16
+ #
17
+ # ## Usage Examples
18
+ #
19
+ # Helper mode (most concise):
20
+ # string :title, :required
21
+ # string :bio, :optional
22
+ #
23
+ # Equivalent to simple mode:
24
+ # string :title, required: true
25
+ # string :bio, required: false
26
+ #
27
+ # ## Processing Flow
28
+ #
29
+ # 1. Helper mode: `string :title, :required`
30
+ # 2. HelperMapper: `:required` → `required: true`
31
+ # 3. OptionNormalizer: `required: true` → `{ is: true, message: nil }`
32
+ # 4. Final: Advanced mode used internally
33
+ #
34
+ # ## Adding New Helpers
35
+ #
36
+ # To add a new helper:
37
+ # ```ruby
38
+ # HELPER_MAPPINGS = {
39
+ # required: { required: true },
40
+ # optional: { required: false },
41
+ # my_helper: { my_option: :smth } # New helper example
42
+ # }.freeze
43
+ # ```
44
+ class HelperMapper
45
+ HELPER_MAPPINGS = {
46
+ required: { required: true },
47
+ optional: { required: false }
48
+ }.freeze
49
+
50
+ class << self
51
+ # Maps helper symbols to their simple mode equivalents
52
+ #
53
+ # @param helpers [Array<Symbol>] Array of helper symbols
54
+ # @return [Hash] Simple mode options hash
55
+ def map(helpers)
56
+ helpers.each_with_object({}) do |helper, result|
57
+ mapping = HELPER_MAPPINGS.fetch(helper)
58
+ result.merge!(mapping) if mapping.present?
59
+ end
60
+ end
61
+
62
+ # Checks if a symbol is a registered helper
63
+ #
64
+ # @param symbol [Symbol] Symbol to check
65
+ # @return [Boolean] True if symbol is a helper
66
+ def helper?(symbol)
67
+ HELPER_MAPPINGS.key?(symbol)
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,160 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Treaty
4
+ module Attribute
5
+ module Option
6
+ # Base class for all option processors (validators and modifiers).
7
+ #
8
+ # ## Option Modes
9
+ #
10
+ # Treaty supports two modes for defining options:
11
+ #
12
+ # 1. **Simple Mode** - Concise syntax for common cases:
13
+ # - `required: true`
14
+ # - `as: :value`
15
+ # - `default: 12`
16
+ # - `in: %w[twitter linkedin]`
17
+ #
18
+ # 2. **Advanced Mode** - Extended syntax with custom messages:
19
+ # - `required: { is: true, message: "Custom error" }`
20
+ # - `as: { is: :value, message: nil }`
21
+ # - `inclusion: { in: %w[...], message: "Must be one of..." }`
22
+ #
23
+ # ## Helpers
24
+ #
25
+ # Helpers are shortcuts in DSL that map to simple mode options:
26
+ # - `:required` → `required: true`
27
+ # - `:optional` → `required: false`
28
+ #
29
+ # ## Advanced Mode Keys
30
+ #
31
+ # Each option in advanced mode has a value key:
32
+ # - Default key: `:is` (used by most options)
33
+ # - Special key: `:in` (used by inclusion validator)
34
+ #
35
+ # The value key is defined by overriding `value_key` method in subclasses.
36
+ #
37
+ # ## Processing Phases
38
+ #
39
+ # Each option processor can participate in three phases:
40
+ # - Phase 1: Schema validation (validate DSL definition correctness)
41
+ # - Phase 2: Value validation (validate runtime data values)
42
+ # - Phase 3: Value transformation (transform values: defaults, renaming, etc.)
43
+ class Base
44
+ # Creates a new option processor instance
45
+ #
46
+ # @param attribute_name [Symbol] The name of the attribute
47
+ # @param attribute_type [Symbol] The type of the attribute
48
+ # @param option_schema [Object] The option schema (simple or advanced mode)
49
+ def initialize(attribute_name:, attribute_type:, option_schema:)
50
+ @attribute_name = attribute_name
51
+ @attribute_type = attribute_type
52
+ @option_schema = option_schema
53
+ end
54
+
55
+ # Phase 1: Validates schema (DSL definition)
56
+ # Override in subclasses if validation is needed
57
+ #
58
+ # @raise [Treaty::Exceptions::Validation] If schema is invalid
59
+ # @return [void]
60
+ def validate_schema!
61
+ # No-op by default
62
+ end
63
+
64
+ # Phase 2: Validates value (runtime data)
65
+ # Override in subclasses if validation is needed
66
+ #
67
+ # @param value [Object] The value to validate
68
+ # @raise [Treaty::Exceptions::Validation] If value is invalid
69
+ # @return [void]
70
+ def validate_value!(value)
71
+ # No-op by default
72
+ end
73
+
74
+ # Phase 3: Transforms value
75
+ # Returns transformed value or original if no transformation needed
76
+ # Override in subclasses if transformation is needed
77
+ #
78
+ # @param value [Object] The value to transform
79
+ # @return [Object] Transformed value
80
+ def transform_value(value)
81
+ value
82
+ end
83
+
84
+ # Indicates if this option processor transforms attribute names
85
+ # Override in subclasses if needed (e.g., AsModifier)
86
+ #
87
+ # @return [Boolean] True if this processor transforms names
88
+ def transforms_name?
89
+ false
90
+ end
91
+
92
+ # Returns the target name for the attribute if this processor transforms names
93
+ # Override in subclasses if needed (e.g., AsModifier)
94
+ #
95
+ # @return [Symbol] The target attribute name
96
+ def target_name
97
+ @attribute_name
98
+ end
99
+
100
+ protected
101
+
102
+ # Returns the value key for this option in advanced mode
103
+ # Default is :is, but can be overridden (e.g., :in for inclusion)
104
+ #
105
+ # @return [Symbol] The key used to store the value in advanced mode
106
+ def value_key
107
+ :is
108
+ end
109
+
110
+ # Checks if option is enabled
111
+ # Handles both simple mode (boolean) and advanced mode (hash with value key)
112
+ #
113
+ # @return [Boolean] Whether the option is enabled
114
+ def option_enabled?
115
+ return false if @option_schema.nil?
116
+ return @option_schema if @option_schema.is_a?(TrueClass) || @option_schema.is_a?(FalseClass)
117
+
118
+ @option_schema.fetch(value_key, false)
119
+ end
120
+
121
+ # Extracts the actual value from normalized schema
122
+ # Works with both simple mode and advanced mode
123
+ #
124
+ # In simple mode: returns the value directly
125
+ # In advanced mode: extracts value using the appropriate key (is/in)
126
+ #
127
+ # @return [Object] The actual value from the option schema
128
+ def option_value
129
+ return @option_schema unless @option_schema.is_a?(Hash)
130
+
131
+ @option_schema.fetch(value_key, nil)
132
+ end
133
+
134
+ # Gets custom error message from advanced mode schema
135
+ # Returns nil if no custom message, which triggers I18n default message
136
+ #
137
+ # @return [String, nil] Custom error message or nil for default message
138
+ def custom_message
139
+ return nil unless @option_schema.is_a?(Hash)
140
+
141
+ @option_schema.fetch(:message, nil)
142
+ end
143
+
144
+ # Checks if schema is in advanced mode
145
+ #
146
+ # @return [Boolean] True if schema is in advanced mode (hash with value key)
147
+ def advanced_mode?
148
+ @option_schema.is_a?(Hash) && @option_schema.key?(value_key)
149
+ end
150
+
151
+ # Checks if schema is in simple mode
152
+ #
153
+ # @return [Boolean] True if schema is in simple mode (not a hash or no value key)
154
+ def simple_mode?
155
+ !advanced_mode?
156
+ end
157
+ end
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Treaty
4
+ module Attribute
5
+ module Option
6
+ module Modifiers
7
+ # Transforms attribute names during data processing.
8
+ #
9
+ # ## Usage Examples
10
+ #
11
+ # Simple mode:
12
+ # # Request: expects "handle", outputs as "value"
13
+ # string :handle, as: :value
14
+ #
15
+ # Advanced mode:
16
+ # string :handle, as: { is: :value, message: nil }
17
+ #
18
+ # ## Use Cases
19
+ #
20
+ # 1. **Request to Service mapping**:
21
+ # ```ruby
22
+ # request do
23
+ # string :user_id, as: :id
24
+ # end
25
+ # # Input: { user_id: "123" }
26
+ # # Service receives: { id: "123" }
27
+ # ```
28
+ #
29
+ # 2. **Service to Response mapping**:
30
+ # ```ruby
31
+ # response 200 do
32
+ # string :id, as: :user_id
33
+ # end
34
+ # # Service returns: { id: "123" }
35
+ # # Output: { user_id: "123" }
36
+ # ```
37
+ #
38
+ # ## How It Works
39
+ #
40
+ # AsModifier doesn't transform values - it transforms attribute names.
41
+ # The orchestrator uses `target_name` to map source name to target name.
42
+ #
43
+ # ## Advanced Mode
44
+ #
45
+ # Schema format: `{ is: :symbol, message: nil }`
46
+ class AsModifier < Treaty::Attribute::Option::Base
47
+ # Validates that target name is a Symbol
48
+ #
49
+ # @raise [Treaty::Exceptions::Validation] If target is not a Symbol
50
+ # @return [void]
51
+ def validate_schema!
52
+ target = option_value
53
+
54
+ return if target.is_a?(Symbol)
55
+
56
+ raise Treaty::Exceptions::Validation,
57
+ I18n.t("treaty.attributes.modifiers.as.invalid_type",
58
+ attribute: @attribute_name,
59
+ type: target.class)
60
+ end
61
+
62
+ # Indicates that AsModifier transforms attribute names
63
+ #
64
+ # @return [Boolean] Always returns true
65
+ def transforms_name?
66
+ true
67
+ end
68
+
69
+ # Returns the target name for the attribute
70
+ #
71
+ # @return [Symbol] The target attribute name
72
+ def target_name
73
+ option_value
74
+ end
75
+
76
+ # AsModifier doesn't modify the value itself, only the name
77
+ # The renaming is handled by the orchestrator using target_name
78
+ #
79
+ # @param value [Object] The value to transform
80
+ # @return [Object] Unchanged value
81
+ def transform_value(value)
82
+ value
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Treaty
4
+ module Attribute
5
+ module Option
6
+ module Modifiers
7
+ # Sets default values for attributes when value is nil.
8
+ #
9
+ # ## Usage Examples
10
+ #
11
+ # Simple mode with static value:
12
+ # integer :limit, default: 12
13
+ # string :status, default: "pending"
14
+ # boolean :active, default: false
15
+ #
16
+ # Simple mode with dynamic value (Proc):
17
+ # datetime :created_at, default: -> { Time.current }
18
+ # string :uuid, default: -> { SecureRandom.uuid }
19
+ #
20
+ # Advanced mode:
21
+ # integer :limit, default: { is: 12, message: nil }
22
+ #
23
+ # ## Use Cases
24
+ #
25
+ # 1. **Response defaults** (most common):
26
+ # ```ruby
27
+ # response 200 do
28
+ # scope :meta do
29
+ # integer :limit, default: 12
30
+ # integer :page, default: 1
31
+ # end
32
+ # end
33
+ # # Service returns: { meta: { page: 1 } }
34
+ # # Output: { meta: { page: 1, limit: 12 } }
35
+ # ```
36
+ #
37
+ # 2. **Request defaults**:
38
+ # ```ruby
39
+ # request do
40
+ # string :format, default: "json"
41
+ # end
42
+ # # Input: {}
43
+ # # Service receives: { format: "json" }
44
+ # ```
45
+ #
46
+ # ## Important Notes
47
+ #
48
+ # - Default is applied ONLY when value is nil
49
+ # - Empty strings, empty arrays, false are NOT replaced
50
+ # - Proc defaults are called at transformation time
51
+ # - Procs receive no arguments
52
+ #
53
+ # ## Array and Object Types
54
+ #
55
+ # NOTE: DO NOT use `default: []` or `default: {}` for array/object types!
56
+ # Array and object types automatically represent empty collections.
57
+ #
58
+ # Incorrect:
59
+ # array :tags, default: [] # Wrong! Redundant
60
+ # object :meta, default: {} # Wrong! Redundant
61
+ #
62
+ # Correct:
63
+ # array :tags # Automatically handles empty array
64
+ # object :meta # Automatically handles empty object
65
+ #
66
+ # ## Advanced Mode
67
+ #
68
+ # Schema format: `{ is: value_or_proc, message: nil }`
69
+ class DefaultModifier < Treaty::Attribute::Option::Base
70
+ # Validates schema (no validation needed)
71
+ # Default value can be any type
72
+ #
73
+ # @return [void]
74
+ def validate_schema!
75
+ # Schema structure is already normalized by OptionNormalizer.
76
+ # Default value can be any type, so nothing specific to validate here.
77
+ end
78
+
79
+ # Applies default value if current value is nil
80
+ # Empty strings, empty arrays, and false are NOT replaced
81
+ #
82
+ # @param value [Object] The current value
83
+ # @param _context [Hash] Unused context parameter
84
+ # @return [Object] Default value if original is nil, otherwise original value
85
+ def transform_value(value, _context = {})
86
+ # Only apply default if value is nil
87
+ # Empty strings, empty arrays, false are NOT replaced
88
+ return value unless value.nil?
89
+
90
+ default_value = option_value
91
+
92
+ # If default value is a Proc, call it to get the value
93
+ if default_value.is_a?(Proc)
94
+ default_value.call
95
+ else
96
+ default_value
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,128 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Treaty
4
+ module Attribute
5
+ module Option
6
+ # Central registry for all option processors (validators and modifiers).
7
+ #
8
+ # ## Purpose
9
+ #
10
+ # Provides a centralized registry pattern for managing all option processors.
11
+ # Enables dynamic discovery and extensibility of the option system.
12
+ #
13
+ # ## Responsibilities
14
+ #
15
+ # 1. **Registration** - Stores option processor classes
16
+ # 2. **Retrieval** - Provides access to registered processors
17
+ # 3. **Categorization** - Organizes processors by category (validator/modifier)
18
+ # 4. **Validation** - Checks if options are registered
19
+ #
20
+ # ## Registered Options
21
+ #
22
+ # ### Validators
23
+ # - `:required` → RequiredValidator
24
+ # - `:type` → TypeValidator
25
+ # - `:inclusion` → InclusionValidator
26
+ #
27
+ # ### Modifiers
28
+ # - `:as` → AsModifier
29
+ # - `:default` → DefaultModifier
30
+ #
31
+ # ## Usage
32
+ #
33
+ # Registration (done in RegistryInitializer):
34
+ # Registry.register(:required, RequiredValidator, category: :validator)
35
+ #
36
+ # Retrieval (done in OptionOrchestrator):
37
+ # processor_class = Registry.processor_for(:required)
38
+ # processor = processor_class.new(...)
39
+ #
40
+ # ## Extensibility
41
+ #
42
+ # To add a new option:
43
+ # 1. Create processor class inheriting from Option::Base
44
+ # 2. Register it: `Registry.register(:my_option, MyProcessor, category: :validator)`
45
+ # 3. Option becomes available in DSL immediately
46
+ #
47
+ # ## Architecture
48
+ #
49
+ # Works with:
50
+ # - RegistryInitializer - Populates registry with built-in options
51
+ # - OptionOrchestrator - Uses registry to build processors
52
+ # - Option::Base - Base class for all registered processors
53
+ class Registry
54
+ class << self
55
+ # Register an option processor
56
+ #
57
+ # @param option_name [Symbol] The name of the option (e.g., :required, :as, :default)
58
+ # @param processor_class [Class] The processor class
59
+ # @param category [Symbol] The category (:validator or :modifier)
60
+ def register(option_name, processor_class, category:)
61
+ registry[option_name] = {
62
+ processor_class:,
63
+ category:
64
+ }
65
+ end
66
+
67
+ # Get processor class for an option
68
+ #
69
+ # @param option_name [Symbol] The name of the option
70
+ # @return [Class, nil] The processor class or nil if not found
71
+ def processor_for(option_name)
72
+ registry.dig(option_name, :processor_class)
73
+ end
74
+
75
+ # Get category for an option
76
+ #
77
+ # @param option_name [Symbol] The name of the option
78
+ # @return [Symbol, nil] The category (:validator or :modifier) or nil if not found
79
+ def category_for(option_name)
80
+ registry.dig(option_name, :category)
81
+ end
82
+
83
+ # Check if an option is registered
84
+ #
85
+ # @param option_name [Symbol] The name of the option
86
+ # @return [Boolean]
87
+ def registered?(option_name)
88
+ registry.key?(option_name)
89
+ end
90
+
91
+ # Get all registered option names
92
+ #
93
+ # @return [Array<Symbol>]
94
+ def all_options
95
+ registry.keys
96
+ end
97
+
98
+ # Get all validators
99
+ #
100
+ # @return [Hash] Hash of option_name => processor_class for validators
101
+ def validators
102
+ registry.select { |_, info| info[:category] == :validator }
103
+ .transform_values { |info| info[:processor_class] }
104
+ end
105
+
106
+ # Get all modifiers
107
+ #
108
+ # @return [Hash] Hash of option_name => processor_class for modifiers
109
+ def modifiers
110
+ registry.select { |_, info| info[:category] == :modifier }
111
+ .transform_values { |info| info[:processor_class] }
112
+ end
113
+
114
+ # Reset registry (mainly for testing)
115
+ def reset!
116
+ @registry = nil
117
+ end
118
+
119
+ private
120
+
121
+ def registry
122
+ @registry ||= {}
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Treaty
4
+ module Attribute
5
+ module Option
6
+ # Initializes and registers all built-in option processors with the Registry.
7
+ #
8
+ # ## Purpose
9
+ #
10
+ # Centralized registration point for all option processors (validators and modifiers).
11
+ # Automatically registers all built-in options when loaded.
12
+ #
13
+ # ## Responsibilities
14
+ #
15
+ # 1. **Validator Registration** - Registers all built-in validators
16
+ # 2. **Modifier Registration** - Registers all built-in modifiers
17
+ # 3. **Auto-Loading** - Executes automatically when file is loaded
18
+ #
19
+ # ## Built-in Validators
20
+ #
21
+ # - `:required` → RequiredValidator - Validates required/optional attributes
22
+ # - `:type` → TypeValidator - Validates value types
23
+ # - `:inclusion` → InclusionValidator - Validates value is in allowed set
24
+ #
25
+ # ## Built-in Modifiers
26
+ #
27
+ # - `:as` → AsModifier - Renames attributes
28
+ # - `:default` → DefaultModifier - Provides default values
29
+ #
30
+ # ## Auto-Registration
31
+ #
32
+ # This file calls `register_all!` when loaded, ensuring all processors
33
+ # are available immediately.
34
+ #
35
+ # ## Adding New Options
36
+ #
37
+ # To add a new option processor:
38
+ #
39
+ # 1. Create the processor class (inherit from Option::Base)
40
+ # 2. Add registration call here:
41
+ # ```ruby
42
+ # def register_validators!
43
+ # Registry.register(:required, Validators::RequiredValidator, category: :validator)
44
+ # Registry.register(:my_option, Validators::MyValidator, category: :validator)
45
+ # end
46
+ # ```
47
+ #
48
+ # ## Architecture
49
+ #
50
+ # Works with:
51
+ # - Registry - Stores processor registrations
52
+ # - Option::Base - Base class for all processors
53
+ # - OptionOrchestrator - Uses registered processors
54
+ module RegistryInitializer
55
+ class << self
56
+ # Registers all built-in option processors
57
+ # Called automatically when this file is loaded
58
+ #
59
+ # @return [void]
60
+ def register_all!
61
+ register_validators!
62
+ register_modifiers!
63
+ end
64
+
65
+ private
66
+
67
+ # Registers all built-in validators
68
+ #
69
+ # @return [void]
70
+ def register_validators!
71
+ Registry.register(:required, Validators::RequiredValidator, category: :validator)
72
+ Registry.register(:type, Validators::TypeValidator, category: :validator)
73
+ Registry.register(:inclusion, Validators::InclusionValidator, category: :validator)
74
+ end
75
+
76
+ # Registers all built-in modifiers
77
+ #
78
+ # @return [void]
79
+ def register_modifiers!
80
+ Registry.register(:as, Modifiers::AsModifier, category: :modifier)
81
+ Registry.register(:default, Modifiers::DefaultModifier, category: :modifier)
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+
89
+ # Auto-register all options when this file is loaded
90
+ Treaty::Attribute::Option::RegistryInitializer.register_all!