cmdx 1.1.2 → 1.5.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 (192) hide show
  1. checksums.yaml +4 -4
  2. data/.DS_Store +0 -0
  3. data/.cursor/prompts/docs.md +4 -1
  4. data/.cursor/prompts/llms.md +20 -0
  5. data/.cursor/prompts/rspec.md +4 -1
  6. data/.cursor/prompts/yardoc.md +3 -2
  7. data/.cursor/rules/cursor-instructions.mdc +56 -1
  8. data/.irbrc +6 -0
  9. data/.rubocop.yml +29 -18
  10. data/CHANGELOG.md +5 -133
  11. data/LLM.md +3317 -0
  12. data/README.md +68 -44
  13. data/docs/attributes/coercions.md +162 -0
  14. data/docs/attributes/defaults.md +90 -0
  15. data/docs/attributes/definitions.md +281 -0
  16. data/docs/attributes/naming.md +78 -0
  17. data/docs/attributes/validations.md +309 -0
  18. data/docs/basics/chain.md +56 -249
  19. data/docs/basics/context.md +56 -289
  20. data/docs/basics/execution.md +114 -0
  21. data/docs/basics/setup.md +37 -334
  22. data/docs/callbacks.md +89 -467
  23. data/docs/deprecation.md +91 -174
  24. data/docs/getting_started.md +212 -202
  25. data/docs/internationalization.md +11 -647
  26. data/docs/interruptions/exceptions.md +23 -198
  27. data/docs/interruptions/faults.md +71 -151
  28. data/docs/interruptions/halt.md +109 -186
  29. data/docs/logging.md +44 -256
  30. data/docs/middlewares.md +113 -426
  31. data/docs/outcomes/result.md +81 -228
  32. data/docs/outcomes/states.md +33 -221
  33. data/docs/outcomes/statuses.md +21 -311
  34. data/docs/tips_and_tricks.md +120 -70
  35. data/docs/workflows.md +99 -283
  36. data/lib/cmdx/.DS_Store +0 -0
  37. data/lib/cmdx/attribute.rb +229 -0
  38. data/lib/cmdx/attribute_registry.rb +94 -0
  39. data/lib/cmdx/attribute_value.rb +193 -0
  40. data/lib/cmdx/callback_registry.rb +69 -77
  41. data/lib/cmdx/chain.rb +56 -73
  42. data/lib/cmdx/coercion_registry.rb +52 -68
  43. data/lib/cmdx/coercions/array.rb +19 -18
  44. data/lib/cmdx/coercions/big_decimal.rb +20 -24
  45. data/lib/cmdx/coercions/boolean.rb +26 -25
  46. data/lib/cmdx/coercions/complex.rb +21 -22
  47. data/lib/cmdx/coercions/date.rb +25 -23
  48. data/lib/cmdx/coercions/date_time.rb +24 -25
  49. data/lib/cmdx/coercions/float.rb +25 -22
  50. data/lib/cmdx/coercions/hash.rb +31 -32
  51. data/lib/cmdx/coercions/integer.rb +30 -24
  52. data/lib/cmdx/coercions/rational.rb +29 -24
  53. data/lib/cmdx/coercions/string.rb +19 -22
  54. data/lib/cmdx/coercions/symbol.rb +37 -0
  55. data/lib/cmdx/coercions/time.rb +26 -25
  56. data/lib/cmdx/configuration.rb +49 -108
  57. data/lib/cmdx/context.rb +222 -44
  58. data/lib/cmdx/deprecator.rb +61 -0
  59. data/lib/cmdx/errors.rb +42 -252
  60. data/lib/cmdx/exceptions.rb +39 -0
  61. data/lib/cmdx/faults.rb +78 -39
  62. data/lib/cmdx/freezer.rb +51 -0
  63. data/lib/cmdx/identifier.rb +30 -0
  64. data/lib/cmdx/locale.rb +52 -0
  65. data/lib/cmdx/log_formatters/json.rb +21 -22
  66. data/lib/cmdx/log_formatters/key_value.rb +20 -22
  67. data/lib/cmdx/log_formatters/line.rb +15 -22
  68. data/lib/cmdx/log_formatters/logstash.rb +22 -23
  69. data/lib/cmdx/log_formatters/raw.rb +16 -22
  70. data/lib/cmdx/middleware_registry.rb +70 -74
  71. data/lib/cmdx/middlewares/correlate.rb +90 -54
  72. data/lib/cmdx/middlewares/runtime.rb +58 -0
  73. data/lib/cmdx/middlewares/timeout.rb +48 -68
  74. data/lib/cmdx/railtie.rb +12 -45
  75. data/lib/cmdx/result.rb +229 -314
  76. data/lib/cmdx/task.rb +194 -366
  77. data/lib/cmdx/utils/call.rb +49 -0
  78. data/lib/cmdx/utils/condition.rb +71 -0
  79. data/lib/cmdx/utils/format.rb +61 -0
  80. data/lib/cmdx/validator_registry.rb +63 -72
  81. data/lib/cmdx/validators/exclusion.rb +38 -67
  82. data/lib/cmdx/validators/format.rb +48 -49
  83. data/lib/cmdx/validators/inclusion.rb +43 -74
  84. data/lib/cmdx/validators/length.rb +91 -154
  85. data/lib/cmdx/validators/numeric.rb +87 -162
  86. data/lib/cmdx/validators/presence.rb +37 -50
  87. data/lib/cmdx/version.rb +1 -1
  88. data/lib/cmdx/worker.rb +178 -0
  89. data/lib/cmdx/workflow.rb +85 -81
  90. data/lib/cmdx.rb +19 -13
  91. data/lib/generators/cmdx/install_generator.rb +14 -13
  92. data/lib/generators/cmdx/task_generator.rb +25 -50
  93. data/lib/generators/cmdx/templates/install.rb +11 -46
  94. data/lib/generators/cmdx/templates/task.rb.tt +3 -2
  95. data/lib/locales/en.yml +18 -4
  96. data/src/cmdx-logo.png +0 -0
  97. metadata +32 -116
  98. data/docs/ai_prompts.md +0 -393
  99. data/docs/basics/call.md +0 -317
  100. data/docs/configuration.md +0 -344
  101. data/docs/parameters/coercions.md +0 -396
  102. data/docs/parameters/defaults.md +0 -335
  103. data/docs/parameters/definitions.md +0 -446
  104. data/docs/parameters/namespacing.md +0 -378
  105. data/docs/parameters/validations.md +0 -405
  106. data/docs/testing.md +0 -553
  107. data/lib/cmdx/callback.rb +0 -53
  108. data/lib/cmdx/chain_inspector.rb +0 -56
  109. data/lib/cmdx/chain_serializer.rb +0 -63
  110. data/lib/cmdx/coercion.rb +0 -57
  111. data/lib/cmdx/coercions/virtual.rb +0 -29
  112. data/lib/cmdx/core_ext/hash.rb +0 -83
  113. data/lib/cmdx/core_ext/module.rb +0 -98
  114. data/lib/cmdx/core_ext/object.rb +0 -125
  115. data/lib/cmdx/correlator.rb +0 -122
  116. data/lib/cmdx/error.rb +0 -67
  117. data/lib/cmdx/fault.rb +0 -140
  118. data/lib/cmdx/immutator.rb +0 -52
  119. data/lib/cmdx/lazy_struct.rb +0 -246
  120. data/lib/cmdx/log_formatters/pretty_json.rb +0 -40
  121. data/lib/cmdx/log_formatters/pretty_key_value.rb +0 -38
  122. data/lib/cmdx/log_formatters/pretty_line.rb +0 -41
  123. data/lib/cmdx/logger.rb +0 -49
  124. data/lib/cmdx/logger_ansi.rb +0 -68
  125. data/lib/cmdx/logger_serializer.rb +0 -116
  126. data/lib/cmdx/middleware.rb +0 -70
  127. data/lib/cmdx/parameter.rb +0 -312
  128. data/lib/cmdx/parameter_evaluator.rb +0 -231
  129. data/lib/cmdx/parameter_inspector.rb +0 -66
  130. data/lib/cmdx/parameter_registry.rb +0 -106
  131. data/lib/cmdx/parameter_serializer.rb +0 -59
  132. data/lib/cmdx/result_ansi.rb +0 -71
  133. data/lib/cmdx/result_inspector.rb +0 -71
  134. data/lib/cmdx/result_logger.rb +0 -59
  135. data/lib/cmdx/result_serializer.rb +0 -104
  136. data/lib/cmdx/rspec/matchers.rb +0 -28
  137. data/lib/cmdx/rspec/result_matchers/be_executed.rb +0 -42
  138. data/lib/cmdx/rspec/result_matchers/be_failed_task.rb +0 -94
  139. data/lib/cmdx/rspec/result_matchers/be_skipped_task.rb +0 -94
  140. data/lib/cmdx/rspec/result_matchers/be_state_matchers.rb +0 -59
  141. data/lib/cmdx/rspec/result_matchers/be_status_matchers.rb +0 -57
  142. data/lib/cmdx/rspec/result_matchers/be_successful_task.rb +0 -87
  143. data/lib/cmdx/rspec/result_matchers/have_bad_outcome.rb +0 -51
  144. data/lib/cmdx/rspec/result_matchers/have_caused_failure.rb +0 -58
  145. data/lib/cmdx/rspec/result_matchers/have_chain_index.rb +0 -59
  146. data/lib/cmdx/rspec/result_matchers/have_context.rb +0 -86
  147. data/lib/cmdx/rspec/result_matchers/have_empty_metadata.rb +0 -54
  148. data/lib/cmdx/rspec/result_matchers/have_good_outcome.rb +0 -52
  149. data/lib/cmdx/rspec/result_matchers/have_metadata.rb +0 -114
  150. data/lib/cmdx/rspec/result_matchers/have_preserved_context.rb +0 -66
  151. data/lib/cmdx/rspec/result_matchers/have_received_thrown_failure.rb +0 -64
  152. data/lib/cmdx/rspec/result_matchers/have_runtime.rb +0 -78
  153. data/lib/cmdx/rspec/result_matchers/have_thrown_failure.rb +0 -76
  154. data/lib/cmdx/rspec/task_matchers/be_well_formed_task.rb +0 -62
  155. data/lib/cmdx/rspec/task_matchers/have_callback.rb +0 -85
  156. data/lib/cmdx/rspec/task_matchers/have_cmd_setting.rb +0 -68
  157. data/lib/cmdx/rspec/task_matchers/have_executed_callbacks.rb +0 -92
  158. data/lib/cmdx/rspec/task_matchers/have_middleware.rb +0 -46
  159. data/lib/cmdx/rspec/task_matchers/have_parameter.rb +0 -181
  160. data/lib/cmdx/task_deprecator.rb +0 -58
  161. data/lib/cmdx/task_processor.rb +0 -246
  162. data/lib/cmdx/task_serializer.rb +0 -57
  163. data/lib/cmdx/utils/ansi_color.rb +0 -73
  164. data/lib/cmdx/utils/log_timestamp.rb +0 -36
  165. data/lib/cmdx/utils/monotonic_runtime.rb +0 -34
  166. data/lib/cmdx/utils/name_affix.rb +0 -52
  167. data/lib/cmdx/validator.rb +0 -57
  168. data/lib/generators/cmdx/templates/workflow.rb.tt +0 -7
  169. data/lib/generators/cmdx/workflow_generator.rb +0 -84
  170. data/lib/locales/ar.yml +0 -35
  171. data/lib/locales/cs.yml +0 -35
  172. data/lib/locales/da.yml +0 -35
  173. data/lib/locales/de.yml +0 -35
  174. data/lib/locales/el.yml +0 -35
  175. data/lib/locales/es.yml +0 -35
  176. data/lib/locales/fi.yml +0 -35
  177. data/lib/locales/fr.yml +0 -35
  178. data/lib/locales/he.yml +0 -35
  179. data/lib/locales/hi.yml +0 -35
  180. data/lib/locales/it.yml +0 -35
  181. data/lib/locales/ja.yml +0 -35
  182. data/lib/locales/ko.yml +0 -35
  183. data/lib/locales/nl.yml +0 -35
  184. data/lib/locales/no.yml +0 -35
  185. data/lib/locales/pl.yml +0 -35
  186. data/lib/locales/pt.yml +0 -35
  187. data/lib/locales/ru.yml +0 -35
  188. data/lib/locales/sv.yml +0 -35
  189. data/lib/locales/th.yml +0 -35
  190. data/lib/locales/tr.yml +0 -35
  191. data/lib/locales/vi.yml +0 -35
  192. data/lib/locales/zh.yml +0 -35
