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.
Files changed (170) hide show
  1. checksums.yaml +4 -4
  2. data/.cursor/prompts/docs.md +9 -0
  3. data/.cursor/prompts/rspec.md +21 -0
  4. data/.cursor/prompts/yardoc.md +13 -0
  5. data/.rubocop.yml +2 -0
  6. data/CHANGELOG.md +29 -3
  7. data/README.md +2 -1
  8. data/docs/ai_prompts.md +269 -195
  9. data/docs/basics/call.md +126 -60
  10. data/docs/basics/chain.md +190 -160
  11. data/docs/basics/context.md +242 -154
  12. data/docs/basics/setup.md +302 -32
  13. data/docs/callbacks.md +382 -119
  14. data/docs/configuration.md +211 -49
  15. data/docs/deprecation.md +245 -0
  16. data/docs/getting_started.md +161 -39
  17. data/docs/internationalization.md +590 -70
  18. data/docs/interruptions/exceptions.md +135 -118
  19. data/docs/interruptions/faults.md +152 -127
  20. data/docs/interruptions/halt.md +134 -80
  21. data/docs/logging.md +183 -120
  22. data/docs/middlewares.md +165 -392
  23. data/docs/outcomes/result.md +140 -112
  24. data/docs/outcomes/states.md +134 -99
  25. data/docs/outcomes/statuses.md +204 -146
  26. data/docs/parameters/coercions.md +251 -289
  27. data/docs/parameters/defaults.md +224 -169
  28. data/docs/parameters/definitions.md +289 -141
  29. data/docs/parameters/namespacing.md +250 -161
  30. data/docs/parameters/validations.md +247 -159
  31. data/docs/testing.md +196 -203
  32. data/docs/workflows.md +146 -101
  33. data/lib/cmdx/.DS_Store +0 -0
  34. data/lib/cmdx/callback.rb +39 -55
  35. data/lib/cmdx/callback_registry.rb +80 -73
  36. data/lib/cmdx/chain.rb +65 -122
  37. data/lib/cmdx/chain_inspector.rb +23 -116
  38. data/lib/cmdx/chain_serializer.rb +34 -146
  39. data/lib/cmdx/coercion.rb +57 -0
  40. data/lib/cmdx/coercion_registry.rb +113 -0
  41. data/lib/cmdx/coercions/array.rb +18 -36
  42. data/lib/cmdx/coercions/big_decimal.rb +21 -33
  43. data/lib/cmdx/coercions/boolean.rb +21 -40
  44. data/lib/cmdx/coercions/complex.rb +18 -31
  45. data/lib/cmdx/coercions/date.rb +20 -39
  46. data/lib/cmdx/coercions/date_time.rb +22 -39
  47. data/lib/cmdx/coercions/float.rb +19 -32
  48. data/lib/cmdx/coercions/hash.rb +22 -41
  49. data/lib/cmdx/coercions/integer.rb +20 -33
  50. data/lib/cmdx/coercions/rational.rb +20 -32
  51. data/lib/cmdx/coercions/string.rb +23 -31
  52. data/lib/cmdx/coercions/time.rb +24 -40
  53. data/lib/cmdx/coercions/virtual.rb +14 -31
  54. data/lib/cmdx/configuration.rb +101 -162
  55. data/lib/cmdx/context.rb +34 -166
  56. data/lib/cmdx/core_ext/hash.rb +42 -67
  57. data/lib/cmdx/core_ext/module.rb +35 -79
  58. data/lib/cmdx/core_ext/object.rb +63 -98
  59. data/lib/cmdx/correlator.rb +59 -154
  60. data/lib/cmdx/error.rb +37 -202
  61. data/lib/cmdx/errors.rb +153 -216
  62. data/lib/cmdx/fault.rb +68 -150
  63. data/lib/cmdx/faults.rb +26 -137
  64. data/lib/cmdx/immutator.rb +22 -110
  65. data/lib/cmdx/lazy_struct.rb +110 -186
  66. data/lib/cmdx/log_formatters/json.rb +14 -40
  67. data/lib/cmdx/log_formatters/key_value.rb +14 -40
  68. data/lib/cmdx/log_formatters/line.rb +14 -48
  69. data/lib/cmdx/log_formatters/logstash.rb +14 -57
  70. data/lib/cmdx/log_formatters/pretty_json.rb +14 -50
  71. data/lib/cmdx/log_formatters/pretty_key_value.rb +13 -46
  72. data/lib/cmdx/log_formatters/pretty_line.rb +16 -54
  73. data/lib/cmdx/log_formatters/raw.rb +19 -49
  74. data/lib/cmdx/logger.rb +22 -79
  75. data/lib/cmdx/logger_ansi.rb +31 -72
  76. data/lib/cmdx/logger_serializer.rb +74 -103
  77. data/lib/cmdx/middleware.rb +56 -60
  78. data/lib/cmdx/middleware_registry.rb +82 -77
  79. data/lib/cmdx/middlewares/correlate.rb +41 -226
  80. data/lib/cmdx/middlewares/timeout.rb +46 -185
  81. data/lib/cmdx/parameter.rb +167 -183
  82. data/lib/cmdx/parameter_evaluator.rb +231 -0
  83. data/lib/cmdx/parameter_inspector.rb +37 -55
  84. data/lib/cmdx/parameter_registry.rb +65 -84
  85. data/lib/cmdx/parameter_serializer.rb +32 -76
  86. data/lib/cmdx/railtie.rb +24 -107
  87. data/lib/cmdx/result.rb +254 -259
  88. data/lib/cmdx/result_ansi.rb +28 -80
  89. data/lib/cmdx/result_inspector.rb +34 -70
  90. data/lib/cmdx/result_logger.rb +23 -77
  91. data/lib/cmdx/result_serializer.rb +59 -125
  92. data/lib/cmdx/rspec/matchers.rb +28 -0
  93. data/lib/cmdx/rspec/result_matchers/be_executed.rb +42 -0
  94. data/lib/cmdx/rspec/result_matchers/be_failed_task.rb +94 -0
  95. data/lib/cmdx/rspec/result_matchers/be_skipped_task.rb +94 -0
  96. data/lib/cmdx/rspec/result_matchers/be_state_matchers.rb +59 -0
  97. data/lib/cmdx/rspec/result_matchers/be_status_matchers.rb +57 -0
  98. data/lib/cmdx/rspec/result_matchers/be_successful_task.rb +87 -0
  99. data/lib/cmdx/rspec/result_matchers/have_bad_outcome.rb +51 -0
  100. data/lib/cmdx/rspec/result_matchers/have_caused_failure.rb +58 -0
  101. data/lib/cmdx/rspec/result_matchers/have_chain_index.rb +59 -0
  102. data/lib/cmdx/rspec/result_matchers/have_context.rb +86 -0
  103. data/lib/cmdx/rspec/result_matchers/have_empty_metadata.rb +54 -0
  104. data/lib/cmdx/rspec/result_matchers/have_good_outcome.rb +52 -0
  105. data/lib/cmdx/rspec/result_matchers/have_metadata.rb +114 -0
  106. data/lib/cmdx/rspec/result_matchers/have_preserved_context.rb +66 -0
  107. data/lib/cmdx/rspec/result_matchers/have_received_thrown_failure.rb +64 -0
  108. data/lib/cmdx/rspec/result_matchers/have_runtime.rb +78 -0
  109. data/lib/cmdx/rspec/result_matchers/have_thrown_failure.rb +76 -0
  110. data/lib/cmdx/rspec/task_matchers/be_well_formed_task.rb +62 -0
  111. data/lib/cmdx/rspec/task_matchers/have_callback.rb +85 -0
  112. data/lib/cmdx/rspec/task_matchers/have_cmd_setting.rb +68 -0
  113. data/lib/cmdx/rspec/task_matchers/have_executed_callbacks.rb +92 -0
  114. data/lib/cmdx/rspec/task_matchers/have_middleware.rb +46 -0
  115. data/lib/cmdx/rspec/task_matchers/have_parameter.rb +181 -0
  116. data/lib/cmdx/task.rb +336 -427
  117. data/lib/cmdx/task_deprecator.rb +52 -0
  118. data/lib/cmdx/task_processor.rb +246 -0
  119. data/lib/cmdx/task_serializer.rb +34 -69
  120. data/lib/cmdx/utils/ansi_color.rb +13 -89
  121. data/lib/cmdx/utils/log_timestamp.rb +13 -42
  122. data/lib/cmdx/utils/monotonic_runtime.rb +11 -63
  123. data/lib/cmdx/utils/name_affix.rb +21 -71
  124. data/lib/cmdx/validator.rb +57 -0
  125. data/lib/cmdx/validator_registry.rb +108 -0
  126. data/lib/cmdx/validators/exclusion.rb +55 -94
  127. data/lib/cmdx/validators/format.rb +31 -85
  128. data/lib/cmdx/validators/inclusion.rb +65 -110
  129. data/lib/cmdx/validators/length.rb +117 -133
  130. data/lib/cmdx/validators/numeric.rb +123 -130
  131. data/lib/cmdx/validators/presence.rb +38 -79
  132. data/lib/cmdx/version.rb +1 -7
  133. data/lib/cmdx/workflow.rb +58 -330
  134. data/lib/cmdx.rb +1 -1
  135. data/lib/generators/cmdx/install_generator.rb +14 -31
  136. data/lib/generators/cmdx/task_generator.rb +39 -55
  137. data/lib/generators/cmdx/templates/install.rb +24 -6
  138. data/lib/generators/cmdx/workflow_generator.rb +41 -66
  139. data/lib/locales/ar.yml +0 -1
  140. data/lib/locales/cs.yml +0 -1
  141. data/lib/locales/da.yml +0 -1
  142. data/lib/locales/de.yml +0 -1
  143. data/lib/locales/el.yml +0 -1
  144. data/lib/locales/en.yml +0 -1
  145. data/lib/locales/es.yml +0 -1
  146. data/lib/locales/fi.yml +0 -1
  147. data/lib/locales/fr.yml +0 -1
  148. data/lib/locales/he.yml +0 -1
  149. data/lib/locales/hi.yml +0 -1
  150. data/lib/locales/it.yml +0 -1
  151. data/lib/locales/ja.yml +0 -1
  152. data/lib/locales/ko.yml +0 -1
  153. data/lib/locales/nl.yml +0 -1
  154. data/lib/locales/no.yml +0 -1
  155. data/lib/locales/pl.yml +0 -1
  156. data/lib/locales/pt.yml +0 -1
  157. data/lib/locales/ru.yml +0 -1
  158. data/lib/locales/sv.yml +0 -1
  159. data/lib/locales/th.yml +0 -1
  160. data/lib/locales/tr.yml +0 -1
  161. data/lib/locales/vi.yml +0 -1
  162. data/lib/locales/zh.yml +0 -1
  163. metadata +36 -8
  164. data/lib/cmdx/parameter_validator.rb +0 -81
  165. data/lib/cmdx/parameter_value.rb +0 -244
  166. data/lib/cmdx/parameters_inspector.rb +0 -72
  167. data/lib/cmdx/parameters_serializer.rb +0 -115
  168. data/lib/cmdx/rspec/result_matchers.rb +0 -917
  169. data/lib/cmdx/rspec/task_matchers.rb +0 -570
  170. data/lib/cmdx/validators/custom.rb +0 -102
