domainic-command 0.1.0.alpha.1.0.0 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.yardopts +11 -0
- data/CHANGELOG.md +19 -0
- data/LICENSE +1 -1
- data/README.md +93 -2
- data/lib/domainic/command/class_methods.rb +181 -0
- data/lib/domainic/command/context/attribute.rb +157 -0
- data/lib/domainic/command/context/attribute_set.rb +96 -0
- data/lib/domainic/command/context/behavior.rb +132 -0
- data/lib/domainic/command/context/input_context.rb +55 -0
- data/lib/domainic/command/context/output_context.rb +55 -0
- data/lib/domainic/command/context/runtime_context.rb +126 -0
- data/lib/domainic/command/errors/error.rb +23 -0
- data/lib/domainic/command/errors/execution_error.rb +40 -0
- data/lib/domainic/command/instance_methods.rb +92 -0
- data/lib/domainic/command/result/error_set.rb +272 -0
- data/lib/domainic/command/result/status.rb +49 -0
- data/lib/domainic/command/result.rb +194 -0
- data/lib/domainic/command.rb +77 -0
- data/lib/domainic-command.rb +3 -0
- data/sig/domainic/command/class_methods.rbs +100 -0
- data/sig/domainic/command/context/attribute.rbs +104 -0
- data/sig/domainic/command/context/attribute_set.rbs +69 -0
- data/sig/domainic/command/context/behavior.rbs +82 -0
- data/sig/domainic/command/context/input_context.rbs +40 -0
- data/sig/domainic/command/context/output_context.rbs +40 -0
- data/sig/domainic/command/context/runtime_context.rbs +90 -0
- data/sig/domainic/command/errors/error.rbs +21 -0
- data/sig/domainic/command/errors/execution_error.rbs +32 -0
- data/sig/domainic/command/instance_methods.rbs +56 -0
- data/sig/domainic/command/result/error_set.rbs +186 -0
- data/sig/domainic/command/result/status.rbs +47 -0
- data/sig/domainic/command/result.rbs +149 -0
- data/sig/domainic/command.rbs +67 -0
- data/sig/domainic-command.rbs +1 -0
- data/sig/manifest.yaml +1 -0
- metadata +50 -13
@@ -0,0 +1,104 @@
|
|
1
|
+
module Domainic
|
2
|
+
module Command
|
3
|
+
module Context
|
4
|
+
# Represents an attribute within a command context. This class manages the lifecycle of an attribute, including
|
5
|
+
# its validation, default values, and metadata such as descriptions
|
6
|
+
#
|
7
|
+
# The `Attribute` class supports a variety of configuration options, such as marking an attribute as required,
|
8
|
+
# defining static or dynamic default values, and specifying custom validators. These features ensure that
|
9
|
+
# attributes conform to expected rules and provide useful metadata for documentation or runtime behavior
|
10
|
+
#
|
11
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
12
|
+
# @since 0.1.0
|
13
|
+
class Attribute
|
14
|
+
# Represents an undefined default value for an attribute. This is used internally to distinguish between
|
15
|
+
# an attribute with no default and one with a defined default
|
16
|
+
#
|
17
|
+
# @return [Object] A frozen object representing an undefined default value
|
18
|
+
UNDEFINED_DEFAULT: Object
|
19
|
+
|
20
|
+
@type_validator: Class | Module | Object | Proc
|
21
|
+
|
22
|
+
@default: untyped
|
23
|
+
|
24
|
+
@description: String?
|
25
|
+
|
26
|
+
@name: Symbol
|
27
|
+
|
28
|
+
@required: bool
|
29
|
+
|
30
|
+
# The textual description of the attribute, providing metadata about its purpose or usage
|
31
|
+
#
|
32
|
+
# @return [String, nil] A description of the attribute
|
33
|
+
attr_reader description: String?
|
34
|
+
|
35
|
+
# The name of the attribute, uniquely identifying it within a command context
|
36
|
+
#
|
37
|
+
# @return [Symbol] The name of the attribute
|
38
|
+
attr_reader name: Symbol
|
39
|
+
|
40
|
+
# Create a new attribute instance
|
41
|
+
#
|
42
|
+
# @overload initialize(
|
43
|
+
# name, type_validator_or_description = nil, description_or_type_validator = nil, **options
|
44
|
+
# )
|
45
|
+
# @param name [String, Symbol] The {#name} of the attribute
|
46
|
+
# @param type_validator_or_description [Class, Module, Object, Proc, String, nil] A type validator or the
|
47
|
+
# {#description} of the attribute
|
48
|
+
# @param description_or_type_validator [Class, Module, Object, Proc, String, nil] The {#description} or a
|
49
|
+
# type_validator of the attribute
|
50
|
+
# @param options [Hash] Configuration options for the attribute
|
51
|
+
# @option options [Object] :default The {#default} of the attribute
|
52
|
+
# @option options [Proc] :default_generator An alias for :default
|
53
|
+
# @option options [Object] :default_value An alias for :default
|
54
|
+
# @option options [String, nil] :desc An alias for :description
|
55
|
+
# @option options [String, nil] :description The {#description} of the attribute
|
56
|
+
# @option options [Boolean] :required Whether the attribute is {#required?}
|
57
|
+
# @option options [Class, Module, Object, Proc] :type A type validator for the attribute value
|
58
|
+
#
|
59
|
+
# @return [Attribute] the new Attribute instance
|
60
|
+
def initialize: (String | Symbol name, *(Class | Module | Object | Proc | String)? type_validator_and_description, ?default: untyped, ?default_generator: untyped, ?default_value: untyped, ?desc: String?, ?description: String?, ?required: bool, ?type: Class | Module | Object | Proc) -> void
|
61
|
+
|
62
|
+
# Retrieves the default value of the attribute. If a default generator is specified, it evaluates the generator
|
63
|
+
# and returns the result
|
64
|
+
#
|
65
|
+
# @return [Object, nil] The default value or the result of the generator
|
66
|
+
def default: () -> untyped
|
67
|
+
|
68
|
+
# Determines whether the attribute has a default value defined
|
69
|
+
#
|
70
|
+
# @return [Boolean] `true` if a default is set; otherwise, `false`
|
71
|
+
def default?: () -> bool
|
72
|
+
|
73
|
+
# Determines whether the attribute is marked as required
|
74
|
+
#
|
75
|
+
# @return [Boolean] `true` if the attribute is required; otherwise, `false`
|
76
|
+
def required?: () -> bool
|
77
|
+
|
78
|
+
# Validates the given value against the attribute's type validator
|
79
|
+
#
|
80
|
+
# @param value [Object] The value to validate
|
81
|
+
#
|
82
|
+
# @return [Boolean] `true` if the value is valid; otherwise, `false`
|
83
|
+
def valid?: (untyped value) -> bool
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
# Initializes the {#default} value for the attribute, using the provided options
|
88
|
+
#
|
89
|
+
# @param options [Hash] Configuration options containing default-related keys
|
90
|
+
#
|
91
|
+
# @return [void]
|
92
|
+
def initialize_default: (Hash[Symbol, untyped] options) -> void
|
93
|
+
|
94
|
+
# Initializes the description and type validator for the attribute based on the given arguments and options
|
95
|
+
#
|
96
|
+
# @param arguments [Array<Class, Module, Object, Proc, String, nil>] Arguments for validators or description
|
97
|
+
# @param options [Hash] Configuration options
|
98
|
+
#
|
99
|
+
# @return [void]
|
100
|
+
def initialize_description_and_type_validator: (Array[(Class | Module | Object | Proc | String)?] arguments, Hash[Symbol, untyped] options) -> void
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Domainic
|
2
|
+
module Command
|
3
|
+
module Context
|
4
|
+
# A collection class for managing a set of command context attributes. This class provides a simple interface
|
5
|
+
# for storing, accessing, and iterating over {Attribute} instances.
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# set = AttributeSet.new
|
9
|
+
# set.add(Attribute.new(:name))
|
10
|
+
# set[:name] # => #<Attribute name=:name>
|
11
|
+
#
|
12
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
13
|
+
# @since 0.1.0
|
14
|
+
class AttributeSet
|
15
|
+
@lookup: Hash[Symbol, Attribute]
|
16
|
+
|
17
|
+
# Creates a new AttributeSet instance
|
18
|
+
#
|
19
|
+
# @return [AttributeSet]
|
20
|
+
def initialize: () -> void
|
21
|
+
|
22
|
+
# Retrieves an attribute by name
|
23
|
+
#
|
24
|
+
# @param attribute_name [String, Symbol] The name of the attribute to retrieve
|
25
|
+
#
|
26
|
+
# @return [Attribute, nil] The attribute with the given name, or nil if not found
|
27
|
+
def []: (String | Symbol attribute_name) -> Attribute?
|
28
|
+
|
29
|
+
# Adds an attribute to the set
|
30
|
+
#
|
31
|
+
# @param attribute [Attribute] The attribute to add
|
32
|
+
#
|
33
|
+
# @raise [ArgumentError] If the provided attribute is not an {Attribute} instance
|
34
|
+
# @return [void]
|
35
|
+
def add: (Attribute attribute) -> void
|
36
|
+
|
37
|
+
# Returns all attributes in the set
|
38
|
+
#
|
39
|
+
# @return [Array<Attribute>] An array of all attributes
|
40
|
+
def all: () -> Array[Attribute]
|
41
|
+
|
42
|
+
# Iterates over each attribute in the set
|
43
|
+
#
|
44
|
+
# @yield [Attribute] Each attribute in the set
|
45
|
+
#
|
46
|
+
# @return [void]
|
47
|
+
def each: () { (Attribute) -> untyped } -> void
|
48
|
+
|
49
|
+
# Iterates over each attribute in the set with an object
|
50
|
+
#
|
51
|
+
# @overload each_with_object(object)
|
52
|
+
# @param object [Object] The object to pass to the block
|
53
|
+
# @yield [Attribute, Object] Each attribute and the object
|
54
|
+
#
|
55
|
+
# @return [Object] The final state of the object
|
56
|
+
def each_with_object: [U] (U object) { (Attribute, U) -> untyped } -> U
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
# Ensure that Attributes are duplicated when the AttributeSet is duplicated
|
61
|
+
#
|
62
|
+
# @param source [AttributeSet] The source AttributeSet to copy
|
63
|
+
#
|
64
|
+
# @return [AttributeSet]
|
65
|
+
def initialize_copy: (untyped source) -> untyped
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Domainic
|
2
|
+
module Command
|
3
|
+
module Context
|
4
|
+
# A module that provides attribute management for command contexts. When included in a class, it provides
|
5
|
+
# a DSL for defining and managing typed attributes with validation, default values, and thread-safe access.
|
6
|
+
#
|
7
|
+
# ## Thread Safety
|
8
|
+
# The attribute system is designed to be thread-safe during class definition and inheritance. A class-level
|
9
|
+
# mutex protects the attribute registry during:
|
10
|
+
# * Definition of new attributes via the DSL
|
11
|
+
# * Inheritance of attributes to subclasses
|
12
|
+
#
|
13
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
14
|
+
# @since 0.1.0
|
15
|
+
module Behavior
|
16
|
+
def self.included: (Class | Module base) -> void
|
17
|
+
|
18
|
+
# Provides class-level methods for defining and managing attributes. These methods are
|
19
|
+
# automatically extended onto any class that includes {Behavior}.
|
20
|
+
#
|
21
|
+
# @since 0.1.0
|
22
|
+
module ClassMethods
|
23
|
+
@attributes: AttributeSet
|
24
|
+
|
25
|
+
@attribute_lock: Mutex
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
# Defines a new attribute for the context.
|
30
|
+
#
|
31
|
+
# @overload attribute(name, *type_validator_and_description, **options)
|
32
|
+
# @param name [String, Symbol] The name of the attribute
|
33
|
+
# @param type_validator_and_description [Array<Class, Module, Object, Proc, String, nil>] Type validator or
|
34
|
+
# description arguments
|
35
|
+
# @param options [Hash] Configuration options for the attribute
|
36
|
+
# @option options [Object] :default A static default value
|
37
|
+
# @option options [Proc] :default_generator A proc that generates the default value
|
38
|
+
# @option options [Object] :default_value Alias for :default
|
39
|
+
# @option options [String, nil] :desc Short description of the attribute
|
40
|
+
# @option options [String, nil] :description Full description of the attribute
|
41
|
+
# @option options [Boolean] :required Whether the attribute is required
|
42
|
+
# @option options [Class, Module, Object, Proc] :type A type validator
|
43
|
+
#
|
44
|
+
# @return [void]
|
45
|
+
def attribute: (String | Symbol name, *(Class | Module | Object | Proc | String)? type_validator_and_description, ?default: untyped, ?default_generator: untyped, ?default_value: untyped, ?desc: String?, ?description: String?, ?required: bool, ?type: Class | Module | Object | Proc) -> void
|
46
|
+
|
47
|
+
# Returns the mutex used to synchronize attribute operations.
|
48
|
+
#
|
49
|
+
# @return [Mutex]
|
50
|
+
def attribute_lock: () -> Mutex
|
51
|
+
|
52
|
+
# Returns the set of attributes defined for this context.
|
53
|
+
#
|
54
|
+
# @return [AttributeSet]
|
55
|
+
def attributes: () -> AttributeSet
|
56
|
+
|
57
|
+
# Handles inheritance of attributes to subclasses.
|
58
|
+
#
|
59
|
+
# @param subclass [Class, Module] The inheriting class
|
60
|
+
#
|
61
|
+
# @return [void]
|
62
|
+
def inherited: (Class | Module subclass) -> void
|
63
|
+
end
|
64
|
+
|
65
|
+
# Initializes a new context instance with the given attributes.
|
66
|
+
#
|
67
|
+
# @param options [Hash{String, Symbol => Object}] Attribute values for initialization
|
68
|
+
#
|
69
|
+
# @raise [ArgumentError] If any attribute values are invalid
|
70
|
+
# @return [Behavior]
|
71
|
+
def initialize: (**untyped options) -> void
|
72
|
+
|
73
|
+
# Returns a hash of all attribute names and their values.
|
74
|
+
#
|
75
|
+
# @return [Hash{Symbol => Object}] A hash of attribute values
|
76
|
+
def to_hash: () -> Hash[Symbol, untyped]
|
77
|
+
|
78
|
+
alias to_h to_hash
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Domainic
|
2
|
+
module Command
|
3
|
+
module Context
|
4
|
+
# A context class for managing command input arguments. This class provides a structured way to define,
|
5
|
+
# validate, and access input parameters for commands.
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# class MyInputContext < Domainic::Command::Context::InputContext
|
9
|
+
# argument :name, String, "The name to process"
|
10
|
+
# argument :count, Integer, default: 1
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
14
|
+
# @since 0.1.0
|
15
|
+
class InputContext
|
16
|
+
extend Behavior::ClassMethods
|
17
|
+
|
18
|
+
include Behavior
|
19
|
+
|
20
|
+
# Defines an input argument for the command
|
21
|
+
#
|
22
|
+
# @overload argument(name, *type_validator_and_description, **options)
|
23
|
+
# @param name [String, Symbol] The name of the argument
|
24
|
+
# @param type_validator_and_description [Array<Class, Module, Object, Proc, String, nil>] Type validator or
|
25
|
+
# description arguments
|
26
|
+
# @param options [Hash] Configuration options for the argument
|
27
|
+
# @option options [Object] :default A static default value
|
28
|
+
# @option options [Proc] :default_generator A proc that generates the default value
|
29
|
+
# @option options [Object] :default_value Alias for :default
|
30
|
+
# @option options [String, nil] :desc Short description of the argument
|
31
|
+
# @option options [String, nil] :description Full description of the argument
|
32
|
+
# @option options [Boolean] :required Whether the argument is required
|
33
|
+
# @option options [Class, Module, Object, Proc] :type A type validator
|
34
|
+
#
|
35
|
+
# @return [void]
|
36
|
+
def self.argument: (String | Symbol name, *(Class | Module | Object | Proc | String)? type_validator_and_description, ?default: untyped, ?default_generator: untyped, ?default_value: untyped, ?desc: String?, ?description: String?, ?required: bool, ?type: Class | Module | Object | Proc) -> void
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Domainic
|
2
|
+
module Command
|
3
|
+
module Context
|
4
|
+
# A context class for managing command output values. This class provides a structured way to define,
|
5
|
+
# validate, and access the return values from commands.
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# class MyOutputContext < Domainic::Command::Context::OutputContext
|
9
|
+
# field :processed_name, String, "The processed name"
|
10
|
+
# field :status, Symbol, default: :success
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
14
|
+
# @since 0.1.0
|
15
|
+
class OutputContext
|
16
|
+
extend Behavior::ClassMethods
|
17
|
+
|
18
|
+
include Behavior
|
19
|
+
|
20
|
+
# Defines a return value for the command
|
21
|
+
#
|
22
|
+
# @overload field(name, *type_validator_and_description, **options)
|
23
|
+
# @param name [String, Symbol] The name of the return value
|
24
|
+
# @param type_validator_and_description [Array<Class, Module, Object, Proc, String, nil>] Type validator or
|
25
|
+
# description arguments
|
26
|
+
# @param options [Hash] Configuration options for the return value
|
27
|
+
# @option options [Object] :default A static default value
|
28
|
+
# @option options [Proc] :default_generator A proc that generates the default value
|
29
|
+
# @option options [Object] :default_value Alias for :default
|
30
|
+
# @option options [String, nil] :desc Short description of the return value
|
31
|
+
# @option options [String, nil] :description Full description of the return value
|
32
|
+
# @option options [Boolean] :required Whether the return value is required
|
33
|
+
# @option options [Class, Module, Object, Proc] :type A type validator
|
34
|
+
#
|
35
|
+
# @return [void]
|
36
|
+
def self.field: (String | Symbol name, *(Class | Module | Object | Proc | String)? type_validator_and_description, ?default: untyped, ?default_generator: untyped, ?default_value: untyped, ?desc: String?, ?description: String?, ?required: bool, ?type: Class | Module | Object | Proc) -> void
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module Domainic
|
2
|
+
module Command
|
3
|
+
module Context
|
4
|
+
# A flexible context class for managing command state during execution. This class provides a dynamic
|
5
|
+
# storage mechanism for command data, allowing both hash-style and method-style access to values.
|
6
|
+
#
|
7
|
+
# The RuntimeContext serves as a mutable workspace during command execution, bridging the gap between
|
8
|
+
# input parameters and output values. It automatically handles type coercion of keys to symbols and
|
9
|
+
# provides safe value duplication when converting to a hash.
|
10
|
+
#
|
11
|
+
# @example Hash-style access
|
12
|
+
# context = RuntimeContext.new(count: 1)
|
13
|
+
# context[:count] #=> 1
|
14
|
+
# context[:count] = 2
|
15
|
+
# context[:count] #=> 2
|
16
|
+
#
|
17
|
+
# @example Method-style access
|
18
|
+
# context = RuntimeContext.new(name: "test")
|
19
|
+
# context.name #=> "test"
|
20
|
+
# context.name = "new test"
|
21
|
+
# context.name #=> "new test"
|
22
|
+
#
|
23
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
24
|
+
# @since 0.1.0
|
25
|
+
class RuntimeContext
|
26
|
+
@data: Hash[Symbol, untyped]
|
27
|
+
|
28
|
+
# Creates a new RuntimeContext with the given options
|
29
|
+
#
|
30
|
+
# @param options [Hash] Initial values for the context
|
31
|
+
#
|
32
|
+
# @return [RuntimeContext]
|
33
|
+
def initialize: (**untyped options) -> void
|
34
|
+
|
35
|
+
# Retrieves a value by its attribute name
|
36
|
+
#
|
37
|
+
# @param attribute_name [String, Symbol] The name of the attribute to retrieve
|
38
|
+
#
|
39
|
+
# @return [Object, nil] The value associated with the attribute name
|
40
|
+
def []: (String | Symbol attribute_name) -> untyped
|
41
|
+
|
42
|
+
# Sets a value for the given attribute name
|
43
|
+
#
|
44
|
+
# @param attribute_name [String, Symbol] The name of the attribute to set
|
45
|
+
# @param value [Object] The value to store
|
46
|
+
#
|
47
|
+
# @return [Object] The stored value
|
48
|
+
def []=: (String | Symbol attribute_name, untyped value) -> untyped
|
49
|
+
|
50
|
+
# Converts the context to a hash, duplicating values where appropriate
|
51
|
+
#
|
52
|
+
# @note Class and Module values are not duplicated to prevent potential issues
|
53
|
+
#
|
54
|
+
# @return [Hash{Symbol => Object}] A hash containing all stored values
|
55
|
+
def to_hash: () -> Hash[Symbol, untyped]
|
56
|
+
|
57
|
+
alias to_h to_hash
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
# Handles dynamic method calls for reading and writing attributes
|
62
|
+
#
|
63
|
+
# @return [Object, nil]
|
64
|
+
def method_missing: ...
|
65
|
+
|
66
|
+
# Reads a value from the internal storage
|
67
|
+
#
|
68
|
+
# @param attribute_name [String, Symbol] The name of the attribute to read
|
69
|
+
#
|
70
|
+
# @return [Object, nil] The stored value
|
71
|
+
def read_from_attribute: (String | Symbol attribute_name) -> untyped
|
72
|
+
|
73
|
+
# Determines if a method name can be handled dynamically
|
74
|
+
#
|
75
|
+
# @param method_name [Symbol] The name of the method to check
|
76
|
+
# @param _include_private [Boolean] Whether to include private methods
|
77
|
+
#
|
78
|
+
# @return [Boolean] Whether the method can be handled
|
79
|
+
def respond_to_missing?: (String | Symbol method_name, ?bool _include_private) -> bool
|
80
|
+
|
81
|
+
# Writes a value to the internal storage
|
82
|
+
#
|
83
|
+
# @param attribute_name [String, Symbol] The name of the attribute to write
|
84
|
+
# @param value [Object] The value to store
|
85
|
+
# @return [Object] The stored value
|
86
|
+
def write_to_attribute: (String | Symbol attribute_name, untyped value) -> untyped
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Domainic
|
2
|
+
module Command
|
3
|
+
# Base error class for command-related errors. This class serves as the root of the command error
|
4
|
+
# hierarchy, allowing for specific error handling of command-related issues.
|
5
|
+
#
|
6
|
+
# @note This is an abstract class and should not be instantiated directly. Instead, use one of its
|
7
|
+
# subclasses for specific error cases.
|
8
|
+
#
|
9
|
+
# @example Rescuing command errors
|
10
|
+
# begin
|
11
|
+
# # Command execution code
|
12
|
+
# rescue Domainic::Command::Error => e
|
13
|
+
# # Handle any command-related error
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
17
|
+
# @since 0.1.0
|
18
|
+
class Error < StandardError
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Domainic
|
2
|
+
module Command
|
3
|
+
# Error class raised when a command encounters an execution failure. This class provides access to
|
4
|
+
# both the error message and the {Result} object containing detailed information about the failure.
|
5
|
+
#
|
6
|
+
# @example Handling execution errors
|
7
|
+
# begin
|
8
|
+
# command.call!
|
9
|
+
# rescue Domainic::Command::ExecutionError => e
|
10
|
+
# puts e.message # Access the error message
|
11
|
+
# puts e.result.errors # Access the detailed errors
|
12
|
+
# puts e.result.status_code # Access the status code
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
16
|
+
# @since 0.1.0
|
17
|
+
class ExecutionError < Error
|
18
|
+
# The {Result} object containing detailed information about the execution failure
|
19
|
+
#
|
20
|
+
# @return [Result] The result object associated with the failure
|
21
|
+
attr_reader result: Result
|
22
|
+
|
23
|
+
# Creates a new execution error with the given message and result
|
24
|
+
#
|
25
|
+
# @param message [String] The error message describing what went wrong
|
26
|
+
# @param result [Result] The result object containing detailed failure information
|
27
|
+
#
|
28
|
+
# @return [void]
|
29
|
+
def initialize: (String message, Result result) -> void
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Domainic
|
2
|
+
module Command
|
3
|
+
# Instance methods that are included in any class that includes {Command}. These methods provide
|
4
|
+
# the core execution logic and error handling for commands.
|
5
|
+
#
|
6
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
7
|
+
# @since 0.1.0
|
8
|
+
module InstanceMethods
|
9
|
+
# Executes the command with the given context, handling any errors
|
10
|
+
#
|
11
|
+
# @param context [Hash] The input context for the command
|
12
|
+
#
|
13
|
+
# @return [Result] The result of the command execution
|
14
|
+
def call: (**untyped context) -> Result
|
15
|
+
|
16
|
+
# Executes the command with the given context, raising any errors
|
17
|
+
#
|
18
|
+
# @param input [Hash] The input context for the command
|
19
|
+
#
|
20
|
+
# @raise [ExecutionError] If the command execution fails
|
21
|
+
# @return [Result] The result of the command execution
|
22
|
+
def call!: (**untyped context) -> Result
|
23
|
+
|
24
|
+
# Executes the command's business logic
|
25
|
+
#
|
26
|
+
# @abstract Subclass and override {#execute} to implement command behavior
|
27
|
+
#
|
28
|
+
# @raise [NotImplementedError] If the subclass does not implement {#execute}
|
29
|
+
# @return [void]
|
30
|
+
def execute: () -> void
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
# The runtime context for the command execution
|
35
|
+
#
|
36
|
+
# @return [Context::RuntimeContext] The runtime context
|
37
|
+
attr_reader context: Context::RuntimeContext
|
38
|
+
|
39
|
+
# Execute the command with the given input context
|
40
|
+
#
|
41
|
+
# @param input [Hash] The input context for the command
|
42
|
+
#
|
43
|
+
# @return [Result] The result of the command execution
|
44
|
+
def __execute_command!: (Hash[String | Symbol, untyped] input) -> Result
|
45
|
+
|
46
|
+
# Validates an input or output context
|
47
|
+
#
|
48
|
+
# @param context_type [Symbol] The type of context to validate
|
49
|
+
# @param context [Hash] The context data to validate
|
50
|
+
#
|
51
|
+
# @raise [ExecutionError] If the context is invalid
|
52
|
+
# @return [Context::InputContext, Context::OutputContext] The validated context
|
53
|
+
def __validate_context!: (:input | :output context_type, Hash[String | Symbol, untyped] context) -> (Context::InputContext | Context::OutputContext)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|