cmdx 1.9.0 → 1.9.1

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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/.cursor/prompts/yardoc.md +1 -0
  3. data/CHANGELOG.md +6 -0
  4. data/LLM.md +9 -0
  5. data/README.md +6 -1
  6. data/docs/getting_started.md +9 -0
  7. data/docs/index.md +13 -1
  8. data/lib/cmdx/attribute.rb +82 -1
  9. data/lib/cmdx/attribute_registry.rb +20 -0
  10. data/lib/cmdx/attribute_value.rb +25 -0
  11. data/lib/cmdx/callback_registry.rb +19 -0
  12. data/lib/cmdx/chain.rb +34 -1
  13. data/lib/cmdx/coercion_registry.rb +18 -0
  14. data/lib/cmdx/coercions/array.rb +2 -0
  15. data/lib/cmdx/coercions/big_decimal.rb +3 -0
  16. data/lib/cmdx/coercions/boolean.rb +5 -0
  17. data/lib/cmdx/coercions/complex.rb +2 -0
  18. data/lib/cmdx/coercions/date.rb +4 -0
  19. data/lib/cmdx/coercions/date_time.rb +5 -0
  20. data/lib/cmdx/coercions/float.rb +2 -0
  21. data/lib/cmdx/coercions/hash.rb +2 -0
  22. data/lib/cmdx/coercions/integer.rb +2 -0
  23. data/lib/cmdx/coercions/rational.rb +2 -0
  24. data/lib/cmdx/coercions/string.rb +2 -0
  25. data/lib/cmdx/coercions/symbol.rb +2 -0
  26. data/lib/cmdx/coercions/time.rb +5 -0
  27. data/lib/cmdx/configuration.rb +111 -3
  28. data/lib/cmdx/context.rb +36 -0
  29. data/lib/cmdx/deprecator.rb +3 -0
  30. data/lib/cmdx/errors.rb +22 -0
  31. data/lib/cmdx/executor.rb +43 -0
  32. data/lib/cmdx/faults.rb +14 -0
  33. data/lib/cmdx/identifier.rb +2 -0
  34. data/lib/cmdx/locale.rb +3 -0
  35. data/lib/cmdx/log_formatters/json.rb +2 -0
  36. data/lib/cmdx/log_formatters/key_value.rb +2 -0
  37. data/lib/cmdx/log_formatters/line.rb +2 -0
  38. data/lib/cmdx/log_formatters/logstash.rb +2 -0
  39. data/lib/cmdx/log_formatters/raw.rb +2 -0
  40. data/lib/cmdx/middleware_registry.rb +20 -0
  41. data/lib/cmdx/middlewares/correlate.rb +11 -0
  42. data/lib/cmdx/middlewares/runtime.rb +4 -0
  43. data/lib/cmdx/middlewares/timeout.rb +4 -0
  44. data/lib/cmdx/pipeline.rb +20 -1
  45. data/lib/cmdx/railtie.rb +4 -0
  46. data/lib/cmdx/result.rb +123 -1
  47. data/lib/cmdx/task.rb +91 -1
  48. data/lib/cmdx/utils/call.rb +2 -0
  49. data/lib/cmdx/utils/condition.rb +3 -0
  50. data/lib/cmdx/utils/format.rb +5 -0
  51. data/lib/cmdx/validator_registry.rb +18 -0
  52. data/lib/cmdx/validators/exclusion.rb +2 -0
  53. data/lib/cmdx/validators/format.rb +2 -0
  54. data/lib/cmdx/validators/inclusion.rb +2 -0
  55. data/lib/cmdx/validators/length.rb +14 -0
  56. data/lib/cmdx/validators/numeric.rb +14 -0
  57. data/lib/cmdx/validators/presence.rb +2 -0
  58. data/lib/cmdx/version.rb +4 -1
  59. data/lib/cmdx/workflow.rb +10 -0
  60. data/lib/cmdx.rb +8 -0
  61. data/lib/generators/cmdx/locale_generator.rb +0 -1
  62. metadata +1 -1
@@ -10,6 +10,7 @@ module CMDx
10
10
 
11
11
  extend self
12
12
 