@@ -1,48 +1,31 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cmdx
4
- ##
5
- # Rails generator for creating CMDx initializer configuration.
4
+ # Rails generator for creating CMDx initializer configuration file.
6
5
  #
7
- # This generator creates a configuration initializer file that sets up
8
- # global CMDx settings for task execution, workflow processing, logging,
9
- # and error handling behaviors.
10
- #
11
- # The generated initializer provides sensible defaults that can be
12
- # customized for specific application requirements.
13
- #
14
- # @example Generate CMDx initializer
15
- # rails generate cmdx:install
16
- #
17
- # @example Generated file location
18
- # config/initializers/cmdx.rb
19
- #
20
- # @since 1.0.0
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.
21
10
  class InstallGenerator < Rails::Generators::Base
22
11
 
23
12
  source_root File.expand_path("templates", __dir__)
24
13
 
25
14
  desc "Creates CMDx initializer with global configuration settings"
26
15
 
27
- ##
28
- # Copies the CMDx configuration template to the Rails initializers directory.
16
+ # Copies the CMDx initializer template to the Rails application.
29
17
  #
30
- # Creates a new initializer file at `config/initializers/cmdx.rb` with
31
- # default configuration settings for:
32
- # - Task halt behaviors
33
- # - Timeout settings
34
- # - Workflow execution controls
35
- # - Logger configuration
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.
36
21
  #