data/lib/cmdx/workflow.rb CHANGED
@@ -1,117 +1,121 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CMDx
4
- # Sequential task execution orchestration system for CMDx framework.
5
- #
6
- # Workflow provides declarative composition of multiple tasks into linear pipelines
7
- # with conditional execution, context propagation, and configurable halt behavior.
8
- # Workflows inherit from Task, gaining all task capabilities including callbacks,
9
- # parameter validation, result tracking, and configuration while coordinating
10
- # other tasks rather than implementing business logic directly.
11
- class Workflow < Task
4
+ # Provides workflow execution capabilities by organizing tasks into execution groups.
5
+ # Workflows allow you to define sequences of tasks that can be executed conditionally
6
+ # with breakpoint handling and context management.
7
+ module Workflow
12
8
 
13
- # Data structure containing a group of tasks and their execution options.
14
- #
15
- # @!attribute [r] tasks
16
- # @return [Array<Class>] array of Task or Workflow classes to execute
17
- # @!attribute [r] options
18
- # @return [Hash] execution options including conditional and halt configuration
19
- Group = Struct.new(:tasks, :options)
20
-
21
- class << self
9
+ module ClassMethods
22
10
 
23
- # Returns the array of workflow groups defined for this workflow class.
11
+ # Prevents redefinition of the work method to maintain workflow integrity.
24
12
  #