13
+ # @rbs DEFAULT_PRECISION: Integer
13
14
  DEFAULT_PRECISION = 14
14
15
 
15
16
  # Converts a value to a BigDecimal
@@ -28,6 +29,8 @@ module CMDx
28
29
  # @example Convert other numeric types
29
30
  # BigDecimal.call(42) # => #<BigDecimal:7f8b8c0d8e0f '0.42E2',9(18)>
30
31
  # BigDecimal.call(3.14159) # => #<BigDecimal:7f8b8c0d8e0f '0.314159E1',9(18)>
32
+ #
33
+ # @rbs (untyped value, ?Hash[Symbol, untyped] options) -> BigDecimal
31
34
  def call(value, options = {})
32
35
  BigDecimal(value, options[:precision] || DEFAULT_PRECISION)
33
36
  rescue ArgumentError, TypeError
@@ -10,7 +10,10 @@ module CMDx
10
10
 
11
11
  extend self
12
12
 
13
+ # @rbs FALSEY: Regexp
13
14
  FALSEY = /^(false|f|no|n|0)$/i
15
+
16
+ # @rbs TRUTHY: Regexp
14
17
  TRUTHY = /^(true|t|yes|y|1)$/i
15
18
 
16
19
  # Converts a value to a Boolean
@@ -34,6 +37,8 @@ module CMDx
34
37
  # @example Handle case-insensitive input
35
38
  # Boolean.call("TRUE") # => true
36
39
  # Boolean.call("False") # => false
40
+ #
41
+ # @rbs (untyped value, ?Hash[Symbol, untyped] options) -> bool
37
42
  def call(value, options = {})
38
43
  case value.to_s.downcase
39
44
  when FALSEY then false
@@ -26,6 +26,8 @@ module CMDx
26
26
  # Complex.call(5) # => (5+0i)
27
27
  # Complex.call(3.14) # => (3.14+0i)
28
28
  # Complex.call(Complex(1, 2)) # => (1+2i)
29
+ #
30
+ # @rbs (untyped value, ?Hash[Symbol, untyped] options) -> Complex
29
31
  def call(value, options = {})
30
32
  Complex(value)
31
33
  rescue ArgumentError, TypeError
@@ -12,6 +12,8 @@ module CMDx
12
12
  extend self
13
13
 
14
14
  # Types that are already date-like and don't need conversion
15
+ #
16
+ # @rbs ANALOG_TYPES: Array[String]
15
17
  ANALOG_TYPES = %w[Date DateTime Time].freeze
16
18
 
17
19
  # Converts a value to a Date object
@@ -33,6 +35,8 @@ module CMDx
33
35
  # @example Return existing Date objects unchanged
34
36
  # Date.call(Date.new(2023, 12, 25)) # => #<Date: 2023-12-25>
35
37
  # Date.call(DateTime.new(2023, 12, 25)) # => #<Date: 2023-12-25>
38
+ #
39
+ # @rbs (untyped value, ?Hash[Symbol, untyped] options) -> Date
36
40
  def call(value, options = {})
37
41
  return value if ANALOG_TYPES.include?(value.class.name)
38
42
  return ::Date.strptime(value, options[:strptime]) if options[:strptime]
@@ -11,6 +11,9 @@ module CMDx
11
11
 
12
12
  extend self
13
13
 
14
+ # Types that are already date-time-like and don't need conversion
15
+ #
16
+ # @rbs ANALOG_TYPES: Array[String]
14
17
  ANALOG_TYPES = %w[Date DateTime Time].freeze
15
18
 
16
19
  # Converts a value to a DateTime
@@ -32,6 +35,8 @@ module CMDx
32
35
  # @example Convert existing date objects
33
36
  # DateTime.call(Date.new(2023, 12, 25)) # => #<DateTime: 2023-12-25T00:00:00+00:00>
34
37
  # DateTime.call(Time.new(2023, 12, 25)) # => #<DateTime: 2023-12-25T00:00:00+00:00>
38
+ #
39
+ # @rbs (untyped value, ?Hash[Symbol, untyped] options) -> DateTime
35
40
  def call(value, options = {})
36
41
  return value if ANALOG_TYPES.include?(value.class.name)
