cmdx 1.0.1 → 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.
Files changed (157) hide show
  1. checksums.yaml +4 -4
  2. data/.cursor/prompts/rspec.md +20 -0
  3. data/.cursor/prompts/yardoc.md +8 -0
  4. data/.rubocop.yml +2 -0
  5. data/CHANGELOG.md +17 -2
  6. data/README.md +1 -1
  7. data/docs/basics/call.md +2 -2
  8. data/docs/basics/chain.md +1 -1
  9. data/docs/callbacks.md +3 -36
  10. data/docs/configuration.md +58 -12
  11. data/docs/interruptions/exceptions.md +1 -1
  12. data/docs/interruptions/faults.md +2 -2
  13. data/docs/logging.md +4 -4
  14. data/docs/middlewares.md +43 -43
  15. data/docs/parameters/coercions.md +49 -38
  16. data/docs/parameters/defaults.md +1 -1
  17. data/docs/parameters/validations.md +0 -39
  18. data/docs/testing.md +11 -12
  19. data/docs/workflows.md +4 -4
  20. data/lib/cmdx/.DS_Store +0 -0
  21. data/lib/cmdx/callback.rb +36 -56
  22. data/lib/cmdx/callback_registry.rb +82 -73
  23. data/lib/cmdx/chain.rb +65 -122
  24. data/lib/cmdx/chain_inspector.rb +22 -115
  25. data/lib/cmdx/chain_serializer.rb +17 -148
  26. data/lib/cmdx/coercion.rb +49 -0
  27. data/lib/cmdx/coercion_registry.rb +94 -0
  28. data/lib/cmdx/coercions/array.rb +18 -36
  29. data/lib/cmdx/coercions/big_decimal.rb +21 -33
  30. data/lib/cmdx/coercions/boolean.rb +21 -40
  31. data/lib/cmdx/coercions/complex.rb +18 -31
  32. data/lib/cmdx/coercions/date.rb +20 -39
  33. data/lib/cmdx/coercions/date_time.rb +22 -39
  34. data/lib/cmdx/coercions/float.rb +19 -32
  35. data/lib/cmdx/coercions/hash.rb +22 -41
  36. data/lib/cmdx/coercions/integer.rb +20 -33
  37. data/lib/cmdx/coercions/rational.rb +20 -32
  38. data/lib/cmdx/coercions/string.rb +23 -31
  39. data/lib/cmdx/coercions/time.rb +24 -40
  40. data/lib/cmdx/coercions/virtual.rb +14 -31
  41. data/lib/cmdx/configuration.rb +57 -171
  42. data/lib/cmdx/context.rb +22 -165
  43. data/lib/cmdx/core_ext/hash.rb +42 -67
  44. data/lib/cmdx/core_ext/module.rb +35 -79
  45. data/lib/cmdx/core_ext/object.rb +63 -98
  46. data/lib/cmdx/correlator.rb +40 -156
  47. data/lib/cmdx/error.rb +37 -202
  48. data/lib/cmdx/errors.rb +165 -202
  49. data/lib/cmdx/fault.rb +55 -158
  50. data/lib/cmdx/faults.rb +26 -137
  51. data/lib/cmdx/immutator.rb +22 -109
  52. data/lib/cmdx/lazy_struct.rb +103 -187
  53. data/lib/cmdx/log_formatters/json.rb +14 -40
  54. data/lib/cmdx/log_formatters/key_value.rb +14 -40
  55. data/lib/cmdx/log_formatters/line.rb +14 -48
  56. data/lib/cmdx/log_formatters/logstash.rb +14 -57
  57. data/lib/cmdx/log_formatters/pretty_json.rb +14 -50
  58. data/lib/cmdx/log_formatters/pretty_key_value.rb +13 -46
  59. data/lib/cmdx/log_formatters/pretty_line.rb +16 -54
  60. data/lib/cmdx/log_formatters/raw.rb +19 -49
  61. data/lib/cmdx/logger.rb +20 -82
  62. data/lib/cmdx/logger_ansi.rb +18 -75
  63. data/lib/cmdx/logger_serializer.rb +24 -114
  64. data/lib/cmdx/middleware.rb +38 -60
  65. data/lib/cmdx/middleware_registry.rb +81 -77
  66. data/lib/cmdx/middlewares/correlate.rb +41 -226
  67. data/lib/cmdx/middlewares/timeout.rb +46 -185
  68. data/lib/cmdx/parameter.rb +120 -198
  69. data/lib/cmdx/parameter_evaluator.rb +231 -0
  70. data/lib/cmdx/parameter_inspector.rb +25 -56
  71. data/lib/cmdx/parameter_registry.rb +59 -84
  72. data/lib/cmdx/parameter_serializer.rb +23 -74
  73. data/lib/cmdx/railtie.rb +24 -107
  74. data/lib/cmdx/result.rb +254 -260
  75. data/lib/cmdx/result_ansi.rb +19 -85
  76. data/lib/cmdx/result_inspector.rb +27 -68
  77. data/lib/cmdx/result_logger.rb +18 -81
  78. data/lib/cmdx/result_serializer.rb +28 -132
  79. data/lib/cmdx/rspec/matchers.rb +28 -0
  80. data/lib/cmdx/rspec/result_matchers/be_executed.rb +42 -0
  81. data/lib/cmdx/rspec/result_matchers/be_failed_task.rb +94 -0
  82. data/lib/cmdx/rspec/result_matchers/be_skipped_task.rb +94 -0
  83. data/lib/cmdx/rspec/result_matchers/be_state_matchers.rb +59 -0
  84. data/lib/cmdx/rspec/result_matchers/be_status_matchers.rb +57 -0
  85. data/lib/cmdx/rspec/result_matchers/be_successful_task.rb +87 -0
  86. data/lib/cmdx/rspec/result_matchers/have_bad_outcome.rb +51 -0
  87. data/lib/cmdx/rspec/result_matchers/have_caused_failure.rb +58 -0
  88. data/lib/cmdx/rspec/result_matchers/have_chain_index.rb +59 -0
  89. data/lib/cmdx/rspec/result_matchers/have_context.rb +86 -0
  90. data/lib/cmdx/rspec/result_matchers/have_empty_metadata.rb +54 -0
  91. data/lib/cmdx/rspec/result_matchers/have_good_outcome.rb +52 -0
  92. data/lib/cmdx/rspec/result_matchers/have_metadata.rb +114 -0
  93. data/lib/cmdx/rspec/result_matchers/have_preserved_context.rb +66 -0
  94. data/lib/cmdx/rspec/result_matchers/have_received_thrown_failure.rb +64 -0
  95. data/lib/cmdx/rspec/result_matchers/have_runtime.rb +78 -0
  96. data/lib/cmdx/rspec/result_matchers/have_thrown_failure.rb +76 -0
  97. data/lib/cmdx/rspec/task_matchers/be_well_formed_task.rb +62 -0
  98. data/lib/cmdx/rspec/task_matchers/have_callback.rb +85 -0
  99. data/lib/cmdx/rspec/task_matchers/have_cmd_setting.rb +68 -0
  100. data/lib/cmdx/rspec/task_matchers/have_executed_callbacks.rb +92 -0
  101. data/lib/cmdx/rspec/task_matchers/have_middleware.rb +46 -0
  102. data/lib/cmdx/rspec/task_matchers/have_parameter.rb +181 -0
  103. data/lib/cmdx/task.rb +213 -425
  104. data/lib/cmdx/task_deprecator.rb +55 -0
  105. data/lib/cmdx/task_processor.rb +245 -0
  106. data/lib/cmdx/task_serializer.rb +22 -70
  107. data/lib/cmdx/utils/ansi_color.rb +13 -89
  108. data/lib/cmdx/utils/log_timestamp.rb +13 -42
  109. data/lib/cmdx/utils/monotonic_runtime.rb +13 -63
  110. data/lib/cmdx/utils/name_affix.rb +21 -71
  111. data/lib/cmdx/validator.rb +48 -0
  112. data/lib/cmdx/validator_registry.rb +86 -0
  113. data/lib/cmdx/validators/exclusion.rb +55 -94
  114. data/lib/cmdx/validators/format.rb +31 -85
  115. data/lib/cmdx/validators/inclusion.rb +65 -110
  116. data/lib/cmdx/validators/length.rb +117 -133
  117. data/lib/cmdx/validators/numeric.rb +123 -130
  118. data/lib/cmdx/validators/presence.rb +38 -79
  119. data/lib/cmdx/version.rb +1 -7
  120. data/lib/cmdx/workflow.rb +46 -339
  121. data/lib/cmdx.rb +1 -1
  122. data/lib/generators/cmdx/install_generator.rb +14 -31
  123. data/lib/generators/cmdx/task_generator.rb +39 -55
  124. data/lib/generators/cmdx/templates/install.rb +24 -6
  125. data/lib/generators/cmdx/workflow_generator.rb +41 -66
  126. data/lib/locales/ar.yml +0 -1
  127. data/lib/locales/cs.yml +0 -1
  128. data/lib/locales/da.yml +0 -1
  129. data/lib/locales/de.yml +0 -1
  130. data/lib/locales/el.yml +0 -1
  131. data/lib/locales/en.yml +0 -1
  132. data/lib/locales/es.yml +0 -1
  133. data/lib/locales/fi.yml +0 -1
  134. data/lib/locales/fr.yml +0 -1
  135. data/lib/locales/he.yml +0 -1
  136. data/lib/locales/hi.yml +0 -1
  137. data/lib/locales/it.yml +0 -1
  138. data/lib/locales/ja.yml +0 -1
  139. data/lib/locales/ko.yml +0 -1
  140. data/lib/locales/nl.yml +0 -1
  141. data/lib/locales/no.yml +0 -1
  142. data/lib/locales/pl.yml +0 -1
  143. data/lib/locales/pt.yml +0 -1
  144. data/lib/locales/ru.yml +0 -1
  145. data/lib/locales/sv.yml +0 -1
  146. data/lib/locales/th.yml +0 -1
  147. data/lib/locales/tr.yml +0 -1
  148. data/lib/locales/vi.yml +0 -1
  149. data/lib/locales/zh.yml +0 -1
  150. metadata +34 -8
  151. data/lib/cmdx/parameter_validator.rb +0 -81
  152. data/lib/cmdx/parameter_value.rb +0 -244
  153. data/lib/cmdx/parameters_inspector.rb +0 -72
  154. data/lib/cmdx/parameters_serializer.rb +0 -115
  155. data/lib/cmdx/rspec/result_matchers.rb +0 -917
  156. data/lib/cmdx/rspec/task_matchers.rb +0 -570
  157. data/lib/cmdx/validators/custom.rb +0 -102
