domainic-command 0.1.0.alpha.1.0.0 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|