37
22
  # @return [void]
38
- # @raise [Thor::Error] if the destination file cannot be created
39
23
  #
40
- # @example Generated initializer content
41
- # CMDx.configure do |config|
42
- # config.task_halt = CMDx::Result::FAILED
43
-
44
- # # ... additional settings
45
- # end
24
+ # @raise [Thor::Error] if the destination file cannot be created or already exists without force
25
+ #
26
+ # @example Generate CMDx initializer
27
+ # rails generate cmdx:install
28
+ # # Creates config/initializers/cmdx.rb
46
29
  def copy_initializer_file
47
30
  copy_file("install.rb", "config/initializers/cmdx.rb")
48
31
  end
@@ -1,28 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cmdx
4
- ##
5
- # Rails generator for creating CMDx task classes.
4
+ # Rails generator for creating CMDx task files.
6
5
  #
7
- # This generator creates individual task files that encapsulate specific
8
- # business logic operations. Tasks inherit from CMDx::Task and provide
9
- # parameter validation, callbacks, result tracking, and error handling
10
- # capabilities for focused business operations.
11
- #
12
- # The generator handles name normalization, ensuring "Task" suffix
13
- # and proper file naming conventions. Generated tasks inherit from
14
- # ApplicationTask when available, falling back to CMDx::Task.
15
- #
16
- # @example Generate a task
17
- # rails generate cmdx:task SendEmail
18
- # rails generate cmdx:task ProcessPayment
19
- # rails generate cmdx:task ProcessPaymentTask # "Task" suffix preserved
20
- #
21
- # @example Generated file location
22
- # app/cmds/send_email_task.rb
23
- # app/cmds/process_payment_task.rb
24
- #
25
- # @since 1.0.0
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.
26
10
  class TaskGenerator < Rails::Generators::NamedBase