@@ -1,75 +1,44 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CMDx
4
- # Parameter inspection utility for generating human-readable parameter descriptions.
4
+ # Parameter inspection and formatting utilities for readable parameter representation.
5
5
  #
6
- # The ParameterInspector module provides functionality to convert parameter
7
- # hash representations into formatted, human-readable strings. It handles
8
- # nested parameter structures with proper indentation and ordering.
9
- #
10
- # @example Basic parameter inspection
11
- # parameter_hash = {
12
- # name: :user_id,
13
- # type: :integer,
14
- # source: :context,
15
- # required: true,
16
- # options: { numeric: { min: 1 } },
17
- # children: []
18
- # }
19
- # ParameterInspector.call(parameter_hash)
20
- # # => "Parameter: name=user_id type=integer source=context required=true options={numeric: {min: 1}}"
21
- #
22
- # @example Nested parameter inspection
23
- # nested_parameter = {
24
- # name: :address,
25
- # type: :virtual,
26
- # source: :context,
27
- # required: true,
28
- # options: {},
29
- # children: [
30
- # { name: :street, type: :string, source: :address, required: true, options: {}, children: [] }
31
- # ]
32
- # }
33
- # ParameterInspector.call(nested_parameter)
34
- # # => "Parameter: name=address type=virtual source=context required=true options={}
35
- # # ↳ Parameter: name=street type=string source=address required=true options={}"
36
- #
37
- # @see CMDx::Parameter Parameter hash serialization via to_h
38
- # @see CMDx::ParameterSerializer Parameter-to-hash conversion
6
+ # This module provides functionality to format parameter metadata into human-readable
7
+ # strings for debugging, logging, and introspection purposes. It handles nested
8
+ # parameter structures with proper indentation and displays essential parameter
9
+ # information in a structured format.
39
10
  module ParameterInspector