37
42
  return ::DateTime.strptime(value, options[:strptime]) if options[:strptime]
@@ -30,6 +30,8 @@ module CMDx
30
30
  # Float.call(BigDecimal("123.456")) # => 123.456
31
31
  # Float.call(Rational(3, 4)) # => 0.75
32
32
  # Float.call(Complex(5.0, 0)) # => 5.0
33
+ #
34
+ # @rbs (untyped value, ?Hash[Symbol, untyped] options) -> Float
33
35
  def call(value, options = {})
34
36
  Float(value)
35
37
  rescue ArgumentError, RangeError, TypeError
@@ -30,6 +30,8 @@ module CMDx
30
30
  # Hash.call([:a, 1, :b, 2]) # => {a: 1, b: 2}
31
31
  # @example Coerce from JSON string
32
32
  # Hash.call('{"key": "value"}') # => {"key" => "value"}
33
+ #
34
+ # @rbs (untyped value, ?Hash[Symbol, untyped] options) -> Hash[untyped, untyped]
33
35
  def call(value, options = {})
34
36
  if value.nil?
35
37
  {}
@@ -34,6 +34,8 @@ module CMDx
34
34
  # Integer.call(nil) # => 0
35
35
  # Integer.call(false) # => 0
36
36
  # Integer.call(true) # => 1
37
+ #
38
+ # @rbs (untyped value, ?Hash[Symbol, untyped] options) -> Integer
37
39
  def call(value, options = {})
38
40
  Integer(value)
39
41
  rescue ArgumentError, FloatDomainError, RangeError, TypeError
@@ -33,6 +33,8 @@ module CMDx
33
33
  # Rational.call("") # => (0/1)
34
34
  # Rational.call(nil) # => (0/1)
35
35
  # Rational.call(0) # => (0/1)
36
+ #
37
+ # @rbs (untyped value, ?Hash[Symbol, untyped] options) -> Rational
36
38
  def call(value, options = {})
37
39
  Rational(value)
38
40
  rescue ArgumentError, FloatDomainError, RangeError, TypeError, ZeroDivisionError
@@ -26,6 +26,8 @@ module CMDx
26
26
  # String.call([1, 2, 3]) # => "[1, 2, 3]"
27
27
  # String.call(nil) # => ""
28
28
  # String.call(true) # => "true"
29
+ #
30
+ # @rbs (untyped value, ?Hash[Symbol, untyped] options) -> String
29
31
  def call(value, options = {})
30
32
  String(value)
31
33
  end
@@ -25,6 +25,8 @@ module CMDx
25
25
  # Symbol.call("user_id") # => :user_id
26
26
  # Symbol.call("") # => :""
27
27
  # Symbol.call(:existing) # => :existing
28
+ #
29
+ # @rbs (untyped value, ?Hash[Symbol, untyped] options) -> Symbol
28
30
  def call(value, options = {})
29
31
  value.to_sym
30
32
  rescue NoMethodError
@@ -11,6 +11,9 @@ module CMDx
11
11
 
12
12
  extend self
13
13
 
14
+ # Types that are already time-like and don't need conversion
15
+ #
16
+ # @rbs ANALOG_TYPES: Array[String]
14
17
  ANALOG_TYPES = %w[DateTime Time].freeze
15
18
 
16
19
  # Converts a value to a Time object
@@ -34,6 +37,8 @@ module CMDx
34
37
  # @example Convert strings with custom format
35
38
  # Time.call("25/12/2023", strptime: "%d/%m/%Y") # => Time object
36
39
  # Time.call("12-25-2023", strptime: "%m-%d-%Y") # => Time object
40
+ #
41
+ # @rbs (untyped value, ?Hash[Symbol, untyped] options) -> Time
37
42
  def call(value, options = {})
38
43
  return value if ANALOG_TYPES.include?(value.class.name)
39
44
  return value.to_time if value.respond_to?(:to_time)
@@ -6,11 +6,109 @@ module CMDx
6
6
  # callbacks, coercions, validators, breakpoints, backtraces, and logging.
7
7
  class Configuration
8
8
 