27
11
 
28
12
  source_root File.expand_path("templates", __dir__)
@@ -30,25 +14,21 @@ module Cmdx
30
14
 
31
15
  desc "Creates a task with the given NAME"
32
16
 
33
- ##
34
- # Copies the task template to the application commands directory.
17
+ # Creates the task file from the template.
35
18
  #
36
- # Creates a new task file in `app/cmds/` with the normalized name.
37
- # The generator automatically handles:
38
- # - Removing "Task" suffix from file naming
39
- # - Converting to snake_case for file naming
40
- # - Adding "_task" suffix to the filename
41
- # - Setting up proper class inheritance
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.
42
22
  #
43
23
  # @return [void]
44
- # @raise [Thor::Error] if the destination file cannot be created
45
24
  #
46
- # @example Generated task structure
47
- # class SendEmailTask < ApplicationTask
48
- # def call
49
- # # Task business logic
50
- # end
51
- # end
25
+ # @example Generate a user task
26
+ # rails generate cmdx:task user
27
+ # #=> Creates app/cmds/user_task.rb
28
+ #
29
+ # @example Generate a nested task
30
+ # rails generate cmdx:task admin/users
31
+ # #=> Creates app/cmds/admin/users_task.rb
52
32
  def copy_files
53
33
  name = file_name.sub(/_?task$/i, "")
54
34
  path = File.join("app/cmds", class_path, "#{name}_task.rb")
@@ -57,37 +37,41 @@ module Cmdx
57
37
 
58
38
  private
59
39
 
60
- ##
61
- # Normalizes the class name by ensuring "Task" suffix.
40
+ # Ensures the class name ends with "Task" suffix.
62
41
  #
63
- # Ensures consistent class naming by adding "Task" suffix if not
64
- # already present, allowing users to specify either "SendEmail"
65
- # or "SendEmailTask".
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.
66
45
  #
67
- # @return [String] the normalized class name with "Task" suffix
46
+ # @return [String] the class name with "Task" suffix
68
47
  #
69
- # @example Class name normalization
70
- # # Input: "SendEmail"
71
- # # Output: "SendEmailTask"
48
+ # @example Class name without suffix
49
+ # # Given name: "User"
50
+ # class_name #=> "UserTask"
72
51
  #
73
- # # Input: "SendEmailTask"
74
- # # Output: "SendEmailTask"
52
+ # @example Class name with suffix
53
+ # # Given name: "UserTask"
54
+ # class_name #=> "UserTask"
75
55
  def class_name
76
56
  @class_name ||= super.end_with?("Task") ? super : "#{super}Task"
77
57
  end
78
58
 
79
- ##
80
59
  # Determines the parent class for the generated task.
81
60
  #
82
- # Attempts to use ApplicationTask as the parent class if available,
83
- # falling back to CMDx::Task if ApplicationTask is not defined.
84
- # This allows applications to define custom base task behavior.
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
85
69
  #
86
- # @return [String] the parent class name to inherit from
70
+ # @example With ApplicationTask defined
71
+ # parent_class_name #=> ApplicationTask
87
72
  #
88
- # @example Parent class resolution
89
- # # If ApplicationTask exists: "ApplicationTask"
90
- # # If ApplicationTask missing: "CMDx::Task"
73
+ # @example Without ApplicationTask
74
+ # parent_class_name #=> CMDx::Task
91
75
  def parent_class_name
92
76
  ApplicationTask
93
77
  rescue StandardError
@@ -33,19 +33,37 @@ CMDx.configure do |config|
33
33
  # Global middlewares - automatically applied to all tasks
34
34
  # See https://github.com/drexed/cmdx/blob/main/docs/middlewares.md for more details
35
35
  #
36
- # config.middlewares.use CMDx::Middlewares::Timeout, seconds: 30
37
36
  # config.middlewares.use CMDx::Middlewares::Correlate
