cmdx 1.1.0 → 1.1.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 (87) hide show
  1. checksums.yaml +4 -4
  2. data/.cursor/prompts/docs.md +9 -0
  3. data/.cursor/prompts/rspec.md +13 -12
  4. data/.cursor/prompts/yardoc.md +11 -6
  5. data/CHANGELOG.md +13 -2
  6. data/README.md +1 -0
  7. data/docs/ai_prompts.md +269 -195
  8. data/docs/basics/call.md +124 -58
  9. data/docs/basics/chain.md +190 -160
  10. data/docs/basics/context.md +242 -154
  11. data/docs/basics/setup.md +302 -32
  12. data/docs/callbacks.md +390 -94
  13. data/docs/configuration.md +181 -65
  14. data/docs/deprecation.md +245 -0
  15. data/docs/getting_started.md +161 -39
  16. data/docs/internationalization.md +590 -70
  17. data/docs/interruptions/exceptions.md +135 -118
  18. data/docs/interruptions/faults.md +150 -125
  19. data/docs/interruptions/halt.md +134 -80
  20. data/docs/logging.md +181 -118
  21. data/docs/middlewares.md +150 -377
  22. data/docs/outcomes/result.md +140 -112
  23. data/docs/outcomes/states.md +134 -99
  24. data/docs/outcomes/statuses.md +204 -146
  25. data/docs/parameters/coercions.md +232 -281
  26. data/docs/parameters/defaults.md +224 -169
  27. data/docs/parameters/definitions.md +289 -141
  28. data/docs/parameters/namespacing.md +250 -161
  29. data/docs/parameters/validations.md +260 -133
  30. data/docs/testing.md +191 -197
  31. data/docs/workflows.md +143 -98
  32. data/lib/cmdx/callback.rb +23 -19
  33. data/lib/cmdx/callback_registry.rb +1 -3
  34. data/lib/cmdx/chain_inspector.rb +23 -23
  35. data/lib/cmdx/chain_serializer.rb +38 -19
  36. data/lib/cmdx/coercion.rb +20 -12
  37. data/lib/cmdx/coercion_registry.rb +51 -32
  38. data/lib/cmdx/configuration.rb +84 -31
  39. data/lib/cmdx/context.rb +32 -21
  40. data/lib/cmdx/core_ext/hash.rb +13 -13
  41. data/lib/cmdx/core_ext/module.rb +1 -1
  42. data/lib/cmdx/core_ext/object.rb +12 -12
  43. data/lib/cmdx/correlator.rb +60 -39
  44. data/lib/cmdx/errors.rb +105 -131
  45. data/lib/cmdx/fault.rb +66 -45
  46. data/lib/cmdx/immutator.rb +20 -21
  47. data/lib/cmdx/lazy_struct.rb +78 -70
  48. data/lib/cmdx/log_formatters/json.rb +1 -1
  49. data/lib/cmdx/log_formatters/key_value.rb +1 -1
  50. data/lib/cmdx/log_formatters/line.rb +1 -1
  51. data/lib/cmdx/log_formatters/logstash.rb +1 -1
  52. data/lib/cmdx/log_formatters/pretty_json.rb +1 -1
  53. data/lib/cmdx/log_formatters/pretty_key_value.rb +1 -1
  54. data/lib/cmdx/log_formatters/pretty_line.rb +1 -1
  55. data/lib/cmdx/log_formatters/raw.rb +2 -2
  56. data/lib/cmdx/logger.rb +19 -14
  57. data/lib/cmdx/logger_ansi.rb +33 -17
  58. data/lib/cmdx/logger_serializer.rb +85 -24
  59. data/lib/cmdx/middleware.rb +39 -21
  60. data/lib/cmdx/middleware_registry.rb +4 -3
  61. data/lib/cmdx/parameter.rb +151 -89
  62. data/lib/cmdx/parameter_inspector.rb +34 -21
  63. data/lib/cmdx/parameter_registry.rb +36 -30
  64. data/lib/cmdx/parameter_serializer.rb +21 -14
  65. data/lib/cmdx/result.rb +136 -135
  66. data/lib/cmdx/result_ansi.rb +31 -17
  67. data/lib/cmdx/result_inspector.rb +32 -27
  68. data/lib/cmdx/result_logger.rb +23 -14
  69. data/lib/cmdx/result_serializer.rb +65 -27
  70. data/lib/cmdx/task.rb +234 -113
  71. data/lib/cmdx/task_deprecator.rb +22 -25
  72. data/lib/cmdx/task_processor.rb +89 -88
  73. data/lib/cmdx/task_serializer.rb +27 -14
  74. data/lib/cmdx/utils/monotonic_runtime.rb +2 -4
  75. data/lib/cmdx/validator.rb +25 -16
  76. data/lib/cmdx/validator_registry.rb +53 -31
  77. data/lib/cmdx/validators/exclusion.rb +1 -1
  78. data/lib/cmdx/validators/format.rb +2 -2
  79. data/lib/cmdx/validators/inclusion.rb +2 -2
  80. data/lib/cmdx/validators/length.rb +2 -2
  81. data/lib/cmdx/validators/numeric.rb +3 -3
  82. data/lib/cmdx/validators/presence.rb +2 -2
  83. data/lib/cmdx/version.rb +1 -1
  84. data/lib/cmdx/workflow.rb +54 -33
  85. data/lib/generators/cmdx/task_generator.rb +6 -6
  86. data/lib/generators/cmdx/workflow_generator.rb +6 -6
  87. metadata +3 -1