40
11
 
41
- # Ordered keys for consistent parameter inspection output.
42
- #
43
- # Defines the order in which parameter attributes are displayed
44
- # in the inspection string, with children handled specially.
45
12
  ORDERED_KEYS = %i[
46
13
  name type source required options children
47
14
  ].freeze
48
15
 
49
16
  module_function
50
17
 
51
- # Converts a parameter hash to a human-readable string representation.
52
- #
53
- # Formats parameter data into a structured string with proper ordering
54
- # and indentation for nested parameters. Child parameters are displayed
55
- # with increased indentation and arrow prefixes.
18
+ # Formats a parameter hash into a human-readable string representation.
56
19
  #
57
- # @param parameter [Hash] The parameter hash to inspect
58
- # @param depth [Integer] The current nesting depth for indentation (default: 1)
59
- # @return [String] Formatted parameter description
20
+ # This method converts parameter metadata into a structured string format
21
+ # that displays key parameter information in a consistent order. For parameters
22
+ # with nested children, it recursively formats child parameters with proper
23
+ # indentation to show the hierarchical structure.
60
24
  #
61
- # @example Single parameter inspection
62
- # ParameterInspector.call(param_hash)
63
- # # => "Parameter: name=user_id type=integer source=context required=true"
25
+ # @param parameter [Hash] the parameter hash to format
26
+ # @param depth [Integer] the current nesting depth for indentation (default: 1)
64
27
  #