38
- # config.middlewares.use CustomAuthMiddleware, role: "admin"
39
- # config.middlewares.use PerformanceMiddleware.new(threshold: 5.0)
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
40
 
41
41
  # Global callbacks - automatically applied to all tasks
42
42
  # See https://github.com/drexed/cmdx/blob/main/docs/callbacks.md for more details
43
43
  #
44
44
  # config.callbacks.register :before_execution, :log_task_start
45
- # config.callbacks.register :after_execution, :log_task_end
46
- # config.callbacks.register :on_success, NotificationCallback.new([:email])
45
+ # config.callbacks.register :after_execution, TrackTaskCompletion
46
+ # config.callbacks.register :on_success, NotificationCallback.new(via: [:email, :slack])
47
47
  # config.callbacks.register :on_failure, :alert_support, if: :critical?
48
- # config.callbacks.register :on_complete, proc { |task, callback_type|
48
+ # config.callbacks.register :on_complete, proc { |task, type|
49
49
  # Metrics.increment("task.#{task.class.name.underscore}.completed")
50
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
+ # }
51
69
  end
@@ -1,36 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cmdx
4
- ##
5
- # Rails generator for creating CMDx workflow task classes.
4
+ # Rails generator for creating CMDx workflow files.
6
5
  #
7
- # This generator creates workflow task files that coordinate multiple
8
- # individual tasks in a structured workflow. Workflow tasks inherit
9
- # from CMDx::Workflow and provide orchestration capabilities for
10
- # complex business processes.
11
- #
12
- # The generator handles name normalization, ensuring proper file naming
13
- # conventions and class names. Generated workflow tasks inherit from
14
- # ApplicationWorkflow when available, falling back to CMDx::Workflow.
15
- #
16
- # @example Generate a workflow task
17
- # rails generate cmdx:workflow OrderProcessing
18
- # rails generate cmdx:workflow PaymentWorkflow # "Workflow" suffix preserved
19
- #
20
- # @example Generated file location
21
- # app/cmds/order_processing_workflow.rb
22
- # app/cmds/payment_workflow.rb
23
- #
24
- # @example Generated class structure
25
- # class OrderProcessingWorkflow < ApplicationWorkflow
26
- # def call
27
- # # Workflow orchestration logic
28
- # end
29
- # end
30
- #
31
- # @see CMDx::Workflow Base workflow class
32
- # @see Rails::Generators::NamedBase Rails generator base class
33
- # @since 1.0.0
6
+ # This generator creates workflow files in the app/cmds directory with proper
7
+ # class naming conventions and inheritance. It ensures workflow names end with
8
+ # "Workflow" suffix and creates files in the correct location within the Rails
9
+ # application structure.
34
10
  class WorkflowGenerator < Rails::Generators::NamedBase
35
11
 
36
12
  source_root File.expand_path("templates", __dir__)
@@ -38,28 +14,23 @@ module Cmdx
38
14
 
39
15
  desc "Creates a workflow with the given NAME"
40
16
 
41
- ##
42
- # Copies the workflow task template to the application commands directory.
17
+ # Creates the workflow file from the template.
43
18
  #
44
- # Creates a new workflow task file in `app/cmds/` with the normalized
45
- # name. The generator automatically handles:
46
- # - Removing "workflow" suffix from the provided name for filename
47
- # - Converting to snake_case for file naming
48
- # - Adding "_workflow" suffix to the filename
49
- # - Setting up proper class inheritance
50
- # - Ensuring class names end with "Workflow"
19
+ # Generates a new workflow file in the app/cmds directory based on the provided
20
+ # name. The file name is normalized to ensure it ends with "_workflow.rb" and
21
+ # is placed in the appropriate subdirectory structure.
51
22
  #
52
23
  # @return [void]
53
- # @raise [Thor::Error] if the destination file cannot be created
54
24
  #
55
- # @example File generation
56
- # # Input: rails generate cmdx:workflow OrderProcessing
57
- # # Creates: app/cmds/order_processing_workflow.rb
58
- # # Class: OrderProcessingWorkflow
25
+ # @raise [Thor::Error] if the destination file cannot be created or already exists without force
26
+ #
27
+ # @example Generate a user workflow
28
+ # rails generate cmdx:workflow user
29
+ # #=> Creates app/cmds/user_workflow.rb
59
30
  #
60
- # # Input: rails generate cmdx:workflow PaymentWorkflow
61
- # # Creates: app/cmds/payment_workflow.rb
62
- # # Class: PaymentWorkflow
31
+ # @example Generate a nested workflow
32
+ # rails generate cmdx:workflow admin/users
33
+ # #=> Creates app/cmds/admin/users_workflow.rb
63
34
  def copy_files