data/lib/cmdx/result.rb CHANGED
@@ -37,18 +37,18 @@ module CMDx
37
37
  # @return [Hash] Additional metadata associated with the result
38
38
  attr_reader :metadata
39
39
 
40
- # Creates a new Result instance for the specified task.
40
+ # Initializes a new result for the given task
41
41
  #
42
- # @param task [CMDx::Task] the task instance that will generate this result
42
+ # @param task [CMDx::Task] the task to create a result for
43
43
  #
44
- # @return [Result] a new Result instance
44
+ # @return [CMDx::Result] a new result instance
45
45
  #
46
- # @raise [TypeError] if task is not a Task or Workflow instance
46
+ # @raise [TypeError] if task is not a Task or Workflow
47
47
  #
48
48
  # @example Create a result for a task
49
- # task = MyTask.new
50
- # result = Result.new(task)
51
- # result.state # => "initialized"
49
+ # result = CMDx::Result.new(my_task)
50
+ # result.state #=> "initialized"
51
+ # result.status #=> "success"
52
52
  def initialize(task)
53
53
  raise TypeError, "must be a Task or Workflow" unless task.is_a?(Task)
54
54
 
@@ -64,16 +64,16 @@ module CMDx
64
64
  # @return [Boolean] true if the result matches the state
65
65
  #
66
66
  # @example Check if result is initialized
67
- # result.initialized? # => true
67
+ # result.initialized? #=> true
68
68
  #
69
69
  # @example Check if result is executing
70
- # result.executing? # => false
70
+ # result.executing? #=> false
71
71
  #
72
72
  # @example Check if result is complete
73
- # result.complete? # => false
73
+ # result.complete? #=> false
74
74
  #
75
75
  # @example Check if result is interrupted
76
- # result.interrupted? # => false
76
+ # result.interrupted? #=> false
77
77
  define_method(:"#{s}?") { state == s }
78
78
 
79
79
  # Executes the provided block if the result is in the specified state.
@@ -103,45 +103,45 @@ module CMDx
103
103
  end
104
104
  end
105
105
 
106
- # Transitions the result to its final executed state based on current status.
106
+ # Marks the result as executed by transitioning to complete or interrupted state
107
+ # based on the current status
107
108
  #