65
- # @example Nested parameter inspection with custom depth
66
- # ParameterInspector.call(param_hash, 2)
67
- # # => "Parameter: name=address type=virtual source=context required=true
68
- # # ↳ Parameter: name=street type=string source=address required=true"
28
+ # @return [String] a formatted string representation of the parameter
69
29
  #
70
- # @example Parameter with options
71
- # ParameterInspector.call(param_with_validation)
72
- # # => "Parameter: name=email type=string source=context required=true options={format: {with: /@/}}"
30
+ # @example Format a parameter with nested children
31
+ # param = {
32
+ # name: :user, type: :hash, source: :context, required: false, options: {},
33
+ # children: [
34
+ # { name: :name, type: :string, source: :user, required: true, options: {}, children: [] },
35
+ # { name: :age, type: :integer, source: :user, required: false, options: {}, children: [] }
36
+ # ]
37
+ # }
38
+ # ParameterInspector.call(param)
39
+ # # => "Parameter: name=user type=hash source=context required=false options={}
40
+ # # ↳ Parameter: name=name type=string source=user required=true options={}
41
+ # # ↳ Parameter: name=age type=integer source=user required=false options={}"
73
42
  def call(parameter, depth = 1)
74
43
  ORDERED_KEYS.filter_map do |key|
75
44
  value = parameter[key]
@@ -1,124 +1,99 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CMDx
4
- # Parameter collection class for managing multiple parameter definitions.
4
+ # Registry for managing parameter definitions and validation within tasks.
5
5
  #
6
- # The ParameterRegistry class extends Array to provide specialized functionality for
7
- # managing collections of Parameter instances within CMDx tasks. It handles
8
- # validation coordination, serialization, and inspection of parameter groups.
9
- #
10
- # @example Basic parameter collection usage
11
- # parameter_registry = ParameterRegistry.new
12
- # parameter_registry << Parameter.new(:user_id, klass: Task, type: :integer)
13
- # parameter_registry << Parameter.new(:email, klass: Task, type: :string)
14
- # parameter_registry.valid? # => true (if all parameters are valid)
15
- #
16
- # @example Parameter collection validation
17
- # parameter_registry.validate!(task_instance) # Validates all parameters
18
- # parameter_registry.invalid? # => true if any parameter failed validation
19
- #
20
- # @example Parameter collection serialization
21
- # parameter_registry.to_h # => Array of parameter hash representations
22
- # parameter_registry.to_s # => Human-readable parameter descriptions
23
- #
24
- # @see CMDx::Parameter Individual parameter definitions
25
- # @see CMDx::Task Task parameter integration
26
- class ParameterRegistry < Array
6
+ # This registry handles the storage and validation of parameter definitions,
7
+ # including nested parameter structures and recursive validation logic.
8
+ class ParameterRegistry
27
9
 
28
- # Checks if any parameters in the collection are invalid.
10
+ # The internal array storing parameter definitions.
29
11
  #