64
35
  name = file_name.sub(/_?workflow$/i, "")
65
36
  path = File.join("app/cmds", class_path, "#{name}_workflow.rb")
@@ -68,37 +39,41 @@ module Cmdx
68
39
 
69
40
  private
70
41
 
71
- ##
72
- # Normalizes the class name by ensuring it ends with "Workflow".
42
+ # Ensures the class name ends with "Workflow" suffix.
73
43
  #
74
- # Ensures consistent class naming by appending "Workflow" suffix
75
- # to the provided generator name if it doesn't already end with it,
76
- # allowing users to specify either "OrderProcessing" or "OrderProcessingWorkflow".
44
+ # Takes the provided class name and appends "Workflow" if it doesn't already
45
+ # end with that suffix, ensuring consistent naming conventions across
46
+ # all generated workflow classes.
77
47
  #
78
- # @return [String] the normalized class name with "Workflow" suffix
48
+ # @return [String] the class name with "Workflow" suffix
79
49
  #
80
- # @example Class name normalization
81
- # # Input: "OrderProcessing"
82
- # # Output: "OrderProcessingWorkflow"
50
+ # @example Class name without suffix
51
+ # # Given name: "User"
52
+ # class_name #=> "UserWorkflow"
83
53
  #
84
- # # Input: "PaymentWorkflow"
85
- # # Output: "PaymentWorkflow"
54
+ # @example Class name with suffix
55
+ # # Given name: "UserWorkflow"
56
+ # class_name #=> "UserWorkflow"
86
57
  def class_name
87
58
  @class_name ||= super.end_with?("Workflow") ? super : "#{super}Workflow"
88
59
  end
89
60
 
90
- ##
91
- # Determines the parent class for the generated workflow task.
61
+ # Determines the parent class for the generated workflow.
62
+ #
63
+ # Attempts to use ApplicationWorkflow as the parent class if it exists in the
64
+ # application, otherwise falls back to CMDx::Workflow as the base class.
65
+ # This allows applications to define their own base workflow class with
66
+ # common functionality.
67
+ #
68
+ # @return [Class] the parent class for the generated workflow
92
69
  #
93
- # Attempts to use ApplicationWorkflow as the parent class if available,
94
- # falling back to CMDx::Workflow if ApplicationWorkflow is not defined.
95
- # This allows applications to define custom base workflow behavior.
70
+ # @raise [StandardError] if neither ApplicationWorkflow nor CMDx::Workflow are available
96
71
  #
97
- # @return [String] the parent class name to inherit from
72
+ # @example With ApplicationWorkflow defined
73
+ # parent_class_name #=> ApplicationWorkflow
98
74
  #
99
- # @example Parent class resolution
100
- # # If ApplicationWorkflow exists: "ApplicationWorkflow"
101
- # # If ApplicationWorkflow missing: "CMDx::Workflow"
75
+ # @example Without ApplicationWorkflow
76
+ # parent_class_name #=> CMDx::Workflow
102
77
  def parent_class_name
103
78
  ApplicationWorkflow
104
79
  rescue StandardError
data/lib/locales/ar.yml CHANGED
@@ -11,7 +11,6 @@ ar:
11
11
  required: "معامل مطلوب"
12
12
  undefined: "يفوض لطريقة غير معرفة %{source}"
13
13
  validators:
14
- custom: "غير صالح"
15
14
  exclusion:
16
15
  of: "يجب ألا يكون أحد: %{values}"
17
16
  within: "يجب ألا يكون بين %{min} و %{max}"
data/lib/locales/cs.yml CHANGED
@@ -11,7 +11,6 @@ cs:
11
11
  required: "je povinný parametr"
12
12
  undefined: "deleguje na nedefinovanou metodu %{source}"
13
13
  validators:
14
- custom: "není platný"
15
14
  exclusion:
16
15
  of: "nesmí být jeden z: %{values}"
17
16
  within: "nesmí být mezi %{min} a %{max}"
data/lib/locales/da.yml CHANGED
@@ -11,7 +11,6 @@ da:
11
11
  required: "er en påkrævet parameter"
12
12
  undefined: "delegerer til udefineret metode %{source}"
13
13
  validators:
14
- custom: "er ikke gyldig"
15
14
  exclusion:
16
15
  of: "må ikke være en af: %{values}"
17
16
  within: "må ikke være mellem %{min} og %{max}"
data/lib/locales/de.yml CHANGED
@@ -11,7 +11,6 @@ de:
11
11
  required: "ist ein erforderlicher Parameter"
12
12
  undefined: "delegiert an undefinierte Methode %{source}"