108
- # @return [Result] returns self for method chaining
109
+ # @return [void]
109
110
  #
110
- # @example Complete successful execution
111
- # result.success? # => true
112
- # result.executed! # transitions to complete
113
- # result.complete? # => true
111
+ # @example Mark successful task as executed
112
+ # result.executed!
113
+ # result.complete? #=> true
114
114
  #
115
- # @example Handle failed execution
115
+ # @example Mark failed task as executed
116
116
  # result.fail!
117
- # result.executed! # transitions to interrupted
118
- # result.interrupted? # => true
117
+ # result.executed!
118
+ # result.interrupted? #=> true
119
119
  def executed!
120
120
  success? ? complete! : interrupt!
121
121
  end
122
122
 
123
- # Checks if the result has finished executing (either complete or interrupted).
123
+ # Checks if the result has been executed (either complete or interrupted)
124
124
  #
125
- # @return [Boolean] true if the result is in a final execution state
125
+ # @return [Boolean] true if the result is complete or interrupted
126
126
  #
127
- # @example Check execution completion
128
- # result.executed? # => false
129
- # result.complete!
130
- # result.executed? # => true
127
+ # @example Check if result was executed
128
+ # result.executed? #=> false
129
+ # result.executed!
130
+ # result.executed? #=> true
131
131
  def executed?
132
132
  complete? || interrupted?
133
133
  end
134
134
 
135
- # Executes the provided block if the result has finished executing.
135
+ # Executes the provided block if the result has been executed
136
136
  #
137
- # @param block [Proc] the block to execute if result is executed
137
+ # @param block [Proc] the block to execute if result was executed
138
138
  #
139
139
  # @return [Result] returns self for method chaining
140
140
  #
141
141
  # @raise [ArgumentError] if no block is provided
142
142
  #
143
- # @example Handle executed result
144
- # result.on_executed { |r| puts "Task completed with #{r.status}" }
143
+ # @example Handle executed results
144
+ # result.on_executed { |r| puts "Task execution finished" }
145
145
  def on_executed(&)
146
146
  raise ArgumentError, "block required" unless block_given?
147
147
 
@@ -149,16 +149,15 @@ module CMDx
149
149
  self
150
150
  end
151
151
 
152
- # Transitions the result to executing state.
152
+ # Transitions the result to executing state
153
153
  #
154
- # @return [Result] returns self for method chaining
154
+ # @return [void]
155
155
  #
156
156
  # @raise [RuntimeError] if not transitioning from initialized state
157
157
  #
158
158
  # @example Start task execution
159
- # result.initialized? # => true
160
159
  # result.executing!
161
- # result.executing? # => true
160
+ # result.executing? #=> true
162
161
  def executing!
163
162
  return if executing?
164
163
 
@@ -167,16 +166,16 @@ module CMDx
167
166
  @state = EXECUTING
168
167
  end
169
168
 
170
- # Transitions the result to complete state.
169
+ # Transitions the result to complete state
171
170
  #
172
- # @return [Result] returns self for method chaining
171
+ # @return [void]
173
172
  #
174
173
  # @raise [RuntimeError] if not transitioning from executing state
175
174
  #
176
175
  # @example Complete task execution
177
176
  # result.executing!
178
177
  # result.complete!
179
- # result.complete? # => true
178
+ # result.complete? #=> true
180
179
  def complete!
181
180
  return if complete?
182
181
 
@@ -185,17 +184,16 @@ module CMDx
185
184
  @state = COMPLETE
186
185
  end
187
186
 
188
- # Transitions the result to interrupted state due to failure.
187
+ # Transitions the result to interrupted state
189
188
  #
190
- # @return [Result] returns self for method chaining
189
+ # @return [void]
191
190
  #
192
- # @raise [RuntimeError] if trying to transition from complete state
191
+ # @raise [RuntimeError] if transitioning from complete state
193
192
  #