30
- # @return [Boolean] true if any parameter has validation errors, false otherwise
12
+ # @return [Array] array containing parameter definition objects
13
+ attr_reader :registry
14
+
15
+ # Initializes a new parameter registry.
16
+ #
17
+ # @return [ParameterRegistry] a new parameter registry instance
31
18
  #
32
- # @example
33
- # parameter_registry.invalid? # => true if validation errors exist
34
- def invalid?
35
- !valid?
19
+ # @example Creating an empty registry
20
+ # ParameterRegistry.new
21
+ def initialize
22
+ @registry = []
36
23
  end
37
24
 
38
- # Checks if all parameters in the collection are valid.
25
+ # Creates a deep copy of the parameter registry.
26
+ #
27
+ # @return [ParameterRegistry] a new registry instance with duplicated parameters
28
+ #
29
+ # @example Duplicating a registry
30
+ # original = ParameterRegistry.new
31
+ # copy = original.dup
32
+ def dup
33
+ new_registry = self.class.new
34
+ new_registry.instance_variable_set(:@registry, registry.map(&:dup))
35
+ new_registry
36
+ end
37
+
38
+ # Checks if all parameters in the registry are valid.
39
39
  #
40
40
  # @return [Boolean] true if all parameters are valid, false otherwise
41
41
  #
42
- # @example
43
- # parameter_registry.valid? # => true if no validation errors exist
42
+ # @example Checking registry validity
43
+ # registry.valid?
44
+ # # => true
44
45
  def valid?
45
- all?(&:valid?)
46
+ registry.all?(&:valid?)
46
47
  end
47
48
 
48
- # Validates all parameters in the collection against a task instance.
49
+ # Validates all parameters in the registry against a task instance.
49
50
  #
50
- # Recursively validates each parameter and its children by calling the
51
- # parameter accessor methods on the task instance, which triggers
52
- # value resolution, coercion, and validation.
51
+ # @param task [Task] the task instance to validate parameters against
53
52
  #
54
- # @param task [CMDx::Task] The task instance to validate parameters against
55
53
  # @return [void]
56
54
  #
57
55
  # @example Validating parameters
58
- # task = ProcessOrderTask.new
59
- # parameter_registry.validate!(task) # Validates all parameters
60
- #
61
- # @example Validation with nested parameters
62
- # # Validates parent parameters and all nested child parameters
63
- # parameter_registry.validate!(task_with_nested_params)
56
+ # registry.validate!(task)
64
57
  def validate!(task)
65
- each { |p| recursive_validate!(task, p) }
58
+ registry.each { |p| recursive_validate!(task, p) }
66
59
  end
67
60
 
68
- # Converts the parameter collection to a hash representation.
69
- #
70
- # Serializes all parameters in the collection to their hash representations
71
- # using the ParametersSerializer.
72
- #
73
- # @return [Array<Hash>] Array of serialized parameter data
74
- #
75
- # @example
76
- # parameter_registry.to_h
77
- # # => [
78
- # # {
79
- # # source: :context,
80
- # # name: :user_id,
81
- # # type: :integer,
82
- # # required: true,
83
- # # options: {},
84
- # # children: []
85
- # # },
86
- # # { ... }
87
- # # ]
61
+ # Returns a hash representation of the registry.
62
+ #
63
+ # @return [Hash] serialized hash representation of all parameters
64
+ #
65
+ # @example Getting registry hash
66
+ # registry.to_h
67
+ # # => { name: { type: :string, required: true }, age: { type: :integer } }
88
68
  def to_h
89
- ParametersSerializer.call(self)
69
+ registry.map(&:to_h)
90
70
  end
91
- alias to_a to_h
92
71
 
93
- # Converts the parameter collection to a string representation.
94
- #
95
- # Creates a human-readable string representation of all parameters
96
- # in the collection using the ParametersInspector.
72
+ # Returns a string representation of the registry.
97
73
  #
98
- # @return [String] Multi-line parameter descriptions
74
+ # @return [String] formatted string representation of all parameters
99
75
  #
100
- # @example
101
- # parameter_registry.to_s
102
- # # => "Parameter: name=user_id type=integer source=context required=true
103
- # # Parameter: name=email type=string source=context required=false"
76
+ # @example Getting registry string
77
+ # registry.to_s
78
+ # # => "name (string, required), age (integer)"
104
79
  def to_s
105
- ParametersInspector.call(self)
80
+ registry.map(&:to_s).join("\n")
106
81
  end
