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.
- checksums.yaml +4 -4
- data/.cursor/prompts/docs.md +9 -0
- data/.cursor/prompts/rspec.md +13 -12
- data/.cursor/prompts/yardoc.md +11 -6
- data/CHANGELOG.md +13 -2
- data/README.md +1 -0
- data/docs/ai_prompts.md +269 -195
- data/docs/basics/call.md +124 -58
- data/docs/basics/chain.md +190 -160
- data/docs/basics/context.md +242 -154
- data/docs/basics/setup.md +302 -32
- data/docs/callbacks.md +390 -94
- data/docs/configuration.md +181 -65
- data/docs/deprecation.md +245 -0
- data/docs/getting_started.md +161 -39
- data/docs/internationalization.md +590 -70
- data/docs/interruptions/exceptions.md +135 -118
- data/docs/interruptions/faults.md +150 -125
- data/docs/interruptions/halt.md +134 -80
- data/docs/logging.md +181 -118
- data/docs/middlewares.md +150 -377
- data/docs/outcomes/result.md +140 -112
- data/docs/outcomes/states.md +134 -99
- data/docs/outcomes/statuses.md +204 -146
- data/docs/parameters/coercions.md +232 -281
- data/docs/parameters/defaults.md +224 -169
- data/docs/parameters/definitions.md +289 -141
- data/docs/parameters/namespacing.md +250 -161
- data/docs/parameters/validations.md +260 -133
- data/docs/testing.md +191 -197
- data/docs/workflows.md +143 -98
- data/lib/cmdx/callback.rb +23 -19
- data/lib/cmdx/callback_registry.rb +1 -3
- data/lib/cmdx/chain_inspector.rb +23 -23
- data/lib/cmdx/chain_serializer.rb +38 -19
- data/lib/cmdx/coercion.rb +20 -12
- data/lib/cmdx/coercion_registry.rb +51 -32
- data/lib/cmdx/configuration.rb +84 -31
- data/lib/cmdx/context.rb +32 -21
- data/lib/cmdx/core_ext/hash.rb +13 -13
- data/lib/cmdx/core_ext/module.rb +1 -1
- data/lib/cmdx/core_ext/object.rb +12 -12
- data/lib/cmdx/correlator.rb +60 -39
- data/lib/cmdx/errors.rb +105 -131
- data/lib/cmdx/fault.rb +66 -45
- data/lib/cmdx/immutator.rb +20 -21
- data/lib/cmdx/lazy_struct.rb +78 -70
- data/lib/cmdx/log_formatters/json.rb +1 -1
- data/lib/cmdx/log_formatters/key_value.rb +1 -1
- data/lib/cmdx/log_formatters/line.rb +1 -1
- data/lib/cmdx/log_formatters/logstash.rb +1 -1
- data/lib/cmdx/log_formatters/pretty_json.rb +1 -1
- data/lib/cmdx/log_formatters/pretty_key_value.rb +1 -1
- data/lib/cmdx/log_formatters/pretty_line.rb +1 -1
- data/lib/cmdx/log_formatters/raw.rb +2 -2
- data/lib/cmdx/logger.rb +19 -14
- data/lib/cmdx/logger_ansi.rb +33 -17
- data/lib/cmdx/logger_serializer.rb +85 -24
- data/lib/cmdx/middleware.rb +39 -21
- data/lib/cmdx/middleware_registry.rb +4 -3
- data/lib/cmdx/parameter.rb +151 -89
- data/lib/cmdx/parameter_inspector.rb +34 -21
- data/lib/cmdx/parameter_registry.rb +36 -30
- data/lib/cmdx/parameter_serializer.rb +21 -14
- data/lib/cmdx/result.rb +136 -135
- data/lib/cmdx/result_ansi.rb +31 -17
- data/lib/cmdx/result_inspector.rb +32 -27
- data/lib/cmdx/result_logger.rb +23 -14
- data/lib/cmdx/result_serializer.rb +65 -27
- data/lib/cmdx/task.rb +234 -113
- data/lib/cmdx/task_deprecator.rb +22 -25
- data/lib/cmdx/task_processor.rb +89 -88
- data/lib/cmdx/task_serializer.rb +27 -14
- data/lib/cmdx/utils/monotonic_runtime.rb +2 -4
- data/lib/cmdx/validator.rb +25 -16
- data/lib/cmdx/validator_registry.rb +53 -31
- data/lib/cmdx/validators/exclusion.rb +1 -1
- data/lib/cmdx/validators/format.rb +2 -2
- data/lib/cmdx/validators/inclusion.rb +2 -2
- data/lib/cmdx/validators/length.rb +2 -2
- data/lib/cmdx/validators/numeric.rb +3 -3
- data/lib/cmdx/validators/presence.rb +2 -2
- data/lib/cmdx/version.rb +1 -1
- data/lib/cmdx/workflow.rb +54 -33
- data/lib/generators/cmdx/task_generator.rb +6 -6
- data/lib/generators/cmdx/workflow_generator.rb +6 -6
- 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
|
-
#
|
40
|
+
# Initializes a new result for the given task
|
41
41
|
#
|
42
|
-
# @param task [CMDx::Task] the task
|
42
|
+
# @param task [CMDx::Task] the task to create a result for
|
43
43
|
#
|
44
|
-
# @return [Result] a new
|
44
|
+
# @return [CMDx::Result] a new result instance
|
45
45
|
#
|
46
|
-
# @raise [TypeError] if task is not a Task or Workflow
|
46
|
+
# @raise [TypeError] if task is not a Task or Workflow
|
47
47
|
#
|
48
48
|
# @example Create a result for a task
|
49
|
-
#
|
50
|
-
# result
|
51
|
-
# result.
|
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?
|
67
|
+
# result.initialized? #=> true
|
68
68
|
#
|
69
69
|
# @example Check if result is executing
|
70
|
-
# result.executing?
|
70
|
+
# result.executing? #=> false
|
71
71
|
#
|
72
72
|
# @example Check if result is complete
|
73
|
-
# result.complete?
|
73
|
+
# result.complete? #=> false
|
74
74
|
#
|
75
75
|
# @example Check if result is interrupted
|
76
|
-
# result.interrupted?
|
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
|
-
#
|
106
|
+
# Marks the result as executed by transitioning to complete or interrupted state
|
107
|
+
# based on the current status
|
107
108
|
#
|
108
|
-
# @return [
|
109
|
+
# @return [void]
|
109
110
|
#
|
110
|
-
# @example
|
111
|
-
# result.
|
112
|
-
# result.
|
113
|
-
# result.complete? # => true
|
111
|
+
# @example Mark successful task as executed
|
112
|
+
# result.executed!
|
113
|
+
# result.complete? #=> true
|
114
114
|
#
|
115
|
-
# @example
|
115
|
+
# @example Mark failed task as executed
|
116
116
|
# result.fail!
|
117
|
-
# result.executed!
|
118
|
-
# result.interrupted?
|
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
|
123
|
+
# Checks if the result has been executed (either complete or interrupted)
|
124
124
|
#
|
125
|
-
# @return [Boolean] true if the result is
|
125
|
+
# @return [Boolean] true if the result is complete or interrupted
|
126
126
|
#
|
127
|
-
# @example Check
|
128
|
-
# result.executed?
|
129
|
-
# result.
|
130
|
-
# result.executed?
|
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
|
135
|
+
# Executes the provided block if the result has been executed
|
136
136
|
#
|
137
|
-
# @param block [Proc] the block to execute if result
|
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
|
144
|
-
# result.on_executed { |r| puts "Task
|
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 [
|
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?
|
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 [
|
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?
|
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
|
187
|
+
# Transitions the result to interrupted state
|
189
188
|
#
|
190
|
-
# @return [
|
189
|
+
# @return [void]
|
191
190
|
#
|
192
|
-
# @raise [RuntimeError] if
|
191
|
+
# @raise [RuntimeError] if transitioning from complete state
|
193
192
|
#
|
194
|
-
# @example Interrupt execution
|
193
|
+
# @example Interrupt task execution
|
195
194
|
# result.executing!
|
196
|
-
# result.fail!
|
197
195
|
# result.interrupt!
|
198
|
-
# result.interrupted?
|
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?
|
211
|
+
# result.success? #=> true
|
214
212
|
#
|
215
213
|
# @example Check if result is skipped
|
216
|
-
# result.skipped?
|
214
|
+
# result.skipped? #=> false
|
217
215
|
#
|
218
216
|
# @example Check if result is failed
|
219
|
-
# result.failed?
|
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
|
244
|
+
# Checks if the result has a good outcome (not failed)
|
247
245
|
#
|
248
|
-
# @return [Boolean] true if the result is
|
246
|
+
# @return [Boolean] true if the result is not failed
|
249
247
|
#
|
250
248
|
# @example Check for good outcome
|
251
|
-
# result.good?
|
249
|
+
# result.good? #=> true (initially successful)
|
252
250
|
# result.fail!
|
253
|
-
# result.good?
|
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
|
267
|
-
# result.on_good { |r| puts "Task
|
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
|
273
|
+
# Checks if the result has a bad outcome (not successful)
|
276
274
|
#
|
277
|
-
# @return [Boolean] true if the result is
|
275
|
+
# @return [Boolean] true if the result is not successful
|
278
276
|
#
|
279
277
|
# @example Check for bad outcome
|
280
|
-
# result.bad?
|
278
|
+
# result.bad? #=> false (initially successful)
|
281
279
|
# result.skip!
|
282
|
-
# result.bad?
|
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
|
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
|
302
|
+
# Transitions the result to skipped status and sets metadata
|
305
303
|
#
|
306
|
-
# @param metadata [Hash] additional metadata
|
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 [
|
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: "
|
314
|
-
# result.skipped?
|
315
|
-
# result.metadata[:reason]
|
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
|
328
|
+
# Transitions the result to failed status and sets metadata
|
328
329
|
#
|
329
|
-
# @param metadata [Hash] additional metadata
|
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 [
|
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
|
336
|
-
# result.fail!(
|
337
|
-
# result.failed?
|
338
|
-
# result.metadata[:error]
|
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
|
-
#
|
354
|
+
# Halts execution by raising a fault if the result is not successful
|
351
355
|
#
|
352
|
-
# @return [
|
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
|
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
|
-
#
|
369
|
+
# Throws the status and metadata from another result to this result
|
366
370
|
#
|
367
|
-
# @param result [Result] the result to throw
|
371
|
+
# @param result [CMDx::Result] the result to throw from
|
368
372
|
# @param local_metadata [Hash] additional metadata to merge
|
369
373
|
#
|
370
|
-
# @return [
|
374
|
+
# @return [void]
|
371
375
|
#
|
372
376
|
# @raise [TypeError] if result is not a Result instance
|
373
377
|
#
|
374
|
-
# @example Throw
|
378
|
+
# @example Throw from a failed result
|
375
379
|
# failed_result = Result.new(task)
|
376
|
-
# failed_result.fail!(
|
380
|
+
# failed_result.fail!(reason: "network timeout")
|
377
381
|
# current_result.throw!(failed_result)
|
378
|
-
# current_result.failed?
|
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
|
392
|
+
# Finds the result that originally caused a failure in the chain
|
389
393
|
#
|
390
|
-
# @return [Result, nil] the result that
|
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
|
-
#
|
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
|
404
|
+
# Checks if this result caused a failure in the chain
|
402
405
|
#
|
403
|
-
# @return [Boolean] true if this result caused the failure
|
406
|
+
# @return [Boolean] true if this result caused the failure
|
404
407
|
#
|
405
|
-
# @example Check if
|
406
|
-
# result.caused_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
|
416
|
+
# Finds the result that this failure was thrown to
|
414
417
|
#
|
415
|
-
# @return [Result, nil] the result that
|
418
|
+
# @return [CMDx::Result, nil] the result that received the thrown failure, or nil if not failed
|
416
419
|
#
|
417
|
-
# @example Find failure
|
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
|
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
|
432
|
-
# result.threw_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
|
441
|
+
# Checks if this result received a thrown failure from another result
|
440
442
|
#
|
441
|
-
# @return [Boolean] true if this
|
443
|
+
# @return [Boolean] true if this result received a thrown failure
|
442
444
|
#
|
443
|
-
# @example Check if
|
444
|
-
# result.thrown_failure?
|
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
|
-
#
|
451
|
+
# Returns the index of this result in the chain
|
450
452
|
#
|
451
|
-
# @return [Integer] the zero-based index
|
453
|
+
# @return [Integer] the zero-based index of this result
|
452
454
|
#
|
453
|
-
# @example Get result
|
454
|
-
# result.index
|
455
|
+
# @example Get result index
|
456
|
+
# result.index #=> 2
|
455
457
|
def index
|
456
458
|
chain.index(self)
|
457
459
|
end
|
458
460
|
|
459
|
-
#
|
461
|
+
# Returns the outcome of the result (state for certain cases, status otherwise)
|
460
462
|
#
|
461
|
-
# @return [String] the outcome
|
463
|
+
# @return [String] the outcome (state or status)
|
462
464
|
#
|
463
465
|
# @example Get result outcome
|
464
|
-
# result.outcome
|
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
|
473
|
+
# Gets or measures the runtime of the result
|
470
474
|
#
|
471
|
-
# @param block [Proc] optional block to measure
|
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
|
480
|
+
# result.runtime #=> 1.234
|
477
481
|
#
|
478
|
-
# @example Measure
|
479
|
-
# result.runtime { sleep 1
|
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]
|
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
|
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
|
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
|
523
|
+
# Deconstructs the result with keys for pattern matching
|
523
524
|
#
|
524
|
-
# @param keys [Array<Symbol>, nil] specific keys to
|
525
|
+
# @param keys [Array<Symbol>, nil] specific keys to include in deconstruction
|
525
526
|
#
|
526
|
-
# @return [Hash] hash
|
527
|
+
# @return [Hash] hash with requested attributes
|
527
528
|
#
|
528
|
-
# @example Pattern
|
529
|
+
# @example Pattern matching with specific keys
|
529
530
|
# case result
|
530
|
-
# in {state: "complete", good: true}
|
531
|
-
# puts "Task
|
531
|
+
# in { state: "complete", good: true }
|
532
|
+
# puts "Task finished well"
|
532
533
|
# end
|
533
534
|
def deconstruct_keys(keys)
|
534
535
|
attributes = {
|
data/lib/cmdx/result_ansi.rb
CHANGED
@@ -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
|
7
|
-
#
|
8
|
-
# It maps execution states and
|
9
|
-
# and
|
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
|
26
|
+
# Applies ANSI color formatting to a result state or status string.
|
27
27
|
#
|
28
|
-
#
|
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
|
-
# @
|
32
|
+
# @param s [String] the result state or status string to colorize
|
31
33
|
#
|
32
|
-
# @
|
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
|
36
|
-
# ResultAnsi.call(
|
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
|
48
|
+
# Determines the appropriate color for a result state or status.
|
42
49
|
#
|
43
|
-
#
|
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
|
-
# @
|
54
|
+
# @param s [String] the result state or status string to find color for
|
46
55
|
#
|
47
|
-
# @
|
48
|
-
#
|
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
|