194
- # @example Interrupt execution on failure
193
+ # @example Interrupt task execution
195
194
  # result.executing!
196
- # result.fail!
197
195
  # result.interrupt!
198
- # result.interrupted? # => true
196
+ # result.interrupted? #=> true
199
197
  def interrupt!
200
198
  return if interrupted?
201
199
 
@@ -210,13 +208,13 @@ module CMDx
210
208
  # @return [Boolean] true if the result matches the status
211
209
  #
212
210
  # @example Check if result is successful
213
- # result.success? # => true
211
+ # result.success? #=> true
214
212
  #
215
213
  # @example Check if result is skipped
216
- # result.skipped? # => false
214
+ # result.skipped? #=> false
217
215
  #
218
216
  # @example Check if result is failed
219
- # result.failed? # => false
217
+ # result.failed? #=> false
220
218
  define_method(:"#{s}?") { status == s }
221
219
 
222
220
  # Executes the provided block if the result has the specified status.
@@ -243,19 +241,19 @@ module CMDx
243
241
  end
244
242
  end
245
243
 
246
- # Checks if the result has a positive outcome (not failed).
244
+ # Checks if the result has a good outcome (not failed)
247
245
  #
248
- # @return [Boolean] true if the result is successful or skipped
246
+ # @return [Boolean] true if the result is not failed
249
247
  #
250
248
  # @example Check for good outcome
251
- # result.good? # => true (success or skipped)
249
+ # result.good? #=> true (initially successful)
252
250
  # result.fail!
253
- # result.good? # => false
251
+ # result.good? #=> false
254
252
  def good?
255
253
  !failed?
256
254
  end
257
255
 
258
- # Executes the provided block if the result has a good outcome.
256
+ # Executes the provided block if the result has a good outcome
259
257
  #
260
258
  # @param block [Proc] the block to execute if result is good
261
259
  #
@@ -263,8 +261,8 @@ module CMDx
263
261
  #
264
262
  # @raise [ArgumentError] if no block is provided
265
263
  #
266
- # @example Handle good outcome
267
- # result.on_good { |r| puts "Task succeeded with #{r.status}" }
264
+ # @example Handle good results
265
+ # result.on_good { |r| puts "Task had good outcome" }
268
266
  def on_good(&)
269
267
  raise ArgumentError, "block required" unless block_given?
270
268
 
@@ -272,19 +270,19 @@ module CMDx
272
270
  self
273
271
  end
274
272
 
275
- # Checks if the result has a negative outcome (not successful).
273
+ # Checks if the result has a bad outcome (not successful)
276
274
  #
277
- # @return [Boolean] true if the result is skipped or failed
275
+ # @return [Boolean] true if the result is not successful
278
276
  #
279
277
  # @example Check for bad outcome
280
- # result.bad? # => false (initially successful)
278
+ # result.bad? #=> false (initially successful)
281
279
  # result.skip!
282
- # result.bad? # => true
280
+ # result.bad? #=> true
283
281
  def bad?
284
282
  !success?
285
283
  end
286
284
 
287
- # Executes the provided block if the result has a bad outcome.
285
+ # Executes the provided block if the result has a bad outcome
288
286
  #
289
287
  # @param block [Proc] the block to execute if result is bad
290
288
  #
@@ -293,7 +291,7 @@ module CMDx
293
291
  # @raise [ArgumentError] if no block is provided
294
292
  #
295
293
  # @example Handle bad outcome
296
- # result.on_bad { |r| puts "Task had issues: #{r.status}" }
294
+ # result.on_bad { |r| puts "Task had bad outcome: #{r.status}" }
297
295
  def on_bad(&)
298
296
  raise ArgumentError, "block required" unless block_given?
299
297
 
@@ -301,18 +299,21 @@ module CMDx
301
299
  self
302
300
  end
303
301
 
304
- # Transitions the result to skipped status with optional metadata.
302
+ # Transitions the result to skipped status and sets metadata
305
303
  #