9
+ # @rbs DEFAULT_BREAKPOINTS: Array[String]
9
10
  DEFAULT_BREAKPOINTS = %w[failed].freeze
10
11
 
11
- attr_accessor :middlewares, :callbacks, :coercions, :validators,
12
- :task_breakpoints, :workflow_breakpoints, :logger,
13
- :backtrace, :backtrace_cleaner, :exception_handler
12
+ # Returns the middleware registry for task execution.
13
+ #
14
+ # @return [MiddlewareRegistry] The middleware registry
15
+ #
16
+ # @example
17
+ # config.middlewares.register(CustomMiddleware)
18
+ #
19
+ # @rbs @middlewares: MiddlewareRegistry
20
+ attr_accessor :middlewares
21
+
22
+ # Returns the callback registry for task lifecycle hooks.
23
+ #
24
+ # @return [CallbackRegistry] The callback registry
25
+ #
26
+ # @example
27
+ # config.callbacks.register(:before_execution, :log_start)
28
+ #
29
+ # @rbs @callbacks: CallbackRegistry
30
+ attr_accessor :callbacks
31
+
32
+ # Returns the coercion registry for type conversions.
33
+ #
34
+ # @return [CoercionRegistry] The coercion registry
35
+ #
36
+ # @example
37
+ # config.coercions.register(:custom, CustomCoercion)
38
+ #
39
+ # @rbs @coercions: CoercionRegistry
40
+ attr_accessor :coercions
41
+
42
+ # Returns the validator registry for attribute validation.
43
+ #
44
+ # @return [ValidatorRegistry] The validator registry
45
+ #
46
+ # @example
47
+ # config.validators.register(:email, EmailValidator)
48
+ #
49
+ # @rbs @validators: ValidatorRegistry
50
+ attr_accessor :validators
51
+
52
+ # Returns the breakpoint statuses for task execution interruption.
53
+ #
54
+ # @return [Array<String>] Array of status names that trigger breakpoints
55
+ #
56
+ # @example
57
+ # config.task_breakpoints = ["failed", "skipped"]
58
+ #
59
+ # @rbs @task_breakpoints: Array[String]
60
+ attr_accessor :task_breakpoints
61
+
62
+ # Returns the breakpoint statuses for workflow execution interruption.
63
+ #
64
+ # @return [Array<String>] Array of status names that trigger breakpoints
65
+ #
66
+ # @example
67
+ # config.workflow_breakpoints = ["failed", "skipped"]
68
+ #
69
+ # @rbs @task_breakpoints: Array[String]
70
+ # @rbs @workflow_breakpoints: Array[String]
71
+ attr_accessor :workflow_breakpoints
72
+
73
+ # Returns the logger instance for CMDx operations.
74
+ #
75
+ # @return [Logger] The logger instance
76
+ #
77
+ # @example
78
+ # config.logger.level = Logger::DEBUG
79
+ #
80
+ # @rbs @logger: Logger
81
+ attr_accessor :logger
82
+
83
+ # Returns whether to log backtraces for failed tasks.
84
+ #
85
+ # @return [Boolean] true if backtraces should be logged
86
+ #
87
+ # @example
88
+ # config.backtrace = true
89
+ #
90
+ # @rbs @backtrace: bool
91
+ attr_accessor :backtrace
92
+
93
+ # Returns the proc used to clean backtraces before logging.
94
+ #
95
+ # @return [Proc, nil] The backtrace cleaner proc, or nil if not set
96
+ #
97
+ # @example
98
+ # config.backtrace_cleaner = ->(bt) { bt.first(5) }
99
+ #
100
+ # @rbs @backtrace_cleaner: (Proc | nil)
101
+ attr_accessor :backtrace_cleaner
102
+
103
+ # Returns the proc called when exceptions occur during execution.
104
+ #
105
+ # @return [Proc, nil] The exception handler proc, or nil if not set
106
+ #
107
+ # @example
108
+ # config.exception_handler = ->(task, error) { Sentry.capture_exception(error) }
109
+ #
110
+ # @rbs @exception_handler: (Proc | nil)
111
+ attr_accessor :exception_handler
14
112
 
15
113
  # Initializes a new Configuration instance with default values.
