cmdx 1.0.1 → 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 +21 -0
- data/.cursor/prompts/yardoc.md +13 -0
- data/.rubocop.yml +2 -0
- data/CHANGELOG.md +29 -3
- data/README.md +2 -1
- data/docs/ai_prompts.md +269 -195
- data/docs/basics/call.md +126 -60
- 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 +382 -119
- data/docs/configuration.md +211 -49
- 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 +152 -127
- data/docs/interruptions/halt.md +134 -80
- data/docs/logging.md +183 -120
- data/docs/middlewares.md +165 -392
- 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 +251 -289
- 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 +247 -159
- data/docs/testing.md +196 -203
- data/docs/workflows.md +146 -101
- data/lib/cmdx/.DS_Store +0 -0
- data/lib/cmdx/callback.rb +39 -55
- data/lib/cmdx/callback_registry.rb +80 -73
- data/lib/cmdx/chain.rb +65 -122
- data/lib/cmdx/chain_inspector.rb +23 -116
- data/lib/cmdx/chain_serializer.rb +34 -146
- data/lib/cmdx/coercion.rb +57 -0
- data/lib/cmdx/coercion_registry.rb +113 -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 +101 -162
- data/lib/cmdx/context.rb +34 -166
- 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 +59 -154
- data/lib/cmdx/error.rb +37 -202
- data/lib/cmdx/errors.rb +153 -216
- data/lib/cmdx/fault.rb +68 -150
- data/lib/cmdx/faults.rb +26 -137
- data/lib/cmdx/immutator.rb +22 -110
- data/lib/cmdx/lazy_struct.rb +110 -186
- 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 +22 -79
- data/lib/cmdx/logger_ansi.rb +31 -72
- data/lib/cmdx/logger_serializer.rb +74 -103
- data/lib/cmdx/middleware.rb +56 -60
- data/lib/cmdx/middleware_registry.rb +82 -77
- data/lib/cmdx/middlewares/correlate.rb +41 -226
- data/lib/cmdx/middlewares/timeout.rb +46 -185
- data/lib/cmdx/parameter.rb +167 -183
- data/lib/cmdx/parameter_evaluator.rb +231 -0
- data/lib/cmdx/parameter_inspector.rb +37 -55
- data/lib/cmdx/parameter_registry.rb +65 -84
- data/lib/cmdx/parameter_serializer.rb +32 -76
- data/lib/cmdx/railtie.rb +24 -107
- data/lib/cmdx/result.rb +254 -259
- data/lib/cmdx/result_ansi.rb +28 -80
- data/lib/cmdx/result_inspector.rb +34 -70
- data/lib/cmdx/result_logger.rb +23 -77
- data/lib/cmdx/result_serializer.rb +59 -125
- 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 +336 -427
- data/lib/cmdx/task_deprecator.rb +52 -0
- data/lib/cmdx/task_processor.rb +246 -0
- data/lib/cmdx/task_serializer.rb +34 -69
- 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 +11 -63
- data/lib/cmdx/utils/name_affix.rb +21 -71
- data/lib/cmdx/validator.rb +57 -0
- data/lib/cmdx/validator_registry.rb +108 -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 +58 -330
- 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 +24 -6
- data/lib/generators/cmdx/workflow_generator.rb +41 -66
- data/lib/locales/ar.yml +0 -1
- data/lib/locales/cs.yml +0 -1
- data/lib/locales/da.yml +0 -1
- data/lib/locales/de.yml +0 -1
- data/lib/locales/el.yml +0 -1
- data/lib/locales/en.yml +0 -1
- data/lib/locales/es.yml +0 -1
- data/lib/locales/fi.yml +0 -1
- data/lib/locales/fr.yml +0 -1
- data/lib/locales/he.yml +0 -1
- data/lib/locales/hi.yml +0 -1
- data/lib/locales/it.yml +0 -1
- data/lib/locales/ja.yml +0 -1
- data/lib/locales/ko.yml +0 -1
- data/lib/locales/nl.yml +0 -1
- data/lib/locales/no.yml +0 -1
- data/lib/locales/pl.yml +0 -1
- data/lib/locales/pt.yml +0 -1
- data/lib/locales/ru.yml +0 -1
- data/lib/locales/sv.yml +0 -1
- data/lib/locales/th.yml +0 -1
- data/lib/locales/tr.yml +0 -1
- data/lib/locales/vi.yml +0 -1
- data/lib/locales/zh.yml +0 -1
- metadata +36 -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
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cmdx
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Juan Gomez
|
@@ -186,6 +186,9 @@ extensions: []
|
|
186
186
|
extra_rdoc_files: []
|
187
187
|
files:
|
188
188
|
- ".DS_Store"
|
189
|
+
- ".cursor/prompts/docs.md"
|
190
|
+
- ".cursor/prompts/rspec.md"
|
191
|
+
- ".cursor/prompts/yardoc.md"
|
189
192
|
- ".cursor/rules/cursor-instructions.mdc"
|
190
193
|
- ".rspec"
|
191
194
|
- ".rubocop.yml"
|
@@ -202,6 +205,7 @@ files:
|
|
202
205
|
- docs/basics/setup.md
|
203
206
|
- docs/callbacks.md
|
204
207
|
- docs/configuration.md
|
208
|
+
- docs/deprecation.md
|
205
209
|
- docs/getting_started.md
|
206
210
|
- docs/internationalization.md
|
207
211
|
- docs/interruptions/exceptions.md
|
@@ -227,6 +231,8 @@ files:
|
|
227
231
|
- lib/cmdx/chain.rb
|
228
232
|
- lib/cmdx/chain_inspector.rb
|
229
233
|
- lib/cmdx/chain_serializer.rb
|
234
|
+
- lib/cmdx/coercion.rb
|
235
|
+
- lib/cmdx/coercion_registry.rb
|
230
236
|
- lib/cmdx/coercions/array.rb
|
231
237
|
- lib/cmdx/coercions/big_decimal.rb
|
232
238
|
- lib/cmdx/coercions/boolean.rb
|
@@ -268,28 +274,50 @@ files:
|
|
268
274
|
- lib/cmdx/middlewares/correlate.rb
|
269
275
|
- lib/cmdx/middlewares/timeout.rb
|
270
276
|
- lib/cmdx/parameter.rb
|
277
|
+
- lib/cmdx/parameter_evaluator.rb
|
271
278
|
- lib/cmdx/parameter_inspector.rb
|
272
279
|
- lib/cmdx/parameter_registry.rb
|
273
280
|
- lib/cmdx/parameter_serializer.rb
|
274
|
-
- lib/cmdx/parameter_validator.rb
|
275
|
-
- lib/cmdx/parameter_value.rb
|
276
|
-
- lib/cmdx/parameters_inspector.rb
|
277
|
-
- lib/cmdx/parameters_serializer.rb
|
278
281
|
- lib/cmdx/railtie.rb
|
279
282
|
- lib/cmdx/result.rb
|
280
283
|
- lib/cmdx/result_ansi.rb
|
281
284
|
- lib/cmdx/result_inspector.rb
|
282
285
|
- lib/cmdx/result_logger.rb
|
283
286
|
- lib/cmdx/result_serializer.rb
|
284
|
-
- lib/cmdx/rspec/
|
285
|
-
- lib/cmdx/rspec/
|
287
|
+
- lib/cmdx/rspec/matchers.rb
|
288
|
+
- lib/cmdx/rspec/result_matchers/be_executed.rb
|
289
|
+
- lib/cmdx/rspec/result_matchers/be_failed_task.rb
|
290
|
+
- lib/cmdx/rspec/result_matchers/be_skipped_task.rb
|
291
|
+
- lib/cmdx/rspec/result_matchers/be_state_matchers.rb
|
292
|
+
- lib/cmdx/rspec/result_matchers/be_status_matchers.rb
|
293
|
+
- lib/cmdx/rspec/result_matchers/be_successful_task.rb
|
294
|
+
- lib/cmdx/rspec/result_matchers/have_bad_outcome.rb
|
295
|
+
- lib/cmdx/rspec/result_matchers/have_caused_failure.rb
|
296
|
+
- lib/cmdx/rspec/result_matchers/have_chain_index.rb
|
297
|
+
- lib/cmdx/rspec/result_matchers/have_context.rb
|
298
|
+
- lib/cmdx/rspec/result_matchers/have_empty_metadata.rb
|
299
|
+
- lib/cmdx/rspec/result_matchers/have_good_outcome.rb
|
300
|
+
- lib/cmdx/rspec/result_matchers/have_metadata.rb
|
301
|
+
- lib/cmdx/rspec/result_matchers/have_preserved_context.rb
|
302
|
+
- lib/cmdx/rspec/result_matchers/have_received_thrown_failure.rb
|
303
|
+
- lib/cmdx/rspec/result_matchers/have_runtime.rb
|
304
|
+
- lib/cmdx/rspec/result_matchers/have_thrown_failure.rb
|
305
|
+
- lib/cmdx/rspec/task_matchers/be_well_formed_task.rb
|
306
|
+
- lib/cmdx/rspec/task_matchers/have_callback.rb
|
307
|
+
- lib/cmdx/rspec/task_matchers/have_cmd_setting.rb
|
308
|
+
- lib/cmdx/rspec/task_matchers/have_executed_callbacks.rb
|
309
|
+
- lib/cmdx/rspec/task_matchers/have_middleware.rb
|
310
|
+
- lib/cmdx/rspec/task_matchers/have_parameter.rb
|
286
311
|
- lib/cmdx/task.rb
|
312
|
+
- lib/cmdx/task_deprecator.rb
|
313
|
+
- lib/cmdx/task_processor.rb
|
287
314
|
- lib/cmdx/task_serializer.rb
|
288
315
|
- lib/cmdx/utils/ansi_color.rb
|
289
316
|
- lib/cmdx/utils/log_timestamp.rb
|
290
317
|
- lib/cmdx/utils/monotonic_runtime.rb
|
291
318
|
- lib/cmdx/utils/name_affix.rb
|
292
|
-
- lib/cmdx/
|
319
|
+
- lib/cmdx/validator.rb
|
320
|
+
- lib/cmdx/validator_registry.rb
|
293
321
|
- lib/cmdx/validators/exclusion.rb
|
294
322
|
- lib/cmdx/validators/format.rb
|
295
323
|
- lib/cmdx/validators/inclusion.rb
|
@@ -1,81 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module CMDx
|
4
|
-
# Parameter validation orchestration module for CMDx tasks.
|
5
|
-
#
|
6
|
-
# The ParameterValidator module provides high-level parameter validation
|
7
|
-
# coordination for task instances. It triggers validation of all task
|
8
|
-
# parameters and handles validation failure by setting task failure state
|
9
|
-
# with appropriate error messages.
|
10
|
-
#
|
11
|
-
# @example Basic parameter validation
|
12
|
-
# class ProcessOrderTask < CMDx::Task
|
13
|
-
# required :order_id, type: :integer
|
14
|
-
# required :email, type: :string, format: { with: /@/ }
|
15
|
-
# end
|
16
|
-
#
|
17
|
-
# task = ProcessOrderTask.new
|
18
|
-
# ParameterValidator.call(task) # Validates all parameters
|
19
|
-
# # If validation fails, task.failed? => true
|
20
|
-
#
|
21
|
-
# @example Validation with error handling
|
22
|
-
# task = ProcessOrderTask.new
|
23
|
-
# ParameterValidator.call(task)
|
24
|
-
#
|
25
|
-
# if task.failed?
|
26
|
-
# puts task.result.metadata[:reason] # => "order_id is a required parameter. email is invalid"
|
27
|
-
# puts task.errors.messages # => { order_id: ["is a required parameter"], email: ["is invalid"] }
|
28
|
-
# end
|
29
|
-
#
|
30
|
-
# @example Successful validation
|
31
|
-
# task = ProcessOrderTask.call(order_id: 123, email: "user@example.com")
|
32
|
-
# # ParameterValidator runs automatically and validation passes
|
33
|
-
# task.success? # => true
|
34
|
-
#
|
35
|
-
# @see CMDx::Parameters Parameter collection validation
|
36
|
-
# @see CMDx::Parameter Individual parameter definitions
|
37
|
-
# @see CMDx::Task Task execution and parameter integration
|
38
|
-
module ParameterValidator
|
39
|
-
|
40
|
-
module_function
|
41
|
-
|
42
|
-
# Validates all parameters for a task instance.
|
43
|
-
#
|
44
|
-
# Triggers validation of all task parameters through the Parameters collection.
|
45
|
-
# If any validation errors occur, sets the task to failed state with a
|
46
|
-
# comprehensive error message and detailed error information.
|
47
|
-
#
|
48
|
-
# @param task [CMDx::Task] The task instance to validate parameters for
|
49
|
-
# @return [void]
|
50
|
-
#
|
51
|
-
# @example Validating task parameters
|
52
|
-
# task = MyTask.new
|
53
|
-
# ParameterValidator.call(task)
|
54
|
-
#
|
55
|
-
# # If validation fails:
|
56
|
-
# task.failed? # => true
|
57
|
-
# task.result.metadata[:reason] # => "Combined error messages from all failed parameters"
|
58
|
-
# task.errors.empty? # => false
|
59
|
-
#
|
60
|
-
# @example Validation success
|
61
|
-
# task = MyTask.new # with valid parameters
|
62
|
-
# ParameterValidator.call(task)
|
63
|
-
#
|
64
|
-
# task.errors.empty? # => true
|
65
|
-
# # Task continues normal execution
|
66
|
-
#
|
67
|
-
# @note This method is typically called automatically during task execution
|
68
|
-
# before the main task logic runs, ensuring parameter validation occurs
|
69
|
-
# early in the task lifecycle.
|
70
|
-
def call(task)
|
71
|
-
task.class.cmd_parameters.validate!(task)
|
72
|
-
return if task.errors.empty?
|
73
|
-
|
74
|
-
task.fail!(
|
75
|
-
reason: task.errors.full_messages.join(". "),
|
76
|
-
messages: task.errors.messages
|
77
|
-
)
|
78
|
-
end
|
79
|
-
|
80
|
-
end
|
81
|
-
end
|
data/lib/cmdx/parameter_value.rb
DELETED
@@ -1,244 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module CMDx
|
4
|
-
# Parameter value resolution and processing class for CMDx tasks.
|
5
|
-
#
|
6
|
-
# The ParameterValue class handles the complete lifecycle of parameter value
|
7
|
-
# processing including source resolution, type coercion, validation, and error
|
8
|
-
# handling. It serves as the bridge between parameter definitions and their
|
9
|
-
# actual values during task execution.
|
10
|
-
#
|
11
|
-
# @example Basic parameter value processing
|
12
|
-
# task = ProcessOrderTask.new
|
13
|
-
# parameter = Parameter.new(:order_id, klass: ProcessOrderTask, type: :integer)
|
14
|
-
# value_processor = ParameterValue.new(task, parameter)
|
15
|
-
# processed_value = value_processor.call # Resolves, coerces, and validates
|
16
|
-
#
|
17
|
-
# @example Parameter value with validation
|
18
|
-
# parameter = Parameter.new(:email, klass: Task, type: :string,
|
19
|
-
# format: { with: /@/ }, presence: true)
|
20
|
-
# value_processor = ParameterValue.new(task, parameter)
|
21
|
-
# value_processor.call # Validates email format and presence
|
22
|
-
#
|
23
|
-
# @example Parameter value with default
|
24
|
-
# parameter = Parameter.new(:priority, klass: Task, default: "normal")
|
25
|
-
# value_processor = ParameterValue.new(task, parameter)
|
26
|
-
# value_processor.call # Returns "normal" if not provided
|
27
|
-
#
|
28
|
-
# @see CMDx::Parameter Parameter definition and configuration
|
29
|
-
# @see CMDx::Coercions Type coercion modules
|
30
|
-
# @see CMDx::Validators Parameter validation modules
|
31
|
-
class ParameterValue
|
32
|
-
|
33
|
-
__cmdx_attr_delegator :parent, :method_source, :name, :options, :required?, :optional?, :type,
|
34
|
-
to: :parameter,
|
35
|
-
private: true
|
36
|
-
|
37
|
-
# @return [CMDx::Task] The task instance being processed
|
38
|
-
# @return [CMDx::Parameter] The parameter definition being processed
|
39
|
-
attr_reader :task, :parameter
|
40
|
-
|
41
|
-
# Initializes a new ParameterValue processor.
|
42
|
-
#
|
43
|
-
# Creates a parameter value processor for resolving, coercing, and validating
|
44
|
-
# a specific parameter value within the context of a task instance.
|
45
|
-
#
|
46
|
-
# @param task [CMDx::Task] The task instance containing the parameter source
|
47
|
-
# @param parameter [CMDx::Parameter] The parameter definition to process
|
48
|
-
#
|
49
|
-
# @example Creating a parameter value processor
|
50
|
-
# processor = ParameterValue.new(task_instance, parameter_definition)
|
51
|
-
def initialize(task, parameter)
|
52
|
-
@task = task
|
53
|
-
@parameter = parameter
|
54
|
-
end
|
55
|
-
|
56
|
-
# Processes the parameter value through coercion and validation.
|
57
|
-
#
|
58
|
-
# Executes the complete parameter value processing pipeline:
|
59
|
-
# 1. Resolves the raw value from the source
|
60
|
-
# 2. Applies type coercion based on parameter type
|
61
|
-
# 3. Runs all configured validations
|
62
|
-
# 4. Returns the final processed value
|
63
|
-
#
|
64
|
-
# @return [Object] The processed and validated parameter value
|
65
|
-
# @raise [CoercionError] If type coercion fails
|
66
|
-
# @raise [ValidationError] If validation fails
|
67
|
-
#
|
68
|
-
# @example Processing a simple parameter
|
69
|
-
# processor.call # => 42 (after coercion and validation)
|
70
|
-
#
|
71
|
-
# @example Processing with validation failure
|
72
|
-
# processor.call # => raises ValidationError: "is not valid"
|
73
|
-
def call
|
74
|
-
coerce!.tap { validate! }
|
75
|
-
end
|
76
|
-
|
77
|
-
private
|
78
|
-
|
79
|
-
# Checks if the parameter source method is defined on the task.
|
80
|
-
#
|
81
|
-
# @return [Boolean] true if source method exists, false otherwise
|
82
|
-
def source_defined?
|
83
|
-
task.respond_to?(method_source, true) || task.__cmdx_try(method_source)
|
84
|
-
end
|
85
|
-
|
86
|
-
# Resolves the source object that contains the parameter value.
|
87
|
-
#
|
88
|
-
# Gets the source object by calling the method_source on the task instance.
|
89
|
-
# Raises ValidationError if the source method is not defined.
|
90
|
-
#
|
91
|
-
# @return [Object] The source object containing parameter values
|
92
|
-
# @raise [ValidationError] If source method is undefined
|
93
|
-
def source
|
94
|
-
return @source if defined?(@source)
|
95
|
-
|
96
|
-
unless source_defined?
|
97
|
-
raise ValidationError, I18n.t(
|
98
|
-
"cmdx.parameters.undefined",
|
99
|
-
default: "delegates to undefined method #{method_source}",
|
100
|
-
source: method_source
|
101
|
-
)
|
102
|
-
end
|
103
|
-
|
104
|
-
@source = task.__cmdx_try(method_source)
|
105
|
-
end
|
106
|
-
|
107
|
-
# Checks if the source object has the parameter value.
|
108
|
-
#
|
109
|
-
# @return [Boolean] true if source responds to parameter name, false otherwise
|
110
|
-
def source_value?
|
111
|
-
return false if source.nil?
|
112
|
-
|
113
|
-
source.__cmdx_respond_to?(name, true)
|
114
|
-
end
|
115
|
-
|
116
|
-
# Checks if a required parameter value is missing from the source.
|
117
|
-
#
|
118
|
-
# @return [Boolean] true if required parameter is missing, false otherwise
|
119
|
-
def source_value_required?
|
120
|
-
return false if parent&.optional? && source.nil?
|
121
|
-
|
122
|
-
required? && !source_value?
|
123
|
-
end
|
124
|
-
|
125
|
-
# Resolves the raw parameter value from the source.
|
126
|
-
#
|
127
|
-
# Gets the parameter value from the source object, handling required
|
128
|
-
# parameter validation and default value resolution.
|
129
|
-
#
|
130
|
-
# @return [Object] The raw parameter value
|
131
|
-
# @raise [ValidationError] If required parameter is missing
|
132
|
-
def value
|
133
|
-
return @value if defined?(@value)
|
134
|
-
|
135
|
-
if source_value_required?
|
136
|
-
raise ValidationError, I18n.t(
|
137
|
-
"cmdx.parameters.required",
|
138
|
-
default: "is a required parameter"
|
139
|
-
)
|
140
|
-
end
|
141
|
-
|
142
|
-
@value = source.__cmdx_try(name)
|
143
|
-
return @value unless @value.nil? && options.key?(:default)
|
144
|
-
|
145
|
-
@value = task.__cmdx_yield(options[:default])
|
146
|
-
end
|
147
|
-
|
148
|
-
# Applies type coercion to the parameter value.
|
149
|
-
#
|
150
|
-
# Attempts to coerce the value to each specified type in order,
|
151
|
-
# supporting multiple type fallbacks for flexible coercion.
|
152
|
-
#
|
153
|
-
# @return [Object] The coerced parameter value
|
154
|
-
# @raise [CoercionError] If all coercion attempts fail
|
155
|
-
# @raise [UnknownCoercionError] If an unknown type is specified
|
156
|
-
def coerce!
|
157
|
-
types = Array(type)
|
158
|
-
tsize = types.size - 1
|
159
|
-
|
160
|
-
types.each_with_index do |t, i|
|
161
|
-
break case t.to_sym
|
162
|
-
when :array then Coercions::Array
|
163
|
-
when :big_decimal then Coercions::BigDecimal
|
164
|
-
when :boolean then Coercions::Boolean
|
165
|
-
when :complex then Coercions::Complex
|
166
|
-
when :date then Coercions::Date
|
167
|
-
when :datetime then Coercions::DateTime
|
168
|
-
when :float then Coercions::Float
|
169
|
-
when :hash then Coercions::Hash
|
170
|
-
when :integer then Coercions::Integer
|
171
|
-
when :rational then Coercions::Rational
|
172
|
-
when :string then Coercions::String
|
173
|
-
when :time then Coercion::Time
|
174
|
-
when :virtual then Coercions::Virtual
|
175
|
-
else raise UnknownCoercionError, "unknown coercion #{t}"
|
176
|
-
end.call(value, options)
|
177
|
-
rescue CoercionError => e
|
178
|
-
next if tsize != i
|
179
|
-
|
180
|
-
raise(e) if tsize.zero?
|
181
|
-
|
182
|
-
values = types.map(&:to_s).join(", ")
|
183
|
-
raise CoercionError, I18n.t(
|
184
|
-
"cmdx.coercions.into_any",
|
185
|
-
values:,
|
186
|
-
default: "could not coerce into one of: #{values}"
|
187
|
-
)
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
# Checks if validations should be skipped for optional missing arguments.
|
192
|
-
#
|
193
|
-
# @return [Boolean] true if validations should be skipped, false otherwise
|
194
|
-
def skip_validations_due_to_optional_missing_argument?
|
195
|
-
optional? && value.nil? && !source.nil? && !source.__cmdx_respond_to?(name, true)
|
196
|
-
end
|
197
|
-
|
198
|
-
# Checks if a specific validator should be skipped due to conditional logic.
|
199
|
-
#
|
200
|
-
# @param key [Symbol] The validator key to check
|
201
|
-
# @return [Boolean] true if validator should be skipped, false otherwise
|
202
|
-
def skip_validator_due_to_conditional?(key)
|
203
|
-
opts = options[key]
|
204
|
-
opts.is_a?(Hash) && !task.__cmdx_eval(opts)
|
205
|
-
end
|
206
|
-
|
207
|
-
# Checks if a specific validator should be skipped due to allow_nil option.
|
208
|
-
#
|
209
|
-
# @param key [Symbol] The validator key to check
|
210
|
-
# @return [Boolean] true if validator should be skipped, false otherwise
|
211
|
-
def skip_validator_due_to_allow_nil?(key)
|
212
|
-
opts = options[key]
|
213
|
-
opts.is_a?(Hash) && opts[:allow_nil] && value.nil?
|
214
|
-
end
|
215
|
-
|
216
|
-
# Runs all configured validations on the parameter value.
|
217
|
-
#
|
218
|
-
# Iterates through all validation options and applies the appropriate
|
219
|
-
# validators, respecting skip conditions for optional parameters,
|
220
|
-
# conditional validations, and allow_nil settings.
|
221
|
-
#
|
222
|
-
# @return [void]
|
223
|
-
# @raise [ValidationError] If any validation fails
|
224
|
-
def validate!
|
225
|
-
return if skip_validations_due_to_optional_missing_argument?
|
226
|
-
|
227
|
-
options.each_key do |key|
|
228
|
-
next if skip_validator_due_to_allow_nil?(key)
|
229
|
-
next if skip_validator_due_to_conditional?(key)
|
230
|
-
|
231
|
-
case key.to_sym
|
232
|
-
when :custom then Validators::Custom
|
233
|
-
when :exclusion then Validators::Exclusion
|
234
|
-
when :format then Validators::Format
|
235
|
-
when :inclusion then Validators::Inclusion
|
236
|
-
when :length then Validators::Length
|
237
|
-
when :numeric then Validators::Numeric
|
238
|
-
when :presence then Validators::Presence
|
239
|
-
end&.call(value, options)
|
240
|
-
end
|
241
|
-
end
|
242
|
-
|
243
|
-
end
|
244
|
-
end
|
@@ -1,72 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module CMDx
|
4
|
-
# Parameter collection inspection utility for generating human-readable descriptions.
|
5
|
-
#
|
6
|
-
# The ParametersInspector module provides functionality to convert collections
|
7
|
-
# of parameters into formatted, human-readable string representations. It
|
8
|
-
# coordinates with ParameterInspector to format individual parameters and
|
9
|
-
# combines them into a cohesive multi-parameter description.
|
10
|
-
#
|
11
|
-
# @example Basic parameters collection inspection
|
12
|
-
# parameter_registry = ParameterRegistry.new
|
13
|
-
# parameter_registry << Parameter.new(:user_id, klass: Task, type: :integer, required: true)
|
14
|
-
# parameter_registry << Parameter.new(:email, klass: Task, type: :string, required: false)
|
15
|
-
#
|
16
|
-
# ParametersInspector.call(parameter_registry)
|
17
|
-
# # => "Parameter: name=user_id type=integer source=context required=true options={}
|
18
|
-
# # Parameter: name=email type=string source=context required=false options={}"
|
19
|
-
#
|
20
|
-
# @example Empty parameters collection
|
21
|
-
# empty_parameter_registry = ParameterRegistry.new
|
22
|
-
# ParametersInspector.call(empty_parameter_registry)
|
23
|
-
# # => ""
|
24
|
-
#
|
25
|
-
# @example Parameters with validation options
|
26
|
-
# parameter_registry = ParameterRegistry.new
|
27
|
-
# parameter_registry << Parameter.new(:age, klass: Task, type: :integer,
|
28
|
-
# numeric: { within: 18..120 }, required: true)
|
29
|
-
# parameter_registry << Parameter.new(:website, klass: Task, type: :string,
|
30
|
-
# format: { with: /^https?:\/\// }, required: false)
|
31
|
-
#
|
32
|
-
# ParametersInspector.call(parameter_registry)
|
33
|
-
# # => "Parameter: name=age type=integer source=context required=true options={numeric: {within: 18..120}}
|
34
|
-
# # Parameter: name=website type=string source=context required=false options={format: {with: /^https?:\/\//}}"
|
35
|
-
#
|
36
|
-
# @see CMDx::ParameterRegistry Parameter collection management
|
37
|
-
# @see CMDx::ParameterInspector Individual parameter inspection
|
38
|
-
# @see CMDx::Parameter Parameter definition and configuration
|
39
|
-
module ParametersInspector
|
40
|
-
|
41
|
-
module_function
|
42
|
-
|
43
|
-
# Converts a Parameters collection to a human-readable string representation.
|
44
|
-
#
|
45
|
-
# Iterates through all parameters in the collection and formats each one
|
46
|
-
# using ParameterInspector, then joins them with newlines to create a
|
47
|
-
# comprehensive multi-parameter description.
|
48
|
-
#
|
49
|
-
# @param parameters [CMDx::ParameterRegistry] The parameters collection to inspect
|
50
|
-
# @return [String] Multi-line formatted parameter descriptions
|
51
|
-
#
|
52
|
-
# @example Inspecting multiple parameters
|
53
|
-
# ParametersInspector.call(parameters_collection)
|
54
|
-
# # => "Parameter: name=user_id type=integer source=context required=true
|
55
|
-
# # Parameter: name=email type=string source=context required=false
|
56
|
-
# # Parameter: name=age type=integer source=context required=true"
|
57
|
-
#
|
58
|
-
# @example Inspecting empty collection
|
59
|
-
# ParametersInspector.call(ParameterRegistry.new)
|
60
|
-
# # => ""
|
61
|
-
#
|
62
|
-
# @example Inspecting single parameter collection
|
63
|
-
# single_param_collection = ParameterRegistry.new
|
64
|
-
# single_param_collection << Parameter.new(:name, klass: Task)
|
65
|
-
# ParametersInspector.call(single_param_collection)
|
66
|
-
# # => "Parameter: name=name type=virtual source=context required=false options={}"
|
67
|
-
def call(parameters)
|
68
|
-
parameters.map(&:to_s).join("\n")
|
69
|
-
end
|
70
|
-
|
71
|
-
end
|
72
|
-
end
|
@@ -1,115 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module CMDx
|
4
|
-
# Parameter collection serialization utility for converting Parameters to hash arrays.
|
5
|
-
#
|
6
|
-
# The ParametersSerializer module provides functionality to serialize collections
|
7
|
-
# of Parameter instances into structured array representations. Each parameter
|
8
|
-
# in the collection is converted to its hash representation, creating a
|
9
|
-
# comprehensive data structure suitable for inspection, logging, and data interchange.
|
10
|
-
#
|
11
|
-
# @example Basic parameters collection serialization
|
12
|
-
# parameter_registry = ParameterRegistry.new
|
13
|
-
# parameter_registry << Parameter.new(:user_id, klass: Task, type: :integer, required: true)
|
14
|
-
# parameters << Parameter.new(:email, klass: Task, type: :string, required: false)
|
15
|
-
#
|
16
|
-
# ParametersSerializer.call(parameters)
|
17
|
-
# # => [
|
18
|
-
# # {
|
19
|
-
# # source: :context,
|
20
|
-
# # name: :user_id,
|
21
|
-
# # type: :integer,
|
22
|
-
# # required: true,
|
23
|
-
# # options: {},
|
24
|
-
# # children: []
|
25
|
-
# # },
|
26
|
-
# # {
|
27
|
-
# # source: :context,
|
28
|
-
# # name: :email,
|
29
|
-
# # type: :string,
|
30
|
-
# # required: false,
|
31
|
-
# # options: {},
|
32
|
-
# # children: []
|
33
|
-
# # }
|
34
|
-
# # ]
|
35
|
-
#
|
36
|
-
# @example Empty parameters collection
|
37
|
-
# empty_parameter_registry = ParameterRegistry.new
|
38
|
-
# ParametersSerializer.call(empty_parameter_registry)
|
39
|
-
# # => []
|
40
|
-
#
|
41
|
-
# @example Parameters with validation and nested structures
|
42
|
-
# parameter_registry = ParameterRegistry.new
|
43
|
-
# parameter_registry << Parameter.new(:age, klass: Task, type: :integer,
|
44
|
-
# numeric: { within: 18..120 }, required: true)
|
45
|
-
#
|
46
|
-
# address_param = Parameter.new(:address, klass: Task) do
|
47
|
-
# required :street, :city
|
48
|
-
# optional :apartment
|
49
|
-
# end
|
50
|
-
# parameter_registry << address_param
|
51
|
-
#
|
52
|
-
# ParametersSerializer.call(parameter_registry)
|
53
|
-
# # => [
|
54
|
-
# # {
|
55
|
-
# # source: :context,
|
56
|
-
# # name: :age,
|
57
|
-
# # type: :integer,
|
58
|
-
# # required: true,
|
59
|
-
# # options: { numeric: { within: 18..120 } },
|
60
|
-
# # children: []
|
61
|
-
# # },
|
62
|
-
# # {
|
63
|
-
# # source: :context,
|
64
|
-
# # name: :address,
|
65
|
-
# # type: :virtual,
|
66
|
-
# # required: false,
|
67
|
-
# # options: {},
|
68
|
-
# # children: [
|
69
|
-
# # { source: :address, name: :street, type: :virtual, required: true, options: {}, children: [] },
|
70
|
-
# # { source: :address, name: :city, type: :virtual, required: true, options: {}, children: [] },
|
71
|
-
# # { source: :address, name: :apartment, type: :virtual, required: false, options: {}, children: [] }
|
72
|
-
# # ]
|
73
|
-
# # }
|
74
|
-
# # ]
|
75
|
-
#
|
76
|
-
# @see CMDx::ParameterRegistry Parameter collection management
|
77
|
-
# @see CMDx::ParameterSerializer Individual parameter serialization
|
78
|
-
# @see CMDx::Parameter Parameter definition and configuration
|
79
|
-
module ParametersSerializer
|
80
|
-
|
81
|
-
module_function
|
82
|
-
|
83
|
-
# Converts a Parameters collection to an array of hash representations.
|
84
|
-
#
|
85
|
-
# Iterates through all parameters in the collection and converts each one
|
86
|
-
# to its hash representation using the Parameter#to_h method, which delegates
|
87
|
-
# to ParameterSerializer.
|
88
|
-
#
|
89
|
-
# @param parameters [CMDx::ParameterRegistry] The parameters collection to serialize
|
90
|
-
# @return [Array<Hash>] Array of serialized parameter data structures
|
91
|
-
#
|
92
|
-
# @example Serializing multiple parameters
|
93
|
-
# ParametersSerializer.call(parameters_collection)
|
94
|
-
# # => [
|
95
|
-
# # { source: :context, name: :user_id, type: :integer, required: true, options: {}, children: [] },
|
96
|
-
# # { source: :context, name: :email, type: :string, required: false, options: {}, children: [] }
|
97
|
-
# # ]
|
98
|
-
#
|
99
|
-
# @example Serializing empty collection
|
100
|
-
# ParametersSerializer.call(ParameterRegistry.new)
|
101
|
-
# # => []
|
102
|
-
#
|
103
|
-
# @example Serializing single parameter collection
|
104
|
-
# single_param_collection = ParameterRegistry.new
|
105
|
-
# single_param_collection << Parameter.new(:name, klass: Task, type: :string)
|
106
|
-
# ParametersSerializer.call(single_param_collection)
|
107
|
-
# # => [
|
108
|
-
# # { source: :context, name: :name, type: :string, required: false, options: {}, children: [] }
|
109
|
-
# # ]
|
110
|
-
def call(parameters)
|
111
|
-
parameters.map(&:to_h)
|
112
|
-
end
|
113
|
-
|
114
|
-
end
|
115
|
-
end
|