306
- # @param metadata [Hash] additional metadata to store with the skip
304
+ # @param metadata [Hash] additional metadata about why the task was skipped
305
+ # @option metadata [String] :reason the reason for skipping
306
+ # @option metadata [Exception] :original_exception the original exception that caused skipping
307
307
  #
308
- # @return [Result] returns self for method chaining
308
+ # @return [void]
309
309
  #
310
310
  # @raise [RuntimeError] if not transitioning from success status
311
+ # @raise [CMDx::Fault] if no original_exception in metadata (via halt!)
311
312
  #
312
313
  # @example Skip a task with reason
313
- # result.skip!(reason: "condition not met")
314
- # result.skipped? # => true
315
- # result.metadata[:reason] # => "condition not met"
314
+ # result.skip!(reason: "Dependencies not met")
315
+ # result.skipped? #=> true
316
+ # result.metadata[:reason] #=> "Dependencies not met"
316
317
  def skip!(**metadata)
317
318
  return if skipped?
318
319
 
@@ -324,18 +325,21 @@ module CMDx
324
325
  halt! unless metadata[:original_exception]
325
326
  end
326
327
 
327
- # Transitions the result to failed status with optional metadata.
328
+ # Transitions the result to failed status and sets metadata
328
329
  #
329
- # @param metadata [Hash] additional metadata to store with the failure
330
+ # @param metadata [Hash] additional metadata about the failure
331
+ # @option metadata [String] :error the error message
332
+ # @option metadata [Exception] :original_exception the original exception that caused failure
330
333
  #
331
- # @return [Result] returns self for method chaining
334
+ # @return [void]
332
335
  #
333
336
  # @raise [RuntimeError] if not transitioning from success status
337
+ # @raise [CMDx::Fault] if no original_exception in metadata (via halt!)
334
338
  #
335
- # @example Fail a task with error details
336
- # result.fail!(error: "validation failed", code: 422)
337
- # result.failed? # => true
338
- # result.metadata[:error] # => "validation failed"
339
+ # @example Fail a task with error message
340
+ # result.fail!(reason: "Database connection failed")
341
+ # result.failed? #=> true
342
+ # result.metadata[:error] #=> "Database connection failed"
339
343
  def fail!(**metadata)
340
344
  return if failed?
341
345
 
@@ -347,35 +351,35 @@ module CMDx
347
351
  halt! unless metadata[:original_exception]
348
352
  end
349
353
 
350
- # Raises a Fault exception to halt execution chain if result is not successful.
354
+ # Halts execution by raising a fault if the result is not successful
351
355
  #
352
- # @return [nil] never returns normally
356
+ # @return [void]
353
357
  #
354
- # @raise [Fault] if the result is not successful
358
+ # @raise [CMDx::Fault] if the result is not successful
355
359
  #
356
- # @example Halt execution on failure
357
- # result.fail!
358
- # result.halt! # raises Fault
360
+ # @example Halt on failed result
361
+ # result.fail!(reason: "Something went wrong")
362
+ # result.halt! # raises CMDx::Fault
359
363
  def halt!
360
364
  return if success?
361
365
 
362
366
  raise Fault.build(self)
363
367
  end
364
368
 
365
- # Propagates status and metadata from another result to this result.
369
+ # Throws the status and metadata from another result to this result
366
370
  #
367
- # @param result [Result] the result to throw/propagate from
371
+ # @param result [CMDx::Result] the result to throw from
368
372
  # @param local_metadata [Hash] additional metadata to merge
369
373
  #
370
- # @return [Result] returns self for method chaining
374
+ # @return [void]
371
375
  #
372
376
  # @raise [TypeError] if result is not a Result instance
373
377
  #
374
- # @example Throw failure from another result
378
+ # @example Throw from a failed result
375
379
  # failed_result = Result.new(task)