107
82
 
108
83
  private
109
84
 
110
- # Recursively validates a parameter and all its children.
85
+ # Recursively validates a parameter and its children against a task.
111
86
  #
112
- # Calls the parameter accessor method on the task to trigger validation,
113
- # then recursively validates all child parameters for nested parameter
114
- # structures.
87
+ # @param task [Task] the task instance to validate against
88
+ # @param parameter [Parameter] the parameter to validate
115
89
  #
116
- # @param task [CMDx::Task] The task instance to validate against
117
- # @param parameter [CMDx::Parameter] The parameter to validate
118
90
  # @return [void]
91
+ #
92
+ # @example Recursive validation (internal use)
93
+ # recursive_validate!(task, parameter)
119
94
  def recursive_validate!(task, parameter)
120
- task.send(parameter.method_name)
121
- parameter.children.each { |cp| recursive_validate!(task, cp) }
95
+ task.send(parameter.method_name) # Make sure parameter is defined on task
96
+ parameter.children.each { |child| recursive_validate!(task, child) }
122
97
  end
123
98
 
124
99
  end
@@ -1,92 +1,41 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CMDx
4
- # Parameter serialization utility for converting Parameter objects to hash representations.
4
+ # Parameter serialization module for converting parameter objects to hash format.
5
5
  #
6
- # The ParameterSerializer module provides functionality to serialize Parameter
7
- # instances into structured hash representations suitable for inspection,
8
- # logging, debugging, and data interchange.
9
- #
10
- # @example Basic parameter serialization
11
- # parameter = Parameter.new(:user_id, klass: Task, type: :integer, required: true)
12
- # ParameterSerializer.call(parameter)
13
- # # => {
14
- # # source: :context,
15
- # # name: :user_id,
16
- # # type: :integer,
17
- # # required: true,
18
- # # options: {},
19
- # # children: []
20
- # # }
21
- #
22
- # @example Parameter with validation options
23
- # parameter = Parameter.new(:email, klass: Task, type: :string,
24
- # format: { with: /@/ }, presence: true)
25
- # ParameterSerializer.call(parameter)
26
- # # => {
27
- # # source: :context,
28
- # # name: :email,
29
- # # type: :string,
30
- # # required: false,
31
- # # options: { format: { with: /@/ }, presence: true },
32
- # # children: []
33
- # # }
34
- #
35
- # @example Nested parameter serialization
36
- # parent = Parameter.new(:address, klass: Task) do
37
- # required :street, :city
38
- # end
39
- # ParameterSerializer.call(parent)
40
- # # => {
41
- # # source: :context,
42
- # # name: :address,
43
- # # type: :virtual,
44
- # # required: false,
45
- # # options: {},
46
- # # children: [
47
- # # { source: :address, name: :street, type: :virtual, required: true, options: {}, children: [] },
48
- # # { source: :address, name: :city, type: :virtual, required: true, options: {}, children: [] }
49
- # # ]
50
- # # }
51
- #
52
- # @see CMDx::Parameter Parameter object creation and configuration
53
- # @see CMDx::ParameterInspector Human-readable parameter formatting
6
+ # This module provides functionality to serialize parameter objects into a
7
+ # standardized hash representation that includes essential metadata about
8
+ # the parameter such as its source, name, type, required status, options,
9
+ # and child parameters. The serialized format is commonly used for debugging,
10
+ # logging, and introspection purposes.
54
11
  module ParameterSerializer
55
12
 
56
13
  module_function
57
14
 
58
- # Converts a Parameter object to a hash representation.
15
+ # Serializes a parameter object into a hash representation.
59
16
  #
60
- # Serializes a Parameter instance into a structured hash containing
61
- # all relevant parameter information including source, name, type,
62
- # requirement status, options, and recursively serialized children.
17
+ # @param parameter [Parameter] the parameter object to serialize
63
18
  #
64
- # @param parameter [CMDx::Parameter] The parameter object to serialize
65
- # @return [Hash] Structured hash representation of the parameter
19
+ # @return [Hash] a hash containing the parameter's metadata
66
20
  #