25
- # Each group contains tasks and their execution options. Groups are processed
26
- # sequentially during workflow execution, with each group's tasks executing
27
- # in order unless halted by a result status.
13
+ # @param method_name [Symbol] The name of the method being added
28
14
  #
29
- # @return [Array<Group>] array of workflow groups containing tasks and options
15
+ # @raise [RuntimeError] If attempting to redefine the work method
30
16
  #
31
- # @example Access workflow groups
32
- # class MyWorkflow < CMDx::Workflow
33
- # process TaskA, TaskB
34
- # process TaskC, if: :condition_met?
17
+ # @example
18
+ # class MyWorkflow
19
+ # include CMDx::Workflow
20
+ # # This would raise an error:
21
+ # # def work; end
35
22
  # end
36
- #
37
- # MyWorkflow.workflow_groups.size #=> 2
38
- # MyWorkflow.workflow_groups.first.tasks #=> [TaskA, TaskB]
39
- def workflow_groups
40
- @workflow_groups ||= []
23
+ def method_added(method_name)
24
+ raise "cannot redefine #{name}##{method_name} method" if method_name == :work
25
+
26
+ super
41
27
  end
42
28
 
43
- # Declares a group of tasks to execute sequentially with optional conditions.
44
- #
45
- # Tasks are executed in the order specified, with shared context propagated
46
- # between executions. Groups support conditional execution and configurable
47
- # halt behavior to control workflow flow based on task results.
29
+ # Returns the collection of execution groups for this workflow.
48
30
  #