376
- # failed_result.fail!(error: "network timeout")
380
+ # failed_result.fail!(reason: "network timeout")
377
381
  # current_result.throw!(failed_result)
378
- # current_result.failed? # => true
382
+ # current_result.failed? #=> true
379
383
  def throw!(result, local_metadata = {})
380
384
  raise TypeError, "must be a Result" unless result.is_a?(Result)
381
385
 
@@ -385,38 +389,36 @@ module CMDx
385
389
  fail!(**md) if result.failed?
386
390
  end
387
391
 
388
- # Finds the original result that caused a failure in the execution chain.
392
+ # Finds the result that originally caused a failure in the chain
389
393
  #
390
- # @return [Result, nil] the result that originally caused the failure, or nil if not failed
394
+ # @return [CMDx::Result, nil] the result that caused the failure, or nil if not failed
391
395
  #
392
- # @example Find original failure cause
393
- # chain.results.last.caused_failure
394
- # # => #<Result task=OriginalTask status=failed>
396
+ # @example Find the original failure cause
397
+ # result.caused_failure #=> #<Result task=OriginalTask status=failed>
395
398
  def caused_failure
396
399
  return unless failed?
397
400
 
398
401
  chain.results.reverse.find(&:failed?)
399
402
  end
400
403
 
401
- # Checks if this result is the original cause of failure in the chain.
404
+ # Checks if this result caused a failure in the chain
402
405
  #
403
- # @return [Boolean] true if this result caused the failure chain
406
+ # @return [Boolean] true if this result caused the failure
404
407
  #
405
- # @example Check if this result caused failure
406
- # result.caused_failure? # => true if this is the original failure
408
+ # @example Check if result caused failure
409
+ # result.caused_failure? #=> true
407
410
  def caused_failure?
408
411
  return false unless failed?
409
412
 
410
413
  caused_failure == self
411
414
  end
412
415
 
413
- # Finds the result that threw/propagated this failure.
416
+ # Finds the result that this failure was thrown to
414
417
  #
415
- # @return [Result, nil] the result that threw this failure, or nil if not applicable
418
+ # @return [CMDx::Result, nil] the result that received the thrown failure, or nil if not failed
416
419
  #
417
- # @example Find failure propagator
418
- # result.threw_failure
419
- # # => #<Result task=PropagatorTask status=failed>
420
+ # @example Find where failure was thrown
421
+ # result.threw_failure #=> #<Result task=PropagatorTask status=failed>
420
422
  def threw_failure
421
423
  return unless failed?
422
424
 
@@ -424,93 +426,92 @@ module CMDx
424
426
  results.find { |r| r.index > index } || results.last
425
427
  end
426
428
 
427
- # Checks if this result threw/propagated a failure.
429
+ # Checks if this result threw a failure to another result
428
430
  #
429
431
  # @return [Boolean] true if this result threw a failure
430
432
  #
431
- # @example Check if this result threw failure
432
- # result.threw_failure? # => true if this result propagated failure
433
+ # @example Check if result threw failure
434
+ # result.threw_failure? #=> false
433
435
  def threw_failure?
434
436
  return false unless failed?
435
437
 
436
438
  threw_failure == self
437
439
  end
438
440
 
439
- # Checks if this result represents a propagated failure (not the original cause).
441
+ # Checks if this result received a thrown failure from another result
440
442
  #
441
- # @return [Boolean] true if this is a propagated failure
443
+ # @return [Boolean] true if this result received a thrown failure
442
444
  #
443
- # @example Check if failure was propagated
444
- # result.thrown_failure? # => true if failure came from earlier in chain
445
+ # @example Check if result received thrown failure
446
+ # result.thrown_failure? #=> true
445
447
  def thrown_failure?
446
448
  failed? && !caused_failure?
447
449
  end
448
450
 
449
- # Gets the index position of this result in the execution chain.
451
+ # Returns the index of this result in the chain
450
452
  #