67
- # @example Simple parameter serialization
68
- # param = Parameter.new(:age, klass: Task, type: :integer, required: true)
69
- # ParameterSerializer.call(param)
70
- # # => {
71
- # # source: :context,
72
- # # name: :age,
73
- # # type: :integer,
74
- # # required: true,
75
- # # options: {},
76
- # # children: []
77
- # # }
21
+ # @raise [NoMethodError] if the parameter doesn't respond to required methods
78
22
  #
79
- # @example Parameter with custom source and options
80
- # param = Parameter.new(:name, klass: Task, source: :user,
81
- # type: :string, length: { min: 2 })
23
+ # @example Serialize a parameter with nested children
24
+ # param = Parameter.new(:user, klass: MyTask, type: :hash) do
25
+ # required :name, type: :string
26
+ # optional :age, type: :integer
27
+ # end
82
28
  # ParameterSerializer.call(param)
83
29
  # # => {
84
- # # source: :user,
85
- # # name: :name,
86
- # # type: :string,
30
+ # # source: :context,
31
+ # # name: :user,
32
+ # # type: :hash,
87
33
  # # required: false,
88
- # # options: { length: { min: 2 } },
89
- # # children: []
34
+ # # options: {},
35
+ # # children: [
36
+ # # { source: :user, name: :name, type: :string, required: true, options: {}, children: [] },
37
+ # # { source: :user, name: :age, type: :integer, required: false, options: {}, children: [] }
38
+ # # ]
90
39
  # # }
91
40
  def call(parameter)