49
- # @param tasks [Array<Class>] Task or Workflow classes to execute in sequence
50
- # @param options [Hash] execution configuration options
31
+ # @return [Array<ExecutionGroup>] Array of execution groups
51
32
  #
52
- # @option options [Proc, Symbol, String] :if condition that must be truthy for group execution
53
- # @option options [Proc, Symbol, String] :unless condition that must be falsy for group execution
54
- # @option options [String, Array<String>] :workflow_halt result statuses that halt workflow execution
55
- #
56
- # @return [void]
57
- #
58
- # @raise [TypeError] when tasks contain objects that are not Task or Workflow classes
59
- #
60
- # @example Declare sequential tasks
61
- # class UserRegistrationWorkflow < CMDx::Workflow
62
- # process CreateUserTask, SendWelcomeEmailTask
33
+ # @example
34
+ # class MyWorkflow
35
+ # include CMDx::Workflow
36
+ # task Task1
37
+ # task Task2
38
+ # puts execution_groups.size # => 2
63
39
  # end
40
+ def execution_groups
41
+ @execution_groups ||= []
42
+ end
43
+
44
+ # Adds multiple tasks to the workflow with optional configuration.
64
45
  #
65
- # @example Declare conditional task group
66
- # class OrderProcessingWorkflow < CMDx::Workflow
67
- # process ValidateOrderTask
68
- # process ChargePaymentTask, if: ->(workflow) { workflow.context.payment_required? }
69
- # process ShipOrderTask, unless: :digital_product?
70
- # process NotifyAdminTask, if: proc { context.admin.active? }
71
- # end
46
+ # @param tasks [Array<Class>] Array of task classes to add
47
+ # @param options [Hash] Configuration options for the task execution
48
+ # @option options [Hash] :breakpoints Breakpoints that trigger workflow interruption
49
+ # @option options [Hash] :conditions Conditional logic for task execution
72
50
  #
73
- # @example Configure halt behavior per group
74
- # class DataProcessingWorkflow < CMDx::Workflow
75
- # process LoadDataTask, ValidateDataTask, workflow_halt: %w[failed skipped]
76
- # process OptionalCleanupTask, workflow_halt: []
51
+ # @raise [TypeError] If any task is not a CMDx::Task subclass
52
+ #
53
+ # @example
54
+ # class MyWorkflow
55
+ # include CMDx::Workflow
56
+ # tasks ValidateTask, ProcessTask, NotifyTask, breakpoints: [:failure, :halt]
77
57
  # end