451
- # @return [Integer] the zero-based index position in the chain
453
+ # @return [Integer] the zero-based index of this result
452
454
  #
453
- # @example Get result position
454
- # result.index # => 2 (third result in chain)
455
+ # @example Get result index
456
+ # result.index #=> 2
455
457
  def index
456
458
  chain.index(self)
457
459
  end
458
460
 
459
- # Determines the overall outcome of this result.
461
+ # Returns the outcome of the result (state for certain cases, status otherwise)
460
462
  #
461
- # @return [String] the outcome - state for certain conditions, status otherwise
463
+ # @return [String] the outcome (state or status)
462
464
  #
463
465
  # @example Get result outcome
464
- # result.outcome # => "success" or "failed" or "initialized"
466
+ # result.outcome #=> "success"
467
+ # result.fail!
468
+ # result.outcome #=> "failed"
465
469
  def outcome
466
470
  initialized? || thrown_failure? ? state : status
467
471
  end
468
472
 
469
- # Gets or measures the runtime duration of the result's execution.
473
+ # Gets or measures the runtime of the result
470
474
  #
471
- # @param block [Proc] optional block to measure execution time
475
+ # @param block [Proc] optional block to measure runtime for
472
476
  #
473
477
  # @return [Float, nil] the runtime in seconds, or nil if not measured
474
478
  #
475
479
  # @example Get existing runtime
476
- # result.runtime # => 0.523 (seconds)
480
+ # result.runtime #=> 1.234
477
481
  #
478
- # @example Measure execution time
479
- # result.runtime { sleep 1; do_work }
480
- # result.runtime # => 1.001
482
+ # @example Measure runtime with block
483
+ # result.runtime { sleep 1 } #=> 1.0
481
484
  def runtime(&)
482
485
  return @runtime unless block_given?
483
486
 
484
487
  @runtime = Utils::MonotonicRuntime.call(&)
485
488
  end
486
489
 
487
- # Converts the result to a hash representation.
490
+ # Converts the result to a hash representation
488
491
  #
489
- # @return [Hash] hash representation of the result
492
+ # @return [Hash] serialized representation of the result
490
493
  #
491
494
  # @example Convert to hash
492
- # result.to_h
493
- # # => {state: "complete", status: "success", metadata: {}}
495
+ # result.to_h #=> { state: "complete", status: "success", ... }
494
496
  def to_h
495
497
  ResultSerializer.call(self)
496
498
  end
497
499
 
498
- # Returns a string representation of the result.
500
+ # Returns a string representation of the result
499
501
  #
500
502
  # @return [String] formatted string representation
501
503
  #
502
- # @example Get string representation
503
- # result.to_s
504
- # # => "MyTask [complete/success]"
504
+ # @example Convert to string
505
+ # result.to_s #=> "Result[complete/success]"
505
506
  def to_s
506
507
  ResultInspector.call(to_h)
507
508
  end
508
509
 
509
- # Deconstructs the result for pattern matching.
510
+ # Deconstructs the result for pattern matching
510
511
  #
511
- # @return [Array] array containing state and status
512
+ # @return [Array<String>] array containing state and status
512
513
  #
513
- # @example Pattern match on result
514
+ # @example Pattern matching with deconstruct
514
515
  # case result
515
516
  # in ["complete", "success"]
516
517
  # puts "Task completed successfully"
@@ -519,16 +520,16 @@ module CMDx
519
520
  [state, status]
520
521
  end
521
522
 
522
- # Deconstructs the result to a hash for pattern matching with keys.
523
+ # Deconstructs the result with keys for pattern matching
523
524
  #
524
- # @param keys [Array<Symbol>, nil] specific keys to extract, or nil for all
525
+ # @param keys [Array<Symbol>, nil] specific keys to include in deconstruction
525
526
  #
526
- # @return [Hash] hash containing requested attributes
527
+ # @return [Hash] hash with requested attributes
527
528
  #