13
13
  validators:
14
- custom: "ist nicht gültig"
15
14
  exclusion:
16
15
  of: "darf nicht einer von: %{values} sein"
17
16
  within: "darf nicht zwischen %{min} und %{max} liegen"
data/lib/locales/el.yml CHANGED
@@ -11,7 +11,6 @@ el:
11
11
  required: "είναι υποχρεωτική παράμετρος"
12
12
  undefined: "αναθέτει σε μη ορισμένη μέθοδο %{source}"
13
13
  validators:
14
- custom: "δεν είναι έγκυρο"
15
14
  exclusion:
16
15
  of: "δεν πρέπει να είναι ένα από: %{values}"
17
16
  within: "δεν πρέπει να είναι μεταξύ %{min} και %{max}"
data/lib/locales/en.yml CHANGED
@@ -11,7 +11,6 @@ en:
11
11
  required: "is a required parameter"
12
12
  undefined: "delegates to undefined method %{source}"
13
13
  validators:
14
- custom: "is not valid"
15
14
  exclusion:
16
15
  of: "must not be one of: %{values}"
17
16
  within: "must not be within %{min} and %{max}"
data/lib/locales/es.yml CHANGED
@@ -11,7 +11,6 @@ es:
11
11
  required: "es un parámetro requerido"
12
12
  undefined: "delegado al método indefinido %{source}"
13
13
  validators:
14
- custom: "no es válida"
15
14
  exclusion:
16
15
  of: "no debe ser uno de: %{values}"
17
16
  within: "no debe estar dentro %{min} y %{max}"
data/lib/locales/fi.yml CHANGED
@@ -11,7 +11,6 @@ fi:
11
11
  required: "on pakollinen parametri"
12
12
  undefined: "delegoi määrittelemättömään metodiin %{source}"
13
13
  validators:
14
- custom: "ei ole kelvollinen"
15
14
  exclusion:
16
15
  of: "ei saa olla mikään seuraavista: %{values}"
17
16
  within: "ei saa olla välillä %{min} ja %{max}"
data/lib/locales/fr.yml CHANGED
@@ -11,7 +11,6 @@ fr:
11
11
  required: "est un paramètre obligatoire"
12
12
  undefined: "délègue à une méthode indéfinie %{source}"
13
13
  validators:
14
- custom: "n'est pas valide"
15
14
  exclusion:
16
15
  of: "ne doit pas être un de: %{values}"
17
16
  within: "ne doit pas être entre %{min} et %{max}"
data/lib/locales/he.yml CHANGED
@@ -11,7 +11,6 @@ he:
11
11
  required: "הוא פרמטר חובה"
12
12
  undefined: "מאציל למתודה לא מוגדרת %{source}"
13
13
  validators:
14
- custom: "לא תקין"
15
14
  exclusion:
16
15
  of: "לא יכול להיות אחד מהבאים: %{values}"
17
16
  within: "לא יכול להיות בין %{min} ל%{max}"
data/lib/locales/hi.yml CHANGED
@@ -11,7 +11,6 @@ hi:
11
11
  required: "एक आवश्यक पैरामीटर है"
12
12
  undefined: "अपरिभाषित मेथड %{source} को प्रत्यायोजित करता है"
13
13
  validators:
14
- custom: "मान्य नहीं है"
15
14
  exclusion:
16
15
  of: "इनमें से एक नहीं होना चाहिए: %{values}"
17
16
  within: "%{min} और %{max} के बीच नहीं होना चाहिए"
data/lib/locales/it.yml CHANGED
@@ -11,7 +11,6 @@ it:
11
11
  required: "è un parametro obbligatorio"
12
12
  undefined: "delega al metodo indefinito %{source}"
13
13
  validators:
14
- custom: "non è valido"
15
14
  exclusion:
16
15
  of: "non deve essere uno di: %{values}"
17
16
  within: "non deve essere tra %{min} e %{max}"
data/lib/locales/ja.yml CHANGED
@@ -11,7 +11,6 @@ ja:
11
11
  required: "必須パラメータです"
12
12
  undefined: "未定義メソッド%{source}に委譲します"
13
13
  validators:
14
- custom: "無効です"
15
14
  exclusion:
16
15
  of: "次のいずれかであってはいけません: %{values}"
17
16
  within: "%{min}と%{max}の間であってはいけません"
data/lib/locales/ko.yml CHANGED
@@ -11,7 +11,6 @@ ko:
11
11
  required: "필수 매개변수입니다"
12
12
  undefined: "정의되지 않은 메서드 %{source}에 위임합니다"
13
13
  validators:
14
- custom: "유효하지 않습니다"
15
14
  exclusion:
16
15
  of: "다음 중 하나가 아니어야 합니다: %{values}"
17
16
  within: "%{min}과 %{max} 사이에 있지 않아야 합니다"
data/lib/locales/nl.yml CHANGED
@@ -11,7 +11,6 @@ nl:
11
11
  required: "is een vereiste parameter"
12
12
  undefined: "delegeert naar ongedefinieerde methode %{source}"
13
13
  validators:
14
- custom: "is niet geldig"
15
14
  exclusion:
16
15
  of: "mag niet een van zijn: %{values}"
17
16
  within: "mag niet tussen %{min} en %{max} liggen"
data/lib/locales/no.yml CHANGED
@@ -11,7 +11,6 @@
11
11
  required: "er en påkrevd parameter"
12
12
  undefined: "delegerer til udefinert metode %{source}"
13
13
  validators:
14
- custom: "er ikke gyldig"
15
14
  exclusion:
16
15
  of: "må ikke være en av: %{values}"
17
16
  within: "må ikke være mellom %{min} og %{max}"
data/lib/locales/pl.yml CHANGED
@@ -11,7 +11,6 @@ pl:
11
11
  required: "jest wymaganym parametrem"
12
12
  undefined: "deleguje do niezdefiniowanej metody %{source}"
13
13
  validators:
14
- custom: "jest nieprawidłowy"
15
14
  exclusion:
16
15
  of: "nie może być jednym z: %{values}"
17
16
  within: "nie może być między %{min} a %{max}"
data/lib/locales/pt.yml CHANGED
@@ -11,7 +11,6 @@ pt:
11
11
  required: "é um parâmetro obrigatório"
12
12
  undefined: "delega para método indefinido %{source}"
13
13
  validators:
14
- custom: "não é válido"
15
14
  exclusion:
16
15
  of: "não deve ser um de: %{values}"
17
16
  within: "não deve estar entre %{min} e %{max}"
data/lib/locales/ru.yml CHANGED
@@ -11,7 +11,6 @@ ru:
11
11
  required: "обязательный параметр"
12
12
  undefined: "делегирует неопределенному методу %{source}"
13
13
  validators:
14
- custom: "недействительный"
15
14
  exclusion:
16
15
  of: "не должен быть одним из: %{values}"
17
16
  within: "не должен быть между %{min} и %{max}"
data/lib/locales/sv.yml CHANGED
@@ -11,7 +11,6 @@ sv:
11
11
  required: "är en obligatorisk parameter"
12
12
  undefined: "delegerar till odefinierad metod %{source}"
13
13
  validators:
14
- custom: "är inte giltig"
15
14
  exclusion:
16
15
  of: "får inte vara en av: %{values}"
17
16
  within: "får inte vara mellan %{min} och %{max}"
data/lib/locales/th.yml CHANGED
@@ -11,7 +11,6 @@ th:
11
11
  required: "เป็นพารามิเตอร์ที่จำเป็น"
12
12
  undefined: "ส่งต่อไปยังเมธอดที่ไม่ได้กำหนด %{source}"
13
13
  validators:
14
- custom: "ไม่ถูกต้อง"
15
14
  exclusion:
16
15
  of: "ต้องไม่เป็นหนึ่งใน: %{values}"
17
16
  within: "ต้องไม่อยู่ระหว่าง %{min} และ %{max}"
data/lib/locales/tr.yml CHANGED
@@ -11,7 +11,6 @@ tr:
11
11
  required: "gerekli bir parametredir"
12
12
  undefined: "tanımsız metoda %{source} yetki verir"
13
13
  validators:
14
- custom: "geçerli değil"
15
14
  exclusion:
16
15
  of: "şunlardan biri olmamalı: %{values}"
17
16
  within: "%{min} ve %{max} arasında olmamalı"
data/lib/locales/vi.yml CHANGED
@@ -11,7 +11,6 @@ vi:
11
11
  required: "là một tham số bắt buộc"
12
12
  undefined: "ủy quyền cho phương thức không xác định %{source}"
13
13
  validators:
14
- custom: "không hợp lệ"
15
14
  exclusion:
16
15
  of: "không được là một trong: %{values}"
17
16
  within: "không được nằm giữa %{min} và %{max}"
data/lib/locales/zh.yml CHANGED
@@ -11,7 +11,6 @@ zh:
11
11
  required: "是必需参数"
12
12
  undefined: "委托给未定义的方法%{source}"
13
13
  validators:
14
- custom: "无效"
15
14
  exclusion:
16
15
  of: "不能是以下任一值: %{values}"
17
16
  within: "不能在%{min}和%{max}之间"