78
- def process(*tasks, **options)
79
- workflow_groups << Group.new(
80
- tasks.flatten.map do |task|
58
+ def tasks(*tasks, **options)
59
+ execution_groups << ExecutionGroup.new(
60
+ tasks.map do |task|
81
61
  next task if task.is_a?(Class) && (task <= Task)
82
62
 
83
- raise TypeError, "must be a Task or Workflow"
63
+ raise TypeError, "must be a CMDx::Task"
84
64
  end,
85
65
  options
86
66
  )
87
67
  end
68
+ alias task tasks
69
+
70
+ end
71
+
72
+ # Represents a group of tasks with shared execution options.
73
+ # @attr tasks [Array<Class>] Array of task classes in this group
74
+ # @attr options [Hash] Configuration options for the group
75
+ ExecutionGroup = Struct.new(:tasks, :options)
88
76
 
77
+ # Extends the including class with workflow capabilities.
78
+ #
79
+ # @param base [Class] The class including this module
80
+ #
81
+ # @example
82
+ # class MyWorkflow
83
+ # include CMDx::Workflow
84
+ # # Now has access to task, tasks, and work methods
85
+ # end
86
+ def self.included(base)
87
+ base.extend(ClassMethods)
89
88
  end
90
89
 
91
- # Each group is evaluated for conditional execution, and if the group should
92
- # execute, all tasks in the group are called in sequence. If any task returns
93
- # a status that matches the workflow halt criteria, execution is halted and
94
- # the result is thrown.
90
+ # Executes the workflow by processing each execution group sequentially.
91
+ # Tasks within each group are executed based on conditional logic and breakpoint handling.
95
92
  #
96
93
  # @return [void]
97
94
  #
98
- # @raise [Fault] if a task fails and its status matches the workflow halt criteria
95
+ # @raise [CMDx::Fault] If a breakpoint is encountered during execution
99
96
  #
100
- # @example Execute workflow
101
- # workflow = MyWorkflow.new(user_id: 123)
102
- # workflow.call
103
- def call
104
- self.class.workflow_groups.each do |group|
105
- next unless cmdx_eval(group.options)
97
+ # @example
98
+ # workflow = MyWorkflow.new
99
+ # workflow.work # Executes all tasks in the workflow
100
+ # @example
101
+ # class DataProcessingWorkflow
102
+ # include CMDx::Workflow
103
+ # task ValidateDataTask, breakpoints: [:failure]
104
+ # task ProcessDataTask, breakpoints: [:halt]
105
+ # task NotifyCompletionTask
106
+ # end
107
+ # workflow = DataProcessingWorkflow.new
108
+ # workflow.work # Stops on first breakpoint encountered
109
+ def work
110
+ self.class.execution_groups.each do |group|
111
+ next unless Utils::Condition.evaluate(self, group.options, self)
106
112
 
107
- workflow_halt = Array(
108
- group.options[:workflow_halt] ||
109
- cmd_setting(:workflow_halt)
110
- ).map(&:to_s)
113
+ breakpoints = group.options[:breakpoints] || self.class.settings[:workflow_breakpoints]
114
+ breakpoints = Array(breakpoints).map(&:to_s).uniq
111
115
 
112
116
  group.tasks.each do |task|
113
- task_result = task.call(context)
114
- next unless workflow_halt.include?(task_result.status)
117
+ task_result = task.execute(context)
118
+ next unless breakpoints.include?(task_result.status)
115
119
 
116
120
  throw!(task_result)
117
121
  end
data/lib/cmdx.rb CHANGED
@@ -2,47 +2,53 @@
2
2
 
3
3
  require "bigdecimal"
4
4
  require "date"
5
- require "i18n"
5
+ require "forwardable"
6
6
  require "json"
7
7
  require "logger"
8
- require "pp"
9
8
  require "securerandom"
9
+ require "set"
10
10
  require "time"
11
11
  require "timeout"
12
+ require "yaml"
12
13
  require "zeitwerk"
13
14
 
14
- module CMDx; end
15
+ module CMDx
16
+
17
+ extend self
18
+
19
+ def gem_path
20
+ @gem_path ||= Pathname.new(__dir__).parent
21
+ end
22
+
23
+ end
15
24
 
16
25
  # Set up Zeitwerk loader for the CMDx gem
17
26
  loader = Zeitwerk::Loader.for_gem
18
- loader.inflector.inflect("cmdx" => "CMDx")
19
- loader.ignore("#{__dir__}/cmdx/core_ext")
27
+ loader.inflector.inflect("cmdx" => "CMDx", "json" => "JSON")
20
28
  loader.ignore("#{__dir__}/cmdx/configuration")
29
+ loader.ignore("#{__dir__}/cmdx/exceptions")
21
30
  loader.ignore("#{__dir__}/cmdx/faults")
22
31
  loader.ignore("#{__dir__}/cmdx/railtie")
23
- loader.ignore("#{__dir__}/cmdx/rspec")
24
32
  loader.ignore("#{__dir__}/generators")
25
33
  loader.ignore("#{__dir__}/locales")
26
34
  loader.setup
27
35
 
28
- # Pre-load core extensions to avoid circular dependencies
29
- require_relative "cmdx/core_ext/module"
30
- require_relative "cmdx/core_ext/object"
31
- require_relative "cmdx/core_ext/hash"
32
-
33
36
  # Pre-load configuration to make module methods available
34
37
  # This is acceptable since configuration is fundamental to the framework
35
38
  require_relative "cmdx/configuration"
36
39
 
40
+ # Pre-load exceptions to make them available at the top level
41
+ # This ensures CMDx::Error and its descendants are always available
42
+ require_relative "cmdx/exceptions"
43
+
37
44
  # Pre-load fault classes to make them available at the top level
38
- # This ensures CMDx::Failed and CMDx::Skipped are always available
45
+ # This ensures CMDx::FailFault and CMDx::SkipFault are always available
39
46
  require_relative "cmdx/faults"
40
47
 
41
48
  # Conditionally load Rails components if Rails is available
42
49
  if defined?(Rails::Generators)
43
50
  require_relative "generators/cmdx/install_generator"
44
51
  require_relative "generators/cmdx/task_generator"
45
- require_relative "generators/cmdx/workflow_generator"
46
52
  end
47
53
 
48
54
  # Load the Railtie last after everything else is required so we don't
@@ -1,31 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cmdx
4
- # Rails generator for creating CMDx initializer configuration file.
4
+ # Generates CMDx initializer file for Rails applications
5
5
  #
6
- # This generator creates a new initializer file at config/initializers/cmdx.rb
7
- # with global configuration settings for the CMDx framework. The generated
8
- # initializer provides a centralized location for configuring CMDx behavior
9
- # such as logging, error handling, and default parameter settings.
6
+ # This generator creates a configuration initializer that sets up global
7
+ # CMDx settings for the Rails application. It copies a pre-configured
8
+ # initializer template to the standard Rails initializers directory.
10
9
  class InstallGenerator < Rails::Generators::Base
11
10
 
12
11
  source_root File.expand_path("templates", __dir__)
13
12
 
14
13
  desc "Creates CMDx initializer with global configuration settings"
15
14
 
16
- # Copies the CMDx initializer template to the Rails application.
15
+ # Copies the CMDx initializer template to the Rails application
17
16
  #
18
- # Creates a new initializer file at config/initializers/cmdx.rb by copying
19
- # the install.rb template. This file contains the default CMDx configuration
20
- # that can be customized for the specific application needs.
17
+ # Creates a new initializer file at `config/initializers/cmdx.rb` containing
18
+ # the default CMDx configuration settings. This allows applications to
19
+ # customize global CMDx behavior through the standard Rails configuration
20
+ # pattern.
21
21
  #
22
22
  # @return [void]
23
23
  #
24
- # @raise [Thor::Error] if the destination file cannot be created or already exists without force
25
- #
26
- # @example Generate CMDx initializer
24
+ # @example Basic usage
27
25
  # rails generate cmdx:install
28
- # # Creates config/initializers/cmdx.rb
26
+ #
27
+ # @example Custom initializer location
28
+ # generator.copy_initializer_file
29
+ # # => Creates config/initializers/cmdx.rb
29
30
  def copy_initializer_file
30
31
  copy_file("install.rb", "config/initializers/cmdx.rb")
31
32
  end
@@ -1,80 +1,55 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cmdx
4
- # Rails generator for creating CMDx task files.
4
+ # Generates CMDx task files for Rails applications
5
5
  #
6
- # This generator creates task files in the app/cmds directory with proper
7
- # class naming conventions and inheritance. It ensures task names end with
8
- # "Task" suffix and creates files in the correct location within the Rails
9
- # application structure.
6
+ # This generator creates task classes that inherit from either ApplicationTask
7
+ # (if defined) or CMDx::Task. It generates the task file in the standard
8
+ # Rails tasks directory structure.
10
9
  class TaskGenerator < Rails::Generators::NamedBase
11
10
 
12
11
  source_root File.expand_path("templates", __dir__)
13
- check_class_collision suffix: "Task"
14
12
 
15
13
  desc "Creates a task with the given NAME"
16
14
 
17
- # Creates the task file from the template.
15
+ # Copies the task template to the Rails application
18
16
  #
19
- # Generates a new task file in the app/cmds directory based on the provided
20
- # name. The file name is normalized to ensure it ends with "_task.rb" and
21
- # is placed in the appropriate subdirectory structure.
17
+ # Creates a new task file at `app/tasks/[class_path]/[file_name].rb` using
18
+ # the task template. The file is placed in the standard Rails tasks directory
19
+ # structure, maintaining proper namespacing if the task is nested.
22
20
  #
23
21
  # @return [void]
24
22
  #
25
- # @example Generate a user task
26
- # rails generate cmdx:task user
27
- # #=> Creates app/cmds/user_task.rb
23
+ # @example Basic usage
24
+ # rails generate cmdx:task UserRegistration
25
+ # # => Creates app/tasks/user_registration.rb
28
26
  #
29
- # @example Generate a nested task
30
- # rails generate cmdx:task admin/users
31
- # #=> Creates app/cmds/admin/users_task.rb
27
+ # @example Nested task
28
+ # rails generate cmdx:task Admin::UserManagement
29
+ # # => Creates app/tasks/admin/user_management.rb
32
30
  def copy_files
33
- name = file_name.sub(/_?task$/i, "")
34
- path = File.join("app/cmds", class_path, "#{name}_task.rb")
31
+ path = File.join("app/tasks", class_path, "#{file_name}.rb")
35
32
  template("task.rb.tt", path)
36
33
  end
37
34
 
38
35
  private
39
36
 
40
- # Ensures the class name ends with "Task" suffix.
37
+ # Determines the appropriate parent class name for the generated task
41
38
  #
42
- # Takes the provided class name and appends "Task" if it doesn't already
43
- # end with that suffix, ensuring consistent naming conventions across
44
- # all generated task classes.
39
+ # Attempts to use ApplicationTask if it exists in the application, otherwise
40
+ # falls back to CMDx::Task. This allows applications to define their own
41
+ # base task class while maintaining compatibility.
45
42
  #
46
- # @return [String] the class name with "Task" suffix
43
+ # @return [Class] The parent class for the generated task
47
44
  #
48
- # @example Class name without suffix
49
- # # Given name: "User"
50
- # class_name #=> "UserTask"
45
+ # @example
46
+ # parent_class_name # => ApplicationTask
51
47
  #
52
- # @example Class name with suffix
53
- # # Given name: "UserTask"
54
- # class_name #=> "UserTask"
55
- def class_name
56
- @class_name ||= super.end_with?("Task") ? super : "#{super}Task"
57
- end
58
-
59
- # Determines the parent class for the generated task.
60
- #
61
- # Attempts to use ApplicationTask as the parent class if it exists in the
62
- # application, otherwise falls back to CMDx::Task as the base class.
63
- # This allows applications to define their own base task class with
64
- # common functionality.
65
- #
66
- # @return [Class] the parent class for the generated task
67
- #
68
- # @raise [StandardError] if neither ApplicationTask nor CMDx::Task are available
69
- #
70
- # @example With ApplicationTask defined
71
- # parent_class_name #=> ApplicationTask
72
- #
73
- # @example Without ApplicationTask
74
- # parent_class_name #=> CMDx::Task
48
+ # @example Fallback behavior
49
+ # parent_class_name # => CMDx::Task
75
50
  def parent_class_name
76
51
  ApplicationTask
77
- rescue StandardError
52
+ rescue NameError
78
53
  CMDx::Task
79
54
  end
80
55
 
@@ -1,69 +1,34 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  CMDx.configure do |config|
4
- # Task halt configuration - controls when call! raises faults
4
+ # Task breakpoint configuration - controls when execute! raises faults
5
5
  # See https://github.com/drexed/cmdx/blob/main/docs/outcomes/statuses.md for more details
6
6
  #
7
7
  # Available statuses: "success", "skipped", "failed"
8
8
  # If set to an empty array, task will never halt
9
- config.task_halt = %w[failed]
9
+ config.task_breakpoints = %w[failed]
10
10
 
11
- # Workflow halt configuration - controls when workflows stop execution
11
+ # Workflow breakpoint configuration - controls when workflows stop execution
12
12
  # When a task returns these statuses, subsequent workflow tasks won't execute
13
13
  # See https://github.com/drexed/cmdx/blob/main/docs/workflow.md for more details
14
14
  #
15
15
  # Available statuses: "success", "skipped", "failed"
16
16
  # If set to an empty array, workflow will never halt
17
- config.workflow_halt = %w[failed]
17
+ config.workflow_breakpoints = %w[failed]
18
18
 
19
19
  # Logger configuration - choose from multiple formatters
20
20
  # See https://github.com/drexed/cmdx/blob/main/docs/logging.md for more details
21
21
  #
22
22
  # Available formatters:
23
- # - CMDx::LogFormatters::Line
24
- # - CMDx::LogFormatters::PrettyLine
25
23
  # - CMDx::LogFormatters::Json
26
- # - CMDx::LogFormatters::PrettyJson
27
24
  # - CMDx::LogFormatters::KeyValue
28
- # - CMDx::LogFormatters::PrettyKeyValue
25
+ # - CMDx::LogFormatters::Line
29
26
  # - CMDx::LogFormatters::Logstash
30
27
  # - CMDx::LogFormatters::Raw
31
- config.logger = Logger.new($stdout, formatter: CMDx::LogFormatters::Line.new)
32
-
33
- # Global middlewares - automatically applied to all tasks
34
- # See https://github.com/drexed/cmdx/blob/main/docs/middlewares.md for more details
35
- #
36
- # config.middlewares.use CMDx::Middlewares::Correlate
37
- # config.middlewares.use CMDx::Middlewares::Timeout, seconds: 30
38
- # config.middlewares.use CustomAuthMiddleware, if: :admin?
39
- # config.middlewares.use CustomPerfMiddleware.new(threshold: 5.0)
40
-
41
- # Global callbacks - automatically applied to all tasks
42
- # See https://github.com/drexed/cmdx/blob/main/docs/callbacks.md for more details
43
- #
44
- # config.callbacks.register :before_execution, :log_task_start
45
- # config.callbacks.register :after_execution, TrackTaskCompletion
46
- # config.callbacks.register :on_success, NotificationCallback.new(via: [:email, :slack])
47
- # config.callbacks.register :on_failure, :alert_support, if: :critical?
48
- # config.callbacks.register :on_complete, proc { |task, type|
49
- # Metrics.increment("task.#{task.class.name.underscore}.completed")
50
- # }
51
-
52
- # Global coercions - custom parameter type conversions
53
- # See https://github.com/drexed/cmdx/blob/main/docs/parameters/coercions.md for more details
54
- #
55
- # config.coercions.register :money, MoneyCoercion
56
- # config.coercions.register :tags, TagsCoercion.new
57
- # config.coercions.register :slug, proc { |value|
58
- # value.to_s.downcase.gsub(/[^a-z0-9]+/, '-').gsub(/-+/, '-').strip('-')
59
- # }
60
-
61
- # Global validators - parameter validation logic
62
- # See https://github.com/drexed/cmdx/blob/main/docs/parameters/validations.md for more details
63
- #
64
- # config.validators.register :email, EmailValidator
65
- # config.validators.register :phone, PhoneValidator.new
66
- # config.validators.register :phone, proc { |value, options|
67
- # PhoneValidator.validate(value, options)
68
- # }
28
+ config.logger = Logger.new(
29
+ $stdout,
30
+ progname: "cmdx",
31
+ formatter: CMDx::LogFormatters::Line.new,
32
+ level: Logger::INFO
33
+ )
69
34
  end
@@ -1,8 +1,9 @@
1
1
  <% module_namespacing do -%>
2
2
  class <%= class_name %> < <%= parent_class_name %>
3
3
 
4
- def call
5
- # TODO
4
+ def work
5
+ # Your logic here...
6
+ # Docs: https://github.com/drexed/cmdx
6
7
  end
7
8
 
8
9
  end
data/lib/locales/en.yml CHANGED
@@ -1,15 +1,29 @@
1
1
  en:
2
2
  cmdx:
3
+ attributes:
4
+ required: "must be accessible via the source"
5
+ undefined: "delegates to undefined method %{method}"
3
6
  coercions:
4
7
  into_a: "could not coerce into a %{type}"
5
8
  into_an: "could not coerce into an %{type}"
6
- into_any: "could not coerce into one of: %{values}"
9
+ into_any: "could not coerce into one of: %{types}"
7
10
  unknown: "unknown %{type} coercion type"
8
11
  faults:
9
12
  unspecified: "no reason given"
10
- parameters:
11
- required: "is a required parameter"
12
- undefined: "delegates to undefined method %{source}"
13
+ types:
14
+ array: "array"
15
+ big_decimal: "big decimal"
16
+ boolean: "boolean"
17
+ complex: "complex"
18
+ date_time: "date time"
19
+ date: "date"
20
+ float: "float"
21
+ hash: "hash"
22
+ integer: "integer"
23
+ rational: "rational"
24
+ string: "string"
25
+ symbol: "symbol"
26
+ time: "time"
13
27
  validators:
14
28
  exclusion:
15
29
  of: "must not be one of: %{values}"
data/src/cmdx-logo.png ADDED
Binary file