528
- # @example Pattern match with keys
529
+ # @example Pattern matching with specific keys
529
530
  # case result
530
- # in {state: "complete", good: true}
531
- # puts "Task completed successfully"
531
+ # in { state: "complete", good: true }
532
+ # puts "Task finished well"
532
533
  # end
533
534
  def deconstruct_keys(keys)
534
535
  attributes = {
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CMDx
4
- # ANSI color formatting for result states and statuses.
4
+ # ANSI color formatting utilities for result states and statuses.
5
5
  #
6
- # This module provides functionality to apply appropriate ANSI color codes
7
- # to result states and statuses for enhanced console output readability.
8
- # It maps execution states and completion statuses to corresponding colors
9
- # and provides methods to format strings with these colors.
6
+ # This module provides functionality to apply appropriate ANSI colors to
7
+ # result states and statuses for enhanced terminal output visibility.
8
+ # It maps different execution states and statuses to their corresponding
9
+ # colors and delegates the actual color application to the AnsiColor utility.
10
10
  module ResultAnsi
11
11
 
12
12
  STATE_COLORS = {
@@ -23,32 +23,46 @@ module CMDx
23
23
 
24
24
  module_function
25
25
 
26
- # Applies ANSI color formatting to a string based on its state or status.
26
+ # Applies ANSI color formatting to a result state or status string.
27
27
  #
28
- # @param s [String] the string to format with ANSI color codes
28
+ # Takes a result state or status string and applies the appropriate ANSI
29
+ # color formatting using the predefined color mappings. This provides
30
+ # visual distinction for different execution outcomes in terminal output.
29
31
  #
30
- # @return [String] the formatted string with appropriate ANSI color codes
32
+ # @param s [String] the result state or status string to colorize
31
33
  #
32
- # @example Format a result state
33
- # ResultAnsi.call(Result::EXECUTING) #=> "\e[0;33;49mexecuting\e[0m"
34
+ # @return [String] the input string with ANSI color codes applied
34
35
  #
35
- # @example Format a result status
36
- # ResultAnsi.call(Result::SUCCESS) #=> "\e[0;32;49msuccess\e[0m"
36
+ # @example Colorize a success status
37
+ # ResultAnsi.call("success") #=> "\e[0;32;49msuccess\e[0m" (green)
38
+ #
39
+ # @example Colorize a failed status
40
+ # ResultAnsi.call("failed") #=> "\e[0;31;49mfailed\e[0m" (red)
41
+ #
42
+ # @example Colorize an executing state
43
+ # ResultAnsi.call("executing") #=> "\e[0;33;49mexecuting\e[0m" (yellow)
37
44
  def call(s)
38
45
  Utils::AnsiColor.call(s, color: color(s))
39
46
  end
40
47
 
41
- # Determines the appropriate ANSI color for a given state or status.
48
+ # Determines the appropriate color for a result state or status.
42
49
  #
43
- # @param s [String] the state or status string to determine color for
50
+ # Looks up the color mapping for the given state or status string,
51
+ # returning the corresponding color symbol or :default if no specific
52
+ # mapping is found.
44
53
  #
45
- # @return [Symbol] the color symbol corresponding to the state/status, or :default if not found
54
+ # @param s [String] the result state or status string to find color for
46
55
  #
47
- # @example Get color for a state
48
- # ResultAnsi.color(Result::COMPLETE) #=> :green
56
+ # @return [Symbol] the color symbol (:blue, :yellow, :green, :red, or :default)
57
+ #
58
+ # @example Get color for success status
59
+ # ResultAnsi.color("success") #=> :green
49
60
  #
50
61
  # @example Get color for unknown value
51
62
  # ResultAnsi.color("unknown") #=> :default
63
+ #
64
+ # @example Get color for executing state
65
+ # ResultAnsi.color("executing") #=> :yellow
52
66
  def color(s)
53
67
  STATE_COLORS[s] || STATUS_COLORS[s] || :default
54
68
  end