cmdx 1.1.2 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.DS_Store +0 -0
- data/.cursor/prompts/docs.md +4 -1
- data/.cursor/prompts/llms.md +20 -0
- data/.cursor/prompts/rspec.md +4 -1
- data/.cursor/prompts/yardoc.md +3 -2
- data/.cursor/rules/cursor-instructions.mdc +55 -1
- data/.irbrc +6 -0
- data/.rubocop.yml +29 -18
- data/CHANGELOG.md +11 -132
- data/LLM.md +3317 -0
- data/README.md +68 -44
- data/docs/attributes/coercions.md +162 -0
- data/docs/attributes/defaults.md +90 -0
- data/docs/attributes/definitions.md +281 -0
- data/docs/attributes/naming.md +78 -0
- data/docs/attributes/validations.md +309 -0
- data/docs/basics/chain.md +56 -249
- data/docs/basics/context.md +56 -289
- data/docs/basics/execution.md +114 -0
- data/docs/basics/setup.md +37 -334
- data/docs/callbacks.md +89 -467
- data/docs/deprecation.md +91 -174
- data/docs/getting_started.md +212 -202
- data/docs/internationalization.md +11 -647
- data/docs/interruptions/exceptions.md +23 -198
- data/docs/interruptions/faults.md +71 -151
- data/docs/interruptions/halt.md +109 -186
- data/docs/logging.md +44 -256
- data/docs/middlewares.md +113 -426
- data/docs/outcomes/result.md +81 -228
- data/docs/outcomes/states.md +33 -221
- data/docs/outcomes/statuses.md +21 -311
- data/docs/tips_and_tricks.md +120 -70
- data/docs/workflows.md +99 -283
- data/lib/cmdx/.DS_Store +0 -0
- data/lib/cmdx/attribute.rb +229 -0
- data/lib/cmdx/attribute_registry.rb +94 -0
- data/lib/cmdx/attribute_value.rb +193 -0
- data/lib/cmdx/callback_registry.rb +69 -77
- data/lib/cmdx/chain.rb +56 -73
- data/lib/cmdx/coercion_registry.rb +52 -68
- data/lib/cmdx/coercions/array.rb +19 -18
- data/lib/cmdx/coercions/big_decimal.rb +20 -24
- data/lib/cmdx/coercions/boolean.rb +26 -25
- data/lib/cmdx/coercions/complex.rb +21 -22
- data/lib/cmdx/coercions/date.rb +25 -23
- data/lib/cmdx/coercions/date_time.rb +24 -25
- data/lib/cmdx/coercions/float.rb +25 -22
- data/lib/cmdx/coercions/hash.rb +31 -32
- data/lib/cmdx/coercions/integer.rb +30 -24
- data/lib/cmdx/coercions/rational.rb +29 -24
- data/lib/cmdx/coercions/string.rb +19 -22
- data/lib/cmdx/coercions/symbol.rb +37 -0
- data/lib/cmdx/coercions/time.rb +26 -25
- data/lib/cmdx/configuration.rb +49 -108
- data/lib/cmdx/context.rb +222 -44
- data/lib/cmdx/deprecator.rb +61 -0
- data/lib/cmdx/errors.rb +42 -252
- data/lib/cmdx/exceptions.rb +39 -0
- data/lib/cmdx/faults.rb +78 -39
- data/lib/cmdx/freezer.rb +51 -0
- data/lib/cmdx/identifier.rb +30 -0
- data/lib/cmdx/locale.rb +52 -0
- data/lib/cmdx/log_formatters/json.rb +21 -22
- data/lib/cmdx/log_formatters/key_value.rb +20 -22
- data/lib/cmdx/log_formatters/line.rb +15 -22
- data/lib/cmdx/log_formatters/logstash.rb +22 -23
- data/lib/cmdx/log_formatters/raw.rb +16 -22
- data/lib/cmdx/middleware_registry.rb +70 -74
- data/lib/cmdx/middlewares/correlate.rb +90 -54
- data/lib/cmdx/middlewares/runtime.rb +58 -0
- data/lib/cmdx/middlewares/timeout.rb +48 -68
- data/lib/cmdx/railtie.rb +12 -45
- data/lib/cmdx/result.rb +229 -314
- data/lib/cmdx/task.rb +194 -366
- data/lib/cmdx/utils/call.rb +49 -0
- data/lib/cmdx/utils/condition.rb +71 -0
- data/lib/cmdx/utils/format.rb +61 -0
- data/lib/cmdx/validator_registry.rb +63 -72
- data/lib/cmdx/validators/exclusion.rb +38 -67
- data/lib/cmdx/validators/format.rb +48 -49
- data/lib/cmdx/validators/inclusion.rb +43 -74
- data/lib/cmdx/validators/length.rb +101 -162
- data/lib/cmdx/validators/numeric.rb +95 -170
- data/lib/cmdx/validators/presence.rb +37 -50
- data/lib/cmdx/version.rb +1 -1
- data/lib/cmdx/worker.rb +178 -0
- data/lib/cmdx/workflow.rb +85 -81
- data/lib/cmdx.rb +19 -13
- data/lib/generators/cmdx/install_generator.rb +14 -13
- data/lib/generators/cmdx/task_generator.rb +25 -50
- data/lib/generators/cmdx/templates/install.rb +11 -46
- data/lib/generators/cmdx/templates/task.rb.tt +3 -2
- data/lib/locales/en.yml +18 -4
- data/src/cmdx-logo.png +0 -0
- metadata +32 -116
- data/docs/ai_prompts.md +0 -393
- data/docs/basics/call.md +0 -317
- data/docs/configuration.md +0 -344
- data/docs/parameters/coercions.md +0 -396
- data/docs/parameters/defaults.md +0 -335
- data/docs/parameters/definitions.md +0 -446
- data/docs/parameters/namespacing.md +0 -378
- data/docs/parameters/validations.md +0 -405
- data/docs/testing.md +0 -553
- data/lib/cmdx/callback.rb +0 -53
- data/lib/cmdx/chain_inspector.rb +0 -56
- data/lib/cmdx/chain_serializer.rb +0 -63
- data/lib/cmdx/coercion.rb +0 -57
- data/lib/cmdx/coercions/virtual.rb +0 -29
- data/lib/cmdx/core_ext/hash.rb +0 -83
- data/lib/cmdx/core_ext/module.rb +0 -98
- data/lib/cmdx/core_ext/object.rb +0 -125
- data/lib/cmdx/correlator.rb +0 -122
- data/lib/cmdx/error.rb +0 -67
- data/lib/cmdx/fault.rb +0 -140
- data/lib/cmdx/immutator.rb +0 -52
- data/lib/cmdx/lazy_struct.rb +0 -246
- data/lib/cmdx/log_formatters/pretty_json.rb +0 -40
- data/lib/cmdx/log_formatters/pretty_key_value.rb +0 -38
- data/lib/cmdx/log_formatters/pretty_line.rb +0 -41
- data/lib/cmdx/logger.rb +0 -49
- data/lib/cmdx/logger_ansi.rb +0 -68
- data/lib/cmdx/logger_serializer.rb +0 -116
- data/lib/cmdx/middleware.rb +0 -70
- data/lib/cmdx/parameter.rb +0 -312
- data/lib/cmdx/parameter_evaluator.rb +0 -231
- data/lib/cmdx/parameter_inspector.rb +0 -66
- data/lib/cmdx/parameter_registry.rb +0 -106
- data/lib/cmdx/parameter_serializer.rb +0 -59
- data/lib/cmdx/result_ansi.rb +0 -71
- data/lib/cmdx/result_inspector.rb +0 -71
- data/lib/cmdx/result_logger.rb +0 -59
- data/lib/cmdx/result_serializer.rb +0 -104
- data/lib/cmdx/rspec/matchers.rb +0 -28
- data/lib/cmdx/rspec/result_matchers/be_executed.rb +0 -42
- data/lib/cmdx/rspec/result_matchers/be_failed_task.rb +0 -94
- data/lib/cmdx/rspec/result_matchers/be_skipped_task.rb +0 -94
- data/lib/cmdx/rspec/result_matchers/be_state_matchers.rb +0 -59
- data/lib/cmdx/rspec/result_matchers/be_status_matchers.rb +0 -57
- data/lib/cmdx/rspec/result_matchers/be_successful_task.rb +0 -87
- data/lib/cmdx/rspec/result_matchers/have_bad_outcome.rb +0 -51
- data/lib/cmdx/rspec/result_matchers/have_caused_failure.rb +0 -58
- data/lib/cmdx/rspec/result_matchers/have_chain_index.rb +0 -59
- data/lib/cmdx/rspec/result_matchers/have_context.rb +0 -86
- data/lib/cmdx/rspec/result_matchers/have_empty_metadata.rb +0 -54
- data/lib/cmdx/rspec/result_matchers/have_good_outcome.rb +0 -52
- data/lib/cmdx/rspec/result_matchers/have_metadata.rb +0 -114
- data/lib/cmdx/rspec/result_matchers/have_preserved_context.rb +0 -66
- data/lib/cmdx/rspec/result_matchers/have_received_thrown_failure.rb +0 -64
- data/lib/cmdx/rspec/result_matchers/have_runtime.rb +0 -78
- data/lib/cmdx/rspec/result_matchers/have_thrown_failure.rb +0 -76
- data/lib/cmdx/rspec/task_matchers/be_well_formed_task.rb +0 -62
- data/lib/cmdx/rspec/task_matchers/have_callback.rb +0 -85
- data/lib/cmdx/rspec/task_matchers/have_cmd_setting.rb +0 -68
- data/lib/cmdx/rspec/task_matchers/have_executed_callbacks.rb +0 -92
- data/lib/cmdx/rspec/task_matchers/have_middleware.rb +0 -46
- data/lib/cmdx/rspec/task_matchers/have_parameter.rb +0 -181
- data/lib/cmdx/task_deprecator.rb +0 -58
- data/lib/cmdx/task_processor.rb +0 -246
- data/lib/cmdx/task_serializer.rb +0 -57
- data/lib/cmdx/utils/ansi_color.rb +0 -73
- data/lib/cmdx/utils/log_timestamp.rb +0 -36
- data/lib/cmdx/utils/monotonic_runtime.rb +0 -34
- data/lib/cmdx/utils/name_affix.rb +0 -52
- data/lib/cmdx/validator.rb +0 -57
- data/lib/generators/cmdx/templates/workflow.rb.tt +0 -7
- data/lib/generators/cmdx/workflow_generator.rb +0 -84
- data/lib/locales/ar.yml +0 -35
- data/lib/locales/cs.yml +0 -35
- data/lib/locales/da.yml +0 -35
- data/lib/locales/de.yml +0 -35
- data/lib/locales/el.yml +0 -35
- data/lib/locales/es.yml +0 -35
- data/lib/locales/fi.yml +0 -35
- data/lib/locales/fr.yml +0 -35
- data/lib/locales/he.yml +0 -35
- data/lib/locales/hi.yml +0 -35
- data/lib/locales/it.yml +0 -35
- data/lib/locales/ja.yml +0 -35
- data/lib/locales/ko.yml +0 -35
- data/lib/locales/nl.yml +0 -35
- data/lib/locales/no.yml +0 -35
- data/lib/locales/pl.yml +0 -35
- data/lib/locales/pt.yml +0 -35
- data/lib/locales/ru.yml +0 -35
- data/lib/locales/sv.yml +0 -35
- data/lib/locales/th.yml +0 -35
- data/lib/locales/tr.yml +0 -35
- data/lib/locales/vi.yml +0 -35
- 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
|
-
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
|
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
|
-
|
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
|
-
#
|
11
|
+
# Prevents redefinition of the work method to maintain workflow integrity.
|
24
12
|
#
|
25
|
-
#
|
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
|
-
# @
|
15
|
+
# @raise [RuntimeError] If attempting to redefine the work method
|
30
16
|
#
|
31
|
-
# @example
|
32
|
-
# class MyWorkflow
|
33
|
-
#
|
34
|
-
#
|
17
|
+
# @example
|
18
|
+
# class MyWorkflow
|
19
|
+
# include CMDx::Workflow
|
20
|
+
# # This would raise an error:
|
21
|
+
# # def work; end
|
35
22
|
# end
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
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
|
-
#
|
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
|
-
# @
|
50
|
-
# @param options [Hash] execution configuration options
|
31
|
+
# @return [Array<ExecutionGroup>] Array of execution groups
|
51
32
|
#
|
52
|
-
# @
|
53
|
-
#
|
54
|
-
#
|
55
|
-
#
|
56
|
-
#
|
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
|
-
# @
|
66
|
-
#
|
67
|
-
#
|
68
|
-
#
|
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
|
-
# @
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
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
|
79
|
-
|
80
|
-
tasks.
|
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
|
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
|
-
#
|
92
|
-
#
|
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]
|
95
|
+
# @raise [CMDx::Fault] If a breakpoint is encountered during execution
|
99
96
|
#
|
100
|
-
# @example
|
101
|
-
# workflow = MyWorkflow.new
|
102
|
-
# workflow.
|
103
|
-
|
104
|
-
|
105
|
-
|
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
|
-
|
108
|
-
|
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.
|
114
|
-
next unless
|
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 "
|
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
|
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::
|
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
|
-
#
|
4
|
+
# Generates CMDx initializer file for Rails applications
|
5
5
|
#
|
6
|
-
# This generator creates a
|
7
|
-
#
|
8
|
-
# initializer
|
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
|
19
|
-
# the
|
20
|
-
#
|
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
|
-
# @
|
25
|
-
#
|
26
|
-
# @example Generate CMDx initializer
|
24
|
+
# @example Basic usage
|
27
25
|
# rails generate cmdx:install
|
28
|
-
#
|
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
|
-
#
|
4
|
+
# Generates CMDx task files for Rails applications
|
5
5
|
#
|
6
|
-
# This generator creates task
|
7
|
-
#
|
8
|
-
#
|
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
|
-
#
|
15
|
+
# Copies the task template to the Rails application
|
18
16
|
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
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
|
26
|
-
# rails generate cmdx:task
|
27
|
-
#
|
23
|
+
# @example Basic usage
|
24
|
+
# rails generate cmdx:task UserRegistration
|
25
|
+
# # => Creates app/tasks/user_registration.rb
|
28
26
|
#
|
29
|
-
# @example
|
30
|
-
# rails generate cmdx:task
|
31
|
-
#
|
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
|
-
|
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
|
-
#
|
37
|
+
# Determines the appropriate parent class name for the generated task
|
41
38
|
#
|
42
|
-
#
|
43
|
-
#
|
44
|
-
#
|
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 [
|
43
|
+
# @return [Class] The parent class for the generated task
|
47
44
|
#
|
48
|
-
# @example
|
49
|
-
# #
|
50
|
-
# class_name #=> "UserTask"
|
45
|
+
# @example
|
46
|
+
# parent_class_name # => ApplicationTask
|
51
47
|
#
|
52
|
-
# @example
|
53
|
-
# #
|
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
|
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
|
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.
|
9
|
+
config.task_breakpoints = %w[failed]
|
10
10
|
|
11
|
-
# Workflow
|
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.
|
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::
|
25
|
+
# - CMDx::LogFormatters::Line
|
29
26
|
# - CMDx::LogFormatters::Logstash
|
30
27
|
# - CMDx::LogFormatters::Raw
|
31
|
-
config.logger = Logger.new(
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
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
|
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: %{
|
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
|
-
|
11
|
-
|
12
|
-
|
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
|