cmdx 1.0.0 → 1.1.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.
- checksums.yaml +4 -4
- data/.cursor/prompts/rspec.md +20 -0
- data/.cursor/prompts/yardoc.md +8 -0
- data/.rubocop.yml +5 -0
- data/CHANGELOG.md +101 -49
- data/README.md +2 -1
- data/docs/ai_prompts.md +10 -0
- data/docs/basics/call.md +11 -2
- data/docs/basics/chain.md +10 -1
- data/docs/basics/context.md +9 -0
- data/docs/basics/setup.md +9 -0
- data/docs/callbacks.md +14 -37
- data/docs/configuration.md +68 -27
- data/docs/getting_started.md +11 -0
- data/docs/internationalization.md +148 -0
- data/docs/interruptions/exceptions.md +10 -1
- data/docs/interruptions/faults.md +11 -2
- data/docs/interruptions/halt.md +9 -0
- data/docs/logging.md +14 -4
- data/docs/middlewares.md +53 -43
- data/docs/outcomes/result.md +9 -0
- data/docs/outcomes/states.md +9 -0
- data/docs/outcomes/statuses.md +9 -0
- data/docs/parameters/coercions.md +58 -38
- data/docs/parameters/defaults.md +10 -1
- data/docs/parameters/definitions.md +9 -0
- data/docs/parameters/namespacing.md +9 -0
- data/docs/parameters/validations.md +8 -67
- data/docs/testing.md +22 -13
- data/docs/tips_and_tricks.md +9 -0
- data/docs/workflows.md +14 -4
- data/lib/cmdx/.DS_Store +0 -0
- data/lib/cmdx/callback.rb +36 -56
- data/lib/cmdx/callback_registry.rb +82 -73
- data/lib/cmdx/chain.rb +65 -122
- data/lib/cmdx/chain_inspector.rb +22 -115
- data/lib/cmdx/chain_serializer.rb +17 -148
- data/lib/cmdx/coercion.rb +49 -0
- data/lib/cmdx/coercion_registry.rb +94 -0
- data/lib/cmdx/coercions/array.rb +18 -36
- data/lib/cmdx/coercions/big_decimal.rb +21 -33
- data/lib/cmdx/coercions/boolean.rb +21 -40
- data/lib/cmdx/coercions/complex.rb +18 -31
- data/lib/cmdx/coercions/date.rb +20 -39
- data/lib/cmdx/coercions/date_time.rb +22 -39
- data/lib/cmdx/coercions/float.rb +19 -32
- data/lib/cmdx/coercions/hash.rb +22 -41
- data/lib/cmdx/coercions/integer.rb +20 -33
- data/lib/cmdx/coercions/rational.rb +20 -32
- data/lib/cmdx/coercions/string.rb +23 -31
- data/lib/cmdx/coercions/time.rb +24 -40
- data/lib/cmdx/coercions/virtual.rb +14 -31
- data/lib/cmdx/configuration.rb +57 -171
- data/lib/cmdx/context.rb +22 -165
- data/lib/cmdx/core_ext/hash.rb +42 -67
- data/lib/cmdx/core_ext/module.rb +35 -79
- data/lib/cmdx/core_ext/object.rb +63 -98
- data/lib/cmdx/correlator.rb +40 -156
- data/lib/cmdx/error.rb +37 -202
- data/lib/cmdx/errors.rb +165 -202
- data/lib/cmdx/fault.rb +55 -158
- data/lib/cmdx/faults.rb +26 -137
- data/lib/cmdx/immutator.rb +22 -109
- data/lib/cmdx/lazy_struct.rb +103 -187
- data/lib/cmdx/log_formatters/json.rb +14 -40
- data/lib/cmdx/log_formatters/key_value.rb +14 -40
- data/lib/cmdx/log_formatters/line.rb +14 -48
- data/lib/cmdx/log_formatters/logstash.rb +14 -57
- data/lib/cmdx/log_formatters/pretty_json.rb +14 -50
- data/lib/cmdx/log_formatters/pretty_key_value.rb +13 -46
- data/lib/cmdx/log_formatters/pretty_line.rb +16 -54
- data/lib/cmdx/log_formatters/raw.rb +19 -49
- data/lib/cmdx/logger.rb +20 -82
- data/lib/cmdx/logger_ansi.rb +18 -75
- data/lib/cmdx/logger_serializer.rb +24 -114
- data/lib/cmdx/middleware.rb +38 -60
- data/lib/cmdx/middleware_registry.rb +81 -77
- data/lib/cmdx/middlewares/correlate.rb +41 -226
- data/lib/cmdx/middlewares/timeout.rb +46 -185
- data/lib/cmdx/parameter.rb +120 -198
- data/lib/cmdx/parameter_evaluator.rb +231 -0
- data/lib/cmdx/parameter_inspector.rb +25 -56
- data/lib/cmdx/parameter_registry.rb +59 -84
- data/lib/cmdx/parameter_serializer.rb +23 -74
- data/lib/cmdx/railtie.rb +24 -107
- data/lib/cmdx/result.rb +254 -260
- data/lib/cmdx/result_ansi.rb +19 -85
- data/lib/cmdx/result_inspector.rb +27 -68
- data/lib/cmdx/result_logger.rb +18 -81
- data/lib/cmdx/result_serializer.rb +28 -132
- data/lib/cmdx/rspec/matchers.rb +28 -0
- data/lib/cmdx/rspec/result_matchers/be_executed.rb +42 -0
- data/lib/cmdx/rspec/result_matchers/be_failed_task.rb +94 -0
- data/lib/cmdx/rspec/result_matchers/be_skipped_task.rb +94 -0
- data/lib/cmdx/rspec/result_matchers/be_state_matchers.rb +59 -0
- data/lib/cmdx/rspec/result_matchers/be_status_matchers.rb +57 -0
- data/lib/cmdx/rspec/result_matchers/be_successful_task.rb +87 -0
- data/lib/cmdx/rspec/result_matchers/have_bad_outcome.rb +51 -0
- data/lib/cmdx/rspec/result_matchers/have_caused_failure.rb +58 -0
- data/lib/cmdx/rspec/result_matchers/have_chain_index.rb +59 -0
- data/lib/cmdx/rspec/result_matchers/have_context.rb +86 -0
- data/lib/cmdx/rspec/result_matchers/have_empty_metadata.rb +54 -0
- data/lib/cmdx/rspec/result_matchers/have_good_outcome.rb +52 -0
- data/lib/cmdx/rspec/result_matchers/have_metadata.rb +114 -0
- data/lib/cmdx/rspec/result_matchers/have_preserved_context.rb +66 -0
- data/lib/cmdx/rspec/result_matchers/have_received_thrown_failure.rb +64 -0
- data/lib/cmdx/rspec/result_matchers/have_runtime.rb +78 -0
- data/lib/cmdx/rspec/result_matchers/have_thrown_failure.rb +76 -0
- data/lib/cmdx/rspec/task_matchers/be_well_formed_task.rb +62 -0
- data/lib/cmdx/rspec/task_matchers/have_callback.rb +85 -0
- data/lib/cmdx/rspec/task_matchers/have_cmd_setting.rb +68 -0
- data/lib/cmdx/rspec/task_matchers/have_executed_callbacks.rb +92 -0
- data/lib/cmdx/rspec/task_matchers/have_middleware.rb +46 -0
- data/lib/cmdx/rspec/task_matchers/have_parameter.rb +181 -0
- data/lib/cmdx/task.rb +213 -425
- data/lib/cmdx/task_deprecator.rb +55 -0
- data/lib/cmdx/task_processor.rb +245 -0
- data/lib/cmdx/task_serializer.rb +22 -70
- data/lib/cmdx/utils/ansi_color.rb +13 -89
- data/lib/cmdx/utils/log_timestamp.rb +13 -42
- data/lib/cmdx/utils/monotonic_runtime.rb +13 -63
- data/lib/cmdx/utils/name_affix.rb +21 -71
- data/lib/cmdx/validator.rb +48 -0
- data/lib/cmdx/validator_registry.rb +86 -0
- data/lib/cmdx/validators/exclusion.rb +55 -94
- data/lib/cmdx/validators/format.rb +31 -85
- data/lib/cmdx/validators/inclusion.rb +65 -110
- data/lib/cmdx/validators/length.rb +117 -133
- data/lib/cmdx/validators/numeric.rb +123 -130
- data/lib/cmdx/validators/presence.rb +38 -79
- data/lib/cmdx/version.rb +1 -7
- data/lib/cmdx/workflow.rb +46 -339
- data/lib/cmdx.rb +1 -1
- data/lib/generators/cmdx/install_generator.rb +14 -31
- data/lib/generators/cmdx/task_generator.rb +39 -55
- data/lib/generators/cmdx/templates/install.rb +61 -11
- data/lib/generators/cmdx/workflow_generator.rb +41 -66
- data/lib/locales/ar.yml +35 -0
- data/lib/locales/cs.yml +35 -0
- data/lib/locales/da.yml +35 -0
- data/lib/locales/de.yml +35 -0
- data/lib/locales/el.yml +35 -0
- data/lib/locales/en.yml +19 -20
- data/lib/locales/es.yml +19 -20
- data/lib/locales/fi.yml +35 -0
- data/lib/locales/fr.yml +35 -0
- data/lib/locales/he.yml +35 -0
- data/lib/locales/hi.yml +35 -0
- data/lib/locales/it.yml +35 -0
- data/lib/locales/ja.yml +35 -0
- data/lib/locales/ko.yml +35 -0
- data/lib/locales/nl.yml +35 -0
- data/lib/locales/no.yml +35 -0
- data/lib/locales/pl.yml +35 -0
- data/lib/locales/pt.yml +35 -0
- data/lib/locales/ru.yml +35 -0
- data/lib/locales/sv.yml +35 -0
- data/lib/locales/th.yml +35 -0
- data/lib/locales/tr.yml +35 -0
- data/lib/locales/vi.yml +35 -0
- data/lib/locales/zh.yml +35 -0
- metadata +57 -8
- data/lib/cmdx/parameter_validator.rb +0 -81
- data/lib/cmdx/parameter_value.rb +0 -244
- data/lib/cmdx/parameters_inspector.rb +0 -72
- data/lib/cmdx/parameters_serializer.rb +0 -115
- data/lib/cmdx/rspec/result_matchers.rb +0 -917
- data/lib/cmdx/rspec/task_matchers.rb +0 -570
- data/lib/cmdx/validators/custom.rb +0 -102
data/lib/cmdx/error.rb
CHANGED
@@ -2,224 +2,59 @@
|
|
2
2
|
|
3
3
|
module CMDx
|
4
4
|
|
5
|
-
|
6
|
-
# Base exception class for all CMDx-specific errors.
|
7
|
-
# All other CMDx exceptions inherit from this class, providing a common
|
8
|
-
# hierarchy for error handling and rescue operations.
|
5
|
+
# Base exception class for all CMDx-related errors.
|
9
6
|
#
|
10
|
-
# This
|
11
|
-
#
|
12
|
-
#
|
13
|
-
# @example Catching all CMDx errors
|
14
|
-
# begin
|
15
|
-
# ProcessOrderTask.call(invalid_params)
|
16
|
-
# rescue CMDx::Error => e
|
17
|
-
# logger.error "CMDx error occurred: #{e.message}"
|
18
|
-
# end
|
19
|
-
#
|
20
|
-
# @example Specific error handling
|
21
|
-
# begin
|
22
|
-
# ProcessOrderTask.call(order_id: "invalid")
|
23
|
-
# rescue CMDx::CoercionError => e
|
24
|
-
# # Handle type coercion failures
|
25
|
-
# rescue CMDx::ValidationError => e
|
26
|
-
# # Handle validation failures
|
27
|
-
# rescue CMDx::Error => e
|
28
|
-
# # Handle any other CMDx errors
|
29
|
-
# end
|
30
|
-
#
|
31
|
-
# @see StandardError Ruby's standard error base class
|
32
|
-
# @since 1.0.0
|
7
|
+
# This serves as the root exception class for all errors raised by the CMDx
|
8
|
+
# framework. It inherits from StandardError and provides a common base for
|
9
|
+
# handling CMDx-specific exceptions.
|
33
10
|
Error = Class.new(StandardError)
|
34
11
|
|
35
|
-
|
36
|
-
# Raised when a value cannot be coerced to the specified type.
|
37
|
-
# This exception occurs during parameter processing when type coercion fails,
|
38
|
-
# typically due to incompatible data formats or invalid input values.
|
39
|
-
#
|
40
|
-
# CoercionError is raised by the various coercion modules when they encounter
|
41
|
-
# values that cannot be converted to the target type. Each coercion module
|
42
|
-
# provides specific error messages indicating the expected type and the
|
43
|
-
# problematic value.
|
44
|
-
#
|
45
|
-
# @example Integer coercion failure
|
46
|
-
# class MyTask < CMDx::Task
|
47
|
-
# required :count, type: :integer
|
48
|
-
# end
|
49
|
-
#
|
50
|
-
# # This will raise CoercionError during parameter processing
|
51
|
-
# MyTask.call(count: "not_a_number")
|
52
|
-
# # => CMDx::CoercionError: could not coerce into an integer
|
53
|
-
#
|
54
|
-
# @example Date coercion failure
|
55
|
-
# class ScheduleTask < CMDx::Task
|
56
|
-
# required :due_date, type: :date
|
57
|
-
# end
|
58
|
-
#
|
59
|
-
# ScheduleTask.call(due_date: "invalid_date")
|
60
|
-
# # => CMDx::CoercionError: could not coerce into a date
|
12
|
+
# Raised when parameter coercion fails during task execution.
|
61
13
|
#
|
62
|
-
#
|
63
|
-
#
|
64
|
-
#
|
65
|
-
# rescue CMDx::CoercionError => e
|
66
|
-
# # Log the coercion failure and provide user-friendly message
|
67
|
-
# logger.warn "Invalid input format: #{e.message}"
|
68
|
-
# render json: { error: "Please provide a valid number" }
|
69
|
-
# end
|
70
|
-
#
|
71
|
-
# @see Parameter Parameter type definitions and coercion
|
72
|
-
# @see ParameterValue Parameter value processing and coercion
|
73
|
-
# @since 1.0.0
|
14
|
+
# This error occurs when a parameter value cannot be converted to the expected
|
15
|
+
# type using the registered coercion handlers. It indicates that the provided
|
16
|
+
# value is incompatible with the parameter's defined type.
|
74
17
|
CoercionError = Class.new(Error)
|
75
18
|
|
76
|
-
|
77
|
-
# Raised when a task class doesn't implement the required `call` method.
|
78
|
-
# This exception enforces the CMDx contract that all task classes must
|
79
|
-
# provide a `call` method containing their business logic.
|
80
|
-
#
|
81
|
-
# This error typically occurs during development when creating new task
|
82
|
-
# classes that inherit from CMDx::Task but forget to implement the
|
83
|
-
# abstract `call` method.
|
84
|
-
#
|
85
|
-
# @example Missing call method
|
86
|
-
# class IncompleteTask < CMDx::Task
|
87
|
-
# required :data, type: :string
|
88
|
-
# # Missing call method implementation
|
89
|
-
# end
|
90
|
-
#
|
91
|
-
# IncompleteTask.call(data: "test")
|
92
|
-
# # => CMDx::UndefinedCallError: call method not defined in IncompleteTask
|
19
|
+
# Raised when a deprecated task is used.
|
93
20
|
#
|
94
|
-
#
|
95
|
-
#
|
96
|
-
|
97
|
-
|
98
|
-
#
|
99
|
-
# # Business logic implementation
|
100
|
-
# context.result = process(data)
|
101
|
-
# end
|
102
|
-
# end
|
103
|
-
#
|
104
|
-
# @example Handling undefined call errors
|
105
|
-
# begin
|
106
|
-
# SomeTask.call(params)
|
107
|
-
# rescue CMDx::UndefinedCallError => e
|
108
|
-
# # This should typically only happen during development
|
109
|
-
# logger.error "Task implementation incomplete: #{e.message}"
|
110
|
-
# raise # Re-raise as this is a programming error
|
111
|
-
# end
|
21
|
+
# This error occurs when a deprecated task is called. It indicates that the
|
22
|
+
# task is no longer supported and should be replaced with a newer alternative.
|
23
|
+
DeprecationError = Class.new(Error)
|
24
|
+
|
25
|
+
# Raised when an abstract method is called without being implemented.
|
112
26
|
#
|
113
|
-
#
|
114
|
-
#
|
115
|
-
#
|
27
|
+
# This error occurs when a subclass fails to implement required abstract methods
|
28
|
+
# such as call methods in validators, callbacks, or middleware. It indicates
|
29
|
+
# incomplete implementation of required functionality.
|
116
30
|
UndefinedCallError = Class.new(Error)
|
117
31
|
|
118
|
-
|
119
|
-
# Raised when an unknown or unsupported coercion type is specified.
|
120
|
-
# This exception occurs when parameter definitions reference type coercions
|
121
|
-
# that don't exist or aren't registered in the CMDx coercion system.
|
122
|
-
#
|
123
|
-
# This error helps catch typos in type specifications and ensures that
|
124
|
-
# only supported data types are used in parameter definitions.
|
32
|
+
# Raised when attempting to use an unregistered callback.
|
125
33
|
#
|
126
|
-
#
|
127
|
-
#
|
128
|
-
#
|
129
|
-
|
130
|
-
|
131
|
-
#
|
132
|
-
# # => CMDx::UnknownCoercionError: unknown coercion unknown_type
|
133
|
-
#
|
134
|
-
# @example Common typos
|
135
|
-
# class TaskWithTypo < CMDx::Task
|
136
|
-
# required :count, type: :integr # Should be :integer
|
137
|
-
# required :flag, type: :bool # Should be :boolean
|
138
|
-
# required :data, type: :json # Should be :hash
|
139
|
-
# end
|
140
|
-
#
|
141
|
-
# @example Supported types
|
142
|
-
# class ProperTask < CMDx::Task
|
143
|
-
# required :id, type: :integer
|
144
|
-
# required :active, type: :boolean
|
145
|
-
# required :metadata, type: :hash
|
146
|
-
# required :tags, type: :array
|
147
|
-
# required :name, type: :string
|
148
|
-
# required :score, type: :float
|
149
|
-
# required :created_at, type: :date_time
|
150
|
-
# end
|
151
|
-
#
|
152
|
-
# @example Handling unknown coercion errors
|
153
|
-
# begin
|
154
|
-
# MyTask.call(params)
|
155
|
-
# rescue CMDx::UnknownCoercionError => e
|
156
|
-
# # This indicates a programming error in parameter definition
|
157
|
-
# logger.error "Invalid type specification: #{e.message}"
|
158
|
-
# raise # Re-raise as this should be fixed in code
|
159
|
-
# end
|
34
|
+
# This error occurs when trying to reference a callback that hasn't been
|
35
|
+
# registered in the callback registry. It indicates that the callback name
|
36
|
+
# is not recognized or was misspelled.
|
37
|
+
UnknownCallbackError = Class.new(Error)
|
38
|
+
|
39
|
+
# Raised when attempting to use an unregistered coercion type.
|
160
40
|
#
|
161
|
-
#
|
162
|
-
#
|
163
|
-
#
|
41
|
+
# This error occurs when trying to use a parameter type that doesn't have
|
42
|
+
# a corresponding coercion handler registered. It indicates that the specified
|
43
|
+
# type is not supported by the coercion system.
|
164
44
|
UnknownCoercionError = Class.new(Error)
|
165
45
|
|
166
|
-
|
167
|
-
# Raised when a parameter value fails validation rules.
|
168
|
-
# This exception occurs during parameter processing when values don't meet
|
169
|
-
# the specified validation criteria, such as format requirements, length
|
170
|
-
# constraints, or custom validation logic.
|
171
|
-
#
|
172
|
-
# ValidationError provides detailed feedback about why validation failed,
|
173
|
-
# helping developers and users understand what corrections are needed.
|
174
|
-
#
|
175
|
-
# @example Presence validation failure
|
176
|
-
# class CreateUserTask < CMDx::Task
|
177
|
-
# required :email, type: :string, presence: true
|
178
|
-
# end
|
179
|
-
#
|
180
|
-
# CreateUserTask.call(email: "")
|
181
|
-
# # => CMDx::ValidationError: cannot be empty
|
46
|
+
# Raised when attempting to use an unregistered validator.
|
182
47
|
#
|
183
|
-
#
|
184
|
-
#
|
185
|
-
#
|
186
|
-
|
187
|
-
|
188
|
-
#
|
189
|
-
# # => CMDx::ValidationError: is an invalid format
|
190
|
-
#
|
191
|
-
# @example Length validation failure
|
192
|
-
# class SetPasswordTask < CMDx::Task
|
193
|
-
# required :password, type: :string, length: { min: 8 }
|
194
|
-
# end
|
195
|
-
#
|
196
|
-
# SetPasswordTask.call(password: "short")
|
197
|
-
# # => CMDx::ValidationError: length must be at least 8
|
198
|
-
#
|
199
|
-
# @example Custom validation failure
|
200
|
-
# class ProcessOrderTask < CMDx::Task
|
201
|
-
# required :quantity, type: :integer, custom: -> (val) { val > 0 }
|
202
|
-
# end
|
203
|
-
#
|
204
|
-
# ProcessOrderTask.call(quantity: -1)
|
205
|
-
# # => CMDx::ValidationError: is not valid
|
206
|
-
#
|
207
|
-
# @example Handling validation errors
|
208
|
-
# begin
|
209
|
-
# CreateUserTask.call(email: "", password: "short")
|
210
|
-
# rescue CMDx::ValidationError => e
|
211
|
-
# # Provide user-friendly feedback
|
212
|
-
# render json: {
|
213
|
-
# error: "Validation failed",
|
214
|
-
# message: e.message,
|
215
|
-
# field: extract_field_from_context(e)
|
216
|
-
# }
|
217
|
-
# end
|
48
|
+
# This error occurs when trying to reference a validator that hasn't been
|
49
|
+
# registered in the validator registry. It indicates that the validator name
|
50
|
+
# is not recognized or was misspelled.
|
51
|
+
UnknownValidatorError = Class.new(Error)
|
52
|
+
|
53
|
+
# Raised when parameter validation fails during task execution.
|
218
54
|
#
|
219
|
-
#
|
220
|
-
#
|
221
|
-
#
|
222
|
-
# @since 1.0.0
|
55
|
+
# This error occurs when a parameter value doesn't meet the validation criteria
|
56
|
+
# defined by the validator. It indicates that the provided value violates
|
57
|
+
# business rules or data integrity constraints.
|
223
58
|
ValidationError = Class.new(Error)
|
224
59
|
|
225
60
|
end
|