92
41
  {
data/lib/cmdx/railtie.rb CHANGED
@@ -1,102 +1,29 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CMDx
4
- ##
5
- # Railtie provides seamless integration between CMDx and Ruby on Rails applications.
6
- # It automatically configures Rails-specific features including internationalization,
7
- # autoloading paths, and directory structure conventions for CMDx tasks and workflows.
4
+ # Rails integration for CMDx framework.
8
5
  #
9
- # The Railtie handles two main integration aspects:
10
- # 1. **I18n Configuration**: Automatically loads CMDx locale files for available locales
11
- # 2. **Autoloading Setup**: Configures Rails autoloaders for CMDx command objects
12
- #
13
- # ## Directory Structure
14
- #
15
- # The Railtie expects CMDx command objects to be organized in the following structure:
16
- # ```
17
- # app/
18
- # cmds/
19
- # workflows/ # Workflow command objects
20
- # order_processing_workflow.rb
21
- # tasks/ # Task command objects
22
- # process_order_task.rb
23
- # send_email_task.rb
24
- # ```
25
- #
26
- # ## Automatic Features
27
- #
28
- # When CMDx is included in a Rails application, the Railtie automatically:
29
- # - Adds `app/cmds` to Rails autoload paths
30
- # - Configures autoloader to collapse `app/cmds/workflows` and `app/cmds/tasks` directories
31
- # - Loads appropriate locale files from CMDx gem for error messages and validations
32
- # - Reloads I18n configuration to include CMDx translations
33
- #
34
- # @example Rails application structure
35
- # # app/cmds/tasks/process_order_task.rb
36
- # class ProcessOrderTask < CMDx::Task
37
- # required :order_id, type: :integer
38
- #
39
- # def call
40
- # context.order = Order.find(order_id)
41
- # context.order.process!
42
- # end
43
- # end
44
- #
45
- # @example Using in Rails controllers
46
- # class OrdersController < ApplicationController
47
- # def process
48
- # result = ProcessOrderTask.call(order_id: params[:id])
49
- #
50
- # if result.success?
51
- # redirect_to order_path(result.context.order), notice: 'Order processed!'
52
- # else
53
- # redirect_to order_path(params[:id]), alert: result.metadata[:reason]
54
- # end
55
- # end
56
- # end
57
- #
58
- # @example I18n integration
59
- # # CMDx automatically loads locale files for validation messages
60
- # # en.yml, es.yml, etc. are automatically available
61
- # result = MyTask.call(invalid_param: nil)
62
- # result.errors.full_messages # Uses localized error messages
63
- #
64
- # @see Configuration Configuration options for Rails integration
65
- # @see Task Task base class for command objects
66
- # @see Workflow Workflow base class for multi-task operations
67
- # @since 1.0.0
6
+ # Provides Rails-specific configuration including internationalization
7
+ # locale loading and autoload path configuration for CMDx workflows and tasks.
68
8
  class Railtie < Rails::Railtie
69
9
 
70
10
  railtie_name :cmdx
71
11
 
72
- ##
73
- # Configures internationalization (I18n) for CMDx in Rails applications.
74
- # Automatically loads locale files from the CMDx gem for all configured
75
- # application locales, ensuring error messages and validations are properly localized.
12
+ # Configure internationalization locales for CMDx.
76
13
  #
77
- # This initializer:
78
- # 1. Iterates through all configured application locales
79
- # 2. Checks for corresponding CMDx locale files
80
- # 3. Adds found locale files to I18n load path
81
- # 4. Reloads I18n configuration
14
+ # Loads available locale files from the CMDx locales directory
15
+ # and adds them to the I18n load path. Only loads locales that
16
+ # are configured as available in the Rails application.
82
17
  #
83
18
  # @param app [Rails::Application] the Rails application instance
84
- # @return [void]
85
19
  #
86
- # @example Available locales
87
- # # If Rails app has config.i18n.available_locales = [:en, :es]
88
- # # This will load:
89
- # # - lib/locales/en.yml (CMDx English translations)
90
- # # - lib/locales/es.yml (CMDx Spanish translations)
20
+ # @return [void]
91
21
  #
92
- # @example Localized error messages
93
- # # With Spanish locale active
94
- # class MyTask < CMDx::Task
95
- # required :name, presence: true
96
- # end
22
+ # @raise [StandardError] if I18n reload fails
97
23
  #
98
- # result = MyTask.call(name: "")
99
- # result.errors.full_messages # Returns Spanish error messages
24
+ # @example Configure locales during Rails initialization
25
+ # # This initializer runs automatically during Rails boot
26
+ # # when CMDx is included in a Rails application
100
27
  initializer("cmdx.configure_locales") do |app|
101
28
  Array(app.config.i18n.available_locales).each do |locale|
102
29
  path = File.expand_path("../../../lib/locales/#{locale}.yml", __FILE__)
@@ -108,34 +35,24 @@ module CMDx
108
35
  I18n.reload!
109
36
  end
110
37
 
111
- ##
112
- # Configures Rails autoloading for CMDx command objects.
113
- # Sets up proper autoloading paths and directory collapsing to ensure
114
- # CMDx tasks and workflows are loaded correctly in Rails applications.
38
+ # Configure Rails autoload paths for CMDx components.
115
39
  #
116
- # This initializer:
117
- # 1. Adds `app/cmds` to Rails autoload paths
118
- # 2. Configures all autoloaders to collapse concept directories
119
- # 3. Ensures proper class name resolution for nested directories
120
- #
121
- # Directory collapsing means that files in `app/cmds/tasks/` will be loaded
122
- # as if they were directly in `app/cmds/`, allowing for better organization
123
- # without affecting class naming conventions.
40
+ # Adds the app/cmds directory to Rails autoload paths and configures
41
+ # autoloaders to collapse the workflows and tasks subdirectories.
42
+ # This enables Rails to automatically load CMDx workflows and tasks
43
+ # from the conventional directory structure.
124
44
  #
125
45
  # @param app [Rails::Application] the Rails application instance
126
- # @return [void]
127
46
  #
128
- # @example Directory structure and class loading
129
- # # File: app/cmds/tasks/process_order_task.rb
130
- # # Class: ProcessOrderTask (not Tasks::ProcessOrderTask)
47
+ # @return [void]
131
48
  #
132
- # # File: app/cmds/workflows/order_processing_workflow.rb
133
- # # Class: OrderProcessingWorkflow (not Workflows::OrderProcessingWorkflow)
49
+ # @raise [StandardError] if autoloader configuration fails
134
50
  #
135
- # @example Autoloading in action
136
- # # Rails will automatically load these classes when referenced:
137
- # ProcessOrderTask.call(order_id: 123) # Loads from app/cmds/tasks/
138
- # OrderProcessingWorkflow.call(orders: [...]) # Loads from app/cmds/workflows/
51
+ # @example Configure autoload paths during Rails initialization
52
+ # # This initializer runs automatically during Rails boot
53
+ # # Enables loading of:
54
+ # # - app/cmds/workflows/my_workflow.rb
55
+ # # - app/cmds/tasks/my_task.rb
139
56
  initializer("cmdx.configure_rails_auto_load_paths") do |app|
140
57
  app.config.autoload_paths += %w[app/cmds]
141
58