16
114
  #
@@ -23,6 +121,8 @@ module CMDx
23
121
  # config = Configuration.new
24
122
  # config.middlewares.class # => MiddlewareRegistry
25
123
  # config.task_breakpoints # => ["failed"]
124
+ #
125
+ # @rbs () -> void
26
126
  def initialize
27
127
  @middlewares = MiddlewareRegistry.new
28
128
  @callbacks = CallbackRegistry.new
@@ -52,6 +152,8 @@ module CMDx
52
152
  # config = Configuration.new
53
153
  # config.to_h
54
154
  # # => { middlewares: #<MiddlewareRegistry>, callbacks: #<CallbackRegistry>, ... }
155
+ #
156
+ # @rbs () -> Hash[Symbol, untyped]
55
157
  def to_h
56
158
  {
57
159
  middlewares: @middlewares,
@@ -78,6 +180,8 @@ module CMDx
78
180
  # @example
79
181
  # config = CMDx.configuration
80
182
  # config.middlewares # => #<MiddlewareRegistry>
183
+ #
184
+ # @rbs () -> Configuration
81
185
  def configuration
82
186
  return @configuration if @configuration
83
187
 
@@ -99,6 +203,8 @@ module CMDx
99
203
  # config.task_breakpoints = ["failed", "skipped"]
100
204
  # config.logger.level = Logger::DEBUG
101
205
  # end
206
+ #
207
+ # @rbs () { (Configuration) -> void } -> Configuration
102
208
  def configure
103
209
  raise ArgumentError, "block required" unless block_given?
104
210
 
@@ -114,6 +220,8 @@ module CMDx
114
220
  # @example
115
221
  # CMDx.reset_configuration!
116
222
  # # Configuration is now reset to defaults
223
+ #
224
+ # @rbs () -> Configuration
117
225
  def reset_configuration!
118
226
  @configuration = Configuration.new
119
227
  end
data/lib/cmdx/context.rb CHANGED
@@ -11,6 +11,14 @@ module CMDx
11
11
 
12
12
  extend Forwardable
13
13
 
14
+ # Returns the internal hash storing context data.
15
+ #
16
+ # @return [Hash{Symbol => Object}] The internal hash table
17
+ #
18
+ # @example
19
+ # context.table # => { name: "John", age: 30 }
20
+ #
21
+ # @rbs @table: Hash[Symbol, untyped]
14
22
  attr_reader :table
15
23
  alias to_h table
16
24
 
@@ -28,6 +36,8 @@ module CMDx
28
36
  # @example
29
37
  # context = Context.new(name: "John", age: 30)
30
38
  # context[:name] # => "John"
39
+ #
40
+ # @rbs (untyped args) -> void
31
41
  def initialize(args = {})
32
42
  @table =
33
43
  if args.respond_to?(:to_hash)
@@ -50,6 +60,8 @@ module CMDx
50
60
  # existing = Context.new(name: "John")
51
61
  # built = Context.build(existing) # reuses existing context
52
62
  # built.object_id == existing.object_id # => true
63
+ #
64
+ # @rbs (untyped context) -> Context
53
65
  def self.build(context = {})
54
66
  if context.is_a?(self) && !context.frozen?
55
67
  context
@@ -70,6 +82,8 @@ module CMDx
70
82
  # context = Context.new(name: "John")
71
83
  # context[:name] # => "John"
72
84
  # context["name"] # => "John" (automatically converted to symbol)
85
+ #
86
+ # @rbs ((String | Symbol) key) -> untyped
73
87
  def [](key)
74
88
  table[key.to_sym]
75
89
  end
@@ -85,6 +99,8 @@ module CMDx
85
99
  # context = Context.new
86
100
  # context.store(:name, "John")
87
101
  # context[:name] # => "John"
102
+ #
103
+ # @rbs ((String | Symbol) key, untyped value) -> untyped
88
104
  def store(key, value)
89
105
  table[key.to_sym] = value
90
106
  end
@@ -104,6 +120,8 @@ module CMDx
104
120
  # context.fetch(:name) # => "John"
105
121
  # context.fetch(:age, 25) # => 25
106
122
  # context.fetch(:city) { |key| "Unknown #{key}" } # => "Unknown city"
123
+ #
124
+ # @rbs ((String | Symbol) key, *untyped) ?{ ((String | Symbol)) -> untyped } -> untyped
107
125
  def fetch(key, ...)
108
126
  table.fetch(key.to_sym, ...)
109
127
  end
@@ -122,6 +140,8 @@ module CMDx
122
140
  # context.fetch_or_store(:name, "Default") # => "John" (existing value)
123
141
  # context.fetch_or_store(:age, 25) # => 25 (stored and returned)
124
142
  # context.fetch_or_store(:city) { |key| "Unknown #{key}" } # => "Unknown city" (stored and returned)
143
+ #
144
+ # @rbs ((String | Symbol) key, ?untyped value) ?{ () -> untyped } -> untyped
125
145
  def fetch_or_store(key, value = nil)
126
146
  table.fetch(key.to_sym) do
127
147
  table[key.to_sym] = block_given? ? yield : value
@@ -139,6 +159,8 @@ module CMDx
139
159
  # context = Context.new(name: "John")
140
160
  # context.merge!(age: 30, city: "NYC")
141
161
  # context.to_h # => {name: "John", age: 30, city: "NYC"}
162
+ #
163
+ # @rbs (?untyped args) -> self
142
164
  def merge!(args = {})
143
165
  args.to_h.each { |key, value| self[key.to_sym] = value }
144
166
  self
@@ -156,6 +178,8 @@ module CMDx
156
178
  # context = Context.new(name: "John", age: 30)
157
179
  # context.delete!(:age) # => 30
158
180
  # context.delete!(:city) { |key| "Key #{key} not found" } # => "Key city not found"
181
+ #
182
+ # @rbs ((String | Symbol) key) ?{ ((String | Symbol)) -> untyped } -> untyped
159
183
  def delete!(key, &)
160
184
  table.delete(key.to_sym, &)
161
185
  end
@@ -170,6 +194,8 @@ module CMDx
170
194
  # context1 = Context.new(name: "John")
171
195
  # context2 = Context.new(name: "John")
172
196
  # context1 == context2 # => true
197
+ #
198
+ # @rbs (untyped other) -> bool
173
199
  def eql?(other)
174
200
  other.is_a?(self.class) && (to_h == other.to_h)
175
201
  end
@@ -185,6 +211,8 @@ module CMDx
185
211
  # context = Context.new(name: "John")
186
212
  # context.key?(:name) # => true
187
213
  # context.key?(:age) # => false
214
+ #
215
+ # @rbs ((String | Symbol) key) -> bool
188
216
  def key?(key)
189
217
  table.key?(key.to_sym)
190
218
  end
@@ -200,6 +228,8 @@ module CMDx
200
228
  # context = Context.new(user: {profile: {name: "John"}})
201
229
  # context.dig(:user, :profile, :name) # => "John"
202
230
  # context.dig(:user, :profile, :age) # => nil
231
+ #
232
+ # @rbs ((String | Symbol) key, *(String | Symbol) keys) -> untyped
203
233
  def dig(key, *keys)
204
234
  table.dig(key.to_sym, *keys)
205
235
  end
@@ -211,6 +241,8 @@ module CMDx
211
241
  # @example
212
242
  # context = Context.new(name: "John", age: 30)
213
243
  # context.to_s # => "name: John, age: 30"
244
+ #
245
+ # @rbs () -> String
214
246
  def to_s
215
247
  Utils::Format.to_str(to_h)
216
248
  end
@@ -227,6 +259,8 @@ module CMDx
227
259
  # @yield [Object] optional block
228
260
  #
229
261
  # @return [Object] the result of the method call
262
+ #
263
+ # @rbs (Symbol method_name, *untyped args, **untyped _kwargs) ?{ () -> untyped } -> untyped
230
264
  def method_missing(method_name, *args, **_kwargs, &)
231
265
  fetch(method_name) do
232
266
  store(method_name[0..-2], args.first) if method_name.end_with?("=")
@@ -244,6 +278,8 @@ module CMDx
244
278
  # context = Context.new(name: "John")
245
279
  # context.respond_to?(:name) # => true
246
280
  # context.respond_to?(:age) # => false
281
+ #
282
+ # @rbs (Symbol method_name, ?bool include_private) -> bool
247
283
  def respond_to_missing?(method_name, include_private = false)
248
284
  key?(method_name) || super
249
285
  end
@@ -10,6 +10,7 @@ module CMDx
10
10
 
11
11
  extend self
12
12
 
13
+ # @rbs EVAL: Proc
13
14
  EVAL = proc do |target, callable|
14
15
  case callable
15
16
  when /raise|log|warn/ then callable
@@ -45,6 +46,8 @@ module CMDx
45
46
  # end
46
47
  #
47
48
  # MyTask.new # => [MyTask] DEPRECATED: migrate to a replacement or discontinue use
49
+ #
50
+ # @rbs (Task task) -> void
48
51
  def restrict(task)
49
52
  type = EVAL.call(task, task.class.settings[:deprecate])
50
53
 
data/lib/cmdx/errors.rb CHANGED
@@ -8,11 +8,21 @@ module CMDx
8
8
 
9
9
  extend Forwardable
10
10
 
11
+ # Returns the internal hash of error messages by attribute.
12
+ #
13
+ # @return [Hash{Symbol => Set<String>}] Hash mapping attribute names to error message sets
14
+ #
15
+ # @example
16
+ # errors.messages # => { email: #<Set: ["must be valid", "is required"]> }
17
+ #
18
+ # @rbs @messages: Hash[Symbol, Set[String]]
11
19
  attr_reader :messages
12
20
 
13
21
  def_delegators :messages, :empty?
14
22
 
15
23
  # Initialize a new error collection.
24
+ #
25
+ # @rbs () -> void
16
26
  def initialize
17
27
  @messages = {}
18
28
  end
@@ -26,6 +36,8 @@ module CMDx
26
36
  # errors = CMDx::Errors.new
27
37
  # errors.add(:email, "must be valid format")
28
38
  # errors.add(:email, "cannot be blank")
39
+ #
40
+ # @rbs (Symbol attribute, String message) -> void
29
41
  def add(attribute, message)
30
42
  return if message.empty?
31
43
 
@@ -42,6 +54,8 @@ module CMDx
42
54
  # @example
43
55
  # errors.for?(:email) # => true
44
56
  # errors.for?(:name) # => false
57
+ #
58
+ # @rbs (Symbol attribute) -> bool
45
59
  def for?(attribute)
46
60
  return false unless messages.key?(attribute)
47
61
 
@@ -54,6 +68,8 @@ module CMDx
54
68
  #
55
69
  # @example
56
70
  # errors.full_messages # => { email: ["email must be valid format", "email cannot be blank"] }
71
+ #
72
+ # @rbs () -> Hash[Symbol, Array[String]]
57
73
  def full_messages
58
74
  messages.each_with_object({}) do |(attribute, messages), hash|
59
75
  hash[attribute] = messages.map { |message| "#{attribute} #{message}" }
@@ -66,6 +82,8 @@ module CMDx
66
82
  #
67
83
  # @example
68
84
  # errors.to_h # => { email: ["must be valid format", "cannot be blank"] }
85
+ #
86
+ # @rbs () -> Hash[Symbol, Array[String]]
69
87
  def to_h
70
88
  messages.transform_values(&:to_a)
71
89
  end
@@ -78,6 +96,8 @@ module CMDx
78
96
  # @example
79
97
  # errors.to_hash # => { email: ["must be valid format", "cannot be blank"] }
80
98
  # errors.to_hash(true) # => { email: ["email must be valid format", "email cannot be blank"] }
99
+ #
100
+ # @rbs (?bool full) -> Hash[Symbol, Array[String]]
81
101
  def to_hash(full = false)
82
102
  full ? full_messages : to_h
83
103
  end
@@ -88,6 +108,8 @@ module CMDx
88
108
  #
89
109
  # @example
90
110
  # errors.to_s # => "email must be valid format. email cannot be blank"
111
+ #
112
+ # @rbs () -> String
91
113
  def to_s
92
114
  full_messages.values.flatten.join(". ")
93
115
  end