axn 0.1.0.pre.alpha.2.8.1 → 0.1.0.pre.alpha.4
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/.cursor/commands/pr.md +36 -0
- data/.cursor/rules/axn-framework-patterns.mdc +43 -0
- data/.cursor/rules/general-coding-standards.mdc +27 -0
- data/.cursor/rules/spec/testing-patterns.mdc +40 -0
- data/CHANGELOG.md +57 -0
- data/Rakefile +114 -4
- data/docs/.vitepress/config.mjs +19 -10
- data/docs/advanced/conventions.md +3 -3
- data/docs/advanced/mountable.md +476 -0
- data/docs/advanced/profiling.md +351 -0
- data/docs/advanced/rough.md +27 -8
- data/docs/index.md +5 -3
- data/docs/intro/about.md +1 -1
- data/docs/intro/overview.md +6 -6
- data/docs/recipes/formatting-context-for-error-tracking.md +186 -0
- data/docs/recipes/memoization.md +103 -18
- data/docs/recipes/rubocop-integration.md +38 -284
- data/docs/recipes/testing.md +14 -14
- data/docs/recipes/validating-user-input.md +1 -1
- data/docs/reference/async.md +429 -0
- data/docs/reference/axn-result.md +107 -0
- data/docs/reference/class.md +225 -64
- data/docs/reference/configuration.md +366 -34
- data/docs/reference/form-object.md +252 -0
- data/docs/reference/instance.md +14 -29
- data/docs/strategies/client.md +212 -0
- data/docs/strategies/form.md +235 -0
- data/docs/strategies/index.md +21 -21
- data/docs/strategies/transaction.md +1 -1
- data/docs/usage/setup.md +16 -2
- data/docs/usage/steps.md +7 -7
- data/docs/usage/using.md +23 -12
- data/docs/usage/writing.md +191 -12
- data/lib/axn/async/adapters/active_job.rb +74 -0
- data/lib/axn/async/adapters/disabled.rb +41 -0
- data/lib/axn/async/adapters/sidekiq.rb +67 -0
- data/lib/axn/async/adapters.rb +26 -0
- data/lib/axn/async/batch_enqueue/config.rb +38 -0
- data/lib/axn/async/batch_enqueue.rb +99 -0
- data/lib/axn/async/enqueue_all_orchestrator.rb +363 -0
- data/lib/axn/async.rb +178 -0
- data/lib/axn/configuration.rb +113 -0
- data/lib/{action → axn}/context.rb +22 -4
- data/lib/axn/core/automatic_logging.rb +89 -0
- data/lib/axn/core/context/facade.rb +69 -0
- data/lib/{action → axn}/core/context/facade_inspector.rb +32 -5
- data/lib/{action → axn}/core/context/internal.rb +5 -5
- data/lib/{action → axn}/core/contract.rb +111 -73
- data/lib/{action → axn}/core/contract_for_subfields.rb +30 -35
- data/lib/{action → axn}/core/contract_validation.rb +27 -12
- data/lib/axn/core/contract_validation_for_subfields.rb +165 -0
- data/lib/axn/core/default_call.rb +63 -0
- data/lib/axn/core/field_resolvers/extract.rb +32 -0
- data/lib/axn/core/field_resolvers/model.rb +63 -0
- data/lib/axn/core/field_resolvers.rb +24 -0
- data/lib/{action → axn}/core/flow/callbacks.rb +7 -7
- data/lib/{action → axn}/core/flow/exception_execution.rb +9 -13
- data/lib/{action → axn}/core/flow/handlers/base_descriptor.rb +3 -2
- data/lib/{action → axn}/core/flow/handlers/descriptors/callback_descriptor.rb +2 -2
- data/lib/{action → axn}/core/flow/handlers/descriptors/message_descriptor.rb +23 -11
- data/lib/axn/core/flow/handlers/invoker.rb +47 -0
- data/lib/{action → axn}/core/flow/handlers/matcher.rb +9 -19
- data/lib/{action → axn}/core/flow/handlers/registry.rb +3 -1
- data/lib/{action → axn}/core/flow/handlers/resolvers/base_resolver.rb +1 -1
- data/lib/{action → axn}/core/flow/handlers/resolvers/callback_resolver.rb +2 -2
- data/lib/{action → axn}/core/flow/handlers/resolvers/message_resolver.rb +12 -3
- data/lib/axn/core/flow/handlers.rb +20 -0
- data/lib/{action → axn}/core/flow/messages.rb +8 -8
- data/lib/{action → axn}/core/flow.rb +4 -4
- data/lib/{action → axn}/core/hooks.rb +17 -5
- data/lib/axn/core/logging.rb +48 -0
- data/lib/axn/core/memoization.rb +53 -0
- data/lib/{action → axn}/core/nesting_tracking.rb +1 -1
- data/lib/{action → axn}/core/timing.rb +1 -1
- data/lib/axn/core/tracing.rb +90 -0
- data/lib/axn/core/use_strategy.rb +29 -0
- data/lib/{action → axn}/core/validation/fields.rb +26 -2
- data/lib/{action → axn}/core/validation/subfields.rb +14 -12
- data/lib/axn/core/validation/validators/model_validator.rb +36 -0
- data/lib/axn/core/validation/validators/type_validator.rb +80 -0
- data/lib/{action → axn}/core/validation/validators/validate_validator.rb +12 -2
- data/lib/{action → axn}/core.rb +55 -55
- data/lib/{action → axn}/exceptions.rb +12 -2
- data/lib/axn/extras/strategies/client.rb +150 -0
- data/lib/axn/extras/strategies/vernier.rb +121 -0
- data/lib/axn/extras.rb +4 -0
- data/lib/axn/factory.rb +122 -34
- data/lib/axn/form_object.rb +90 -0
- data/lib/axn/internal/logging.rb +30 -0
- data/lib/axn/internal/registry.rb +87 -0
- data/lib/axn/mountable/descriptor.rb +76 -0
- data/lib/axn/mountable/helpers/class_builder.rb +193 -0
- data/lib/axn/mountable/helpers/mounter.rb +33 -0
- data/lib/axn/mountable/helpers/namespace_manager.rb +38 -0
- data/lib/axn/mountable/helpers/validator.rb +112 -0
- data/lib/axn/mountable/inherit_profiles.rb +72 -0
- data/lib/axn/mountable/mounting_strategies/_base.rb +87 -0
- data/lib/axn/mountable/mounting_strategies/axn.rb +48 -0
- data/lib/axn/mountable/mounting_strategies/method.rb +95 -0
- data/lib/axn/mountable/mounting_strategies/step.rb +69 -0
- data/lib/axn/mountable/mounting_strategies.rb +32 -0
- data/lib/axn/mountable.rb +119 -0
- data/lib/axn/rails/engine.rb +51 -0
- data/lib/axn/rails/generators/axn_generator.rb +86 -0
- data/lib/axn/rails/generators/templates/action.rb.erb +17 -0
- data/lib/axn/rails/generators/templates/action_spec.rb.erb +25 -0
- data/lib/{action → axn}/result.rb +32 -13
- data/lib/axn/strategies/form.rb +98 -0
- data/lib/axn/strategies/transaction.rb +26 -0
- data/lib/axn/strategies.rb +20 -0
- data/lib/axn/testing/spec_helpers.rb +6 -8
- data/lib/axn/util/callable.rb +120 -0
- data/lib/axn/util/contract_error_handling.rb +32 -0
- data/lib/axn/util/execution_context.rb +34 -0
- data/lib/axn/util/global_id_serialization.rb +52 -0
- data/lib/axn/util/logging.rb +87 -0
- data/lib/axn/util/memoization.rb +20 -0
- data/lib/axn/version.rb +1 -1
- data/lib/axn.rb +26 -16
- data/lib/rubocop/cop/axn/README.md +23 -23
- data/lib/rubocop/cop/axn/unchecked_result.rb +138 -17
- metadata +106 -64
- data/.rspec +0 -3
- data/.rubocop.yml +0 -76
- data/.tool-versions +0 -1
- data/docs/reference/action-result.md +0 -37
- data/lib/action/attachable/base.rb +0 -43
- data/lib/action/attachable/steps.rb +0 -63
- data/lib/action/attachable/subactions.rb +0 -70
- data/lib/action/attachable.rb +0 -17
- data/lib/action/configuration.rb +0 -55
- data/lib/action/core/automatic_logging.rb +0 -93
- data/lib/action/core/context/facade.rb +0 -48
- data/lib/action/core/flow/handlers/invoker.rb +0 -73
- data/lib/action/core/flow/handlers.rb +0 -20
- data/lib/action/core/logging.rb +0 -37
- data/lib/action/core/tracing.rb +0 -17
- data/lib/action/core/use_strategy.rb +0 -30
- data/lib/action/core/validation/validators/model_validator.rb +0 -34
- data/lib/action/core/validation/validators/type_validator.rb +0 -30
- data/lib/action/enqueueable/via_sidekiq.rb +0 -76
- data/lib/action/enqueueable.rb +0 -13
- data/lib/action/strategies/transaction.rb +0 -19
- data/lib/action/strategies.rb +0 -48
- data/lib/axn/util.rb +0 -24
- data/package.json +0 -10
- data/yarn.lock +0 -1166
|
@@ -3,13 +3,17 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Axn
|
|
6
|
-
# This cop enforces that when calling
|
|
6
|
+
# This cop enforces that when calling Axns from within other Axns,
|
|
7
7
|
# you must either use `call!` (with the bang) or check `result.ok?`.
|
|
8
8
|
#
|
|
9
|
+
# When the ActionsNamespace configuration is set (e.g., to "Actions"),
|
|
10
|
+
# the cop will only check calls on classes under that namespace,
|
|
11
|
+
# reducing false positives from other service objects.
|
|
12
|
+
#
|
|
9
13
|
# @example
|
|
10
14
|
# # bad
|
|
11
15
|
# class OuterAction
|
|
12
|
-
# include
|
|
16
|
+
# include Axn
|
|
13
17
|
# def call
|
|
14
18
|
# InnerAction.call(param: "value") # Missing result check
|
|
15
19
|
# end
|
|
@@ -17,7 +21,7 @@ module RuboCop
|
|
|
17
21
|
#
|
|
18
22
|
# # good
|
|
19
23
|
# class OuterAction
|
|
20
|
-
# include
|
|
24
|
+
# include Axn
|
|
21
25
|
# def call
|
|
22
26
|
# result = InnerAction.call(param: "value")
|
|
23
27
|
# return result unless result.ok?
|
|
@@ -27,17 +31,68 @@ module RuboCop
|
|
|
27
31
|
#
|
|
28
32
|
# # also good
|
|
29
33
|
# class OuterAction
|
|
30
|
-
# include
|
|
34
|
+
# include Axn
|
|
31
35
|
# def call
|
|
32
36
|
# InnerAction.call!(param: "value") # Using call! ensures exceptions bubble up
|
|
33
37
|
# end
|
|
34
38
|
# end
|
|
35
39
|
#
|
|
40
|
+
# @example With ActionsNamespace configured as string
|
|
41
|
+
# # .rubocop.yml
|
|
42
|
+
# Axn/UncheckedResult:
|
|
43
|
+
# ActionsNamespace: "Actions"
|
|
44
|
+
#
|
|
45
|
+
# # This will only check Actions::* classes, not other service objects
|
|
46
|
+
# class OuterAction
|
|
47
|
+
# include Axn
|
|
48
|
+
# def call
|
|
49
|
+
# SomeService.call(param: "value") # Won't trigger cop
|
|
50
|
+
# Actions::InnerAction.call(param: "value") # Will trigger cop
|
|
51
|
+
# end
|
|
52
|
+
# end
|
|
53
|
+
#
|
|
54
|
+
# @example With ActionsNamespace configured as array
|
|
55
|
+
# # .rubocop.yml
|
|
56
|
+
# Axn/UncheckedResult:
|
|
57
|
+
# ActionsNamespace: ["Actions", "Services"]
|
|
58
|
+
#
|
|
59
|
+
# # This will check both Actions::* and Services::* classes
|
|
60
|
+
# class OuterAction
|
|
61
|
+
# include Axn
|
|
62
|
+
# def call
|
|
63
|
+
# SomeService.call(param: "value") # Won't trigger cop
|
|
64
|
+
# Actions::InnerAction.call(param: "value") # Will trigger cop
|
|
65
|
+
# Services::SomeService.call(param: "value") # Will trigger cop
|
|
66
|
+
# end
|
|
67
|
+
# end
|
|
68
|
+
#
|
|
36
69
|
# rubocop:disable Metrics/ClassLength
|
|
37
70
|
class UncheckedResult < RuboCop::Cop::Base
|
|
38
71
|
extend RuboCop::Cop::AutoCorrector
|
|
39
72
|
|
|
40
|
-
MSG = "Use `call!` or check `result.ok?` when calling
|
|
73
|
+
MSG = "Use `call!` or check `result.ok?` when calling Axns from within Axns"
|
|
74
|
+
|
|
75
|
+
# Define the configuration schema
|
|
76
|
+
def self.configuration_schema
|
|
77
|
+
@configuration_schema ||= RuboCop::ConfigSchema::Schema.new(
|
|
78
|
+
{
|
|
79
|
+
"ActionsNamespace" => {
|
|
80
|
+
"type" => %w[string array],
|
|
81
|
+
"description" => 'Only check calls on classes under this namespace (e.g., "Actions") or array of namespaces (e.g., ["Actions", "Services"])',
|
|
82
|
+
},
|
|
83
|
+
"CheckNested" => {
|
|
84
|
+
"type" => "boolean",
|
|
85
|
+
"description" => "Check nested Axn calls",
|
|
86
|
+
"default" => true,
|
|
87
|
+
},
|
|
88
|
+
"CheckNonNested" => {
|
|
89
|
+
"type" => "boolean",
|
|
90
|
+
"description" => "Check non-nested Axn calls",
|
|
91
|
+
"default" => true,
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
)
|
|
95
|
+
end
|
|
41
96
|
|
|
42
97
|
# Configuration options
|
|
43
98
|
def check_nested?
|
|
@@ -48,20 +103,20 @@ module RuboCop
|
|
|
48
103
|
cop_config["CheckNonNested"] != false
|
|
49
104
|
end
|
|
50
105
|
|
|
51
|
-
# Track whether we're inside an
|
|
106
|
+
# Track whether we're inside an Axn class and its call method
|
|
52
107
|
def_node_search :action_class?, <<~PATTERN
|
|
53
|
-
(class _ (const nil? :
|
|
108
|
+
(class _ (const nil? :Axn) ...)
|
|
54
109
|
PATTERN
|
|
55
110
|
|
|
56
111
|
def_node_search :includes_action?, <<~PATTERN
|
|
57
|
-
(send nil? :include (const nil? :
|
|
112
|
+
(send nil? :include (const nil? :Axn))
|
|
58
113
|
PATTERN
|
|
59
114
|
|
|
60
115
|
def_node_search :call_method?, <<~PATTERN
|
|
61
116
|
(def :call ...)
|
|
62
117
|
PATTERN
|
|
63
118
|
|
|
64
|
-
def_node_search :
|
|
119
|
+
def_node_search :axn_call?, <<~PATTERN
|
|
65
120
|
(send (const _ _) :call ...)
|
|
66
121
|
PATTERN
|
|
67
122
|
|
|
@@ -102,9 +157,10 @@ module RuboCop
|
|
|
102
157
|
PATTERN
|
|
103
158
|
|
|
104
159
|
def on_send(node)
|
|
105
|
-
return unless
|
|
160
|
+
return unless axn_call?(node)
|
|
161
|
+
return unless axn_action_call?(node)
|
|
106
162
|
return if bang_call?(node)
|
|
107
|
-
return unless
|
|
163
|
+
return unless inside_axn_call_method?(node)
|
|
108
164
|
|
|
109
165
|
# Check if we should process this call based on configuration
|
|
110
166
|
is_inside_action = inside_action_context?(node)
|
|
@@ -117,8 +173,73 @@ module RuboCop
|
|
|
117
173
|
|
|
118
174
|
private
|
|
119
175
|
|
|
120
|
-
def
|
|
121
|
-
#
|
|
176
|
+
def axn_action_call?(node)
|
|
177
|
+
# Get the receiver of the call method
|
|
178
|
+
receiver = node.children[0]
|
|
179
|
+
return false unless receiver&.type == :const
|
|
180
|
+
|
|
181
|
+
# Get the constant name - handle both simple constants and namespaced constants
|
|
182
|
+
const_name = get_constant_name(receiver)
|
|
183
|
+
return false unless const_name
|
|
184
|
+
|
|
185
|
+
# Check if we have the Actions namespace configured
|
|
186
|
+
namespace = actions_namespace
|
|
187
|
+
|
|
188
|
+
if namespace
|
|
189
|
+
# Handle both string and array configurations
|
|
190
|
+
case namespace
|
|
191
|
+
when String
|
|
192
|
+
return const_name.start_with?("#{namespace}::")
|
|
193
|
+
when Array
|
|
194
|
+
# If array is empty, fall back to checking all calls
|
|
195
|
+
return true if namespace.empty?
|
|
196
|
+
|
|
197
|
+
return namespace.any? { |ns| const_name.start_with?("#{ns}::") }
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# If no namespace is configured, we can't be as precise
|
|
202
|
+
# Fall back to checking if the class includes Axn (more complex)
|
|
203
|
+
true
|
|
204
|
+
rescue StandardError => _e
|
|
205
|
+
# If there's any error, assume it's not an Axn action call
|
|
206
|
+
false
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def get_constant_name(const_node)
|
|
210
|
+
# Handle both simple constants (const :SomeClass) and namespaced constants (const (const nil :Actions) :SomeClass)
|
|
211
|
+
if const_node.children[0]&.type == :const
|
|
212
|
+
# This is a namespaced constant like Actions::SomeClass
|
|
213
|
+
namespace = get_constant_name(const_node.children[0])
|
|
214
|
+
class_name = const_node.children[1]
|
|
215
|
+
"#{namespace}::#{class_name}"
|
|
216
|
+
else
|
|
217
|
+
# This is a simple constant like SomeClass
|
|
218
|
+
const_node.children[1]
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def actions_namespace
|
|
223
|
+
# First try to get from RuboCop configuration
|
|
224
|
+
config_value = cop_config["ActionsNamespace"]
|
|
225
|
+
return nil unless config_value
|
|
226
|
+
|
|
227
|
+
# Handle both string and array configurations
|
|
228
|
+
case config_value
|
|
229
|
+
when String
|
|
230
|
+
config_value
|
|
231
|
+
when Array
|
|
232
|
+
config_value.map(&:to_s)
|
|
233
|
+
else
|
|
234
|
+
config_value.to_s
|
|
235
|
+
end
|
|
236
|
+
rescue StandardError => _e
|
|
237
|
+
# If there's any error accessing the configuration, return nil
|
|
238
|
+
nil
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def inside_axn_call_method?(node)
|
|
242
|
+
# Check if we're inside a call method of an Axn class
|
|
122
243
|
current_node = node
|
|
123
244
|
while current_node.parent
|
|
124
245
|
current_node = current_node.parent
|
|
@@ -126,19 +247,19 @@ module RuboCop
|
|
|
126
247
|
# Check if we're inside a def :call
|
|
127
248
|
next unless call_method?(current_node) && current_node.method_name == :call
|
|
128
249
|
|
|
129
|
-
# Now check if this class includes
|
|
250
|
+
# Now check if this class includes Axn
|
|
130
251
|
class_node = find_enclosing_class(current_node)
|
|
131
252
|
return includes_action?(class_node) if class_node
|
|
132
253
|
end
|
|
133
254
|
false
|
|
134
255
|
rescue StandardError => _e
|
|
135
|
-
# If there's any error in the analysis, assume we're not in an
|
|
256
|
+
# If there's any error in the analysis, assume we're not in an Axn call method
|
|
136
257
|
# This prevents the cop from crashing on complex or malformed code
|
|
137
258
|
false
|
|
138
259
|
end
|
|
139
260
|
|
|
140
261
|
def inside_action_context?(node)
|
|
141
|
-
# Check if this
|
|
262
|
+
# Check if this Axn call is inside an Axn class's call method
|
|
142
263
|
current_node = node
|
|
143
264
|
while current_node.parent
|
|
144
265
|
current_node = current_node.parent
|
|
@@ -146,7 +267,7 @@ module RuboCop
|
|
|
146
267
|
# Check if we're inside a def :call
|
|
147
268
|
next unless call_method?(current_node) && current_node.method_name == :call
|
|
148
269
|
|
|
149
|
-
# Now check if this class includes
|
|
270
|
+
# Now check if this class includes Axn
|
|
150
271
|
class_node = find_enclosing_class(current_node)
|
|
151
272
|
return true if class_node && includes_action?(class_node)
|
|
152
273
|
end
|
metadata
CHANGED
|
@@ -1,54 +1,55 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: axn
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.0.pre.alpha.
|
|
4
|
+
version: 0.1.0.pre.alpha.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kali Donovan
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-01-21 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activemodel
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
|
-
- - "
|
|
17
|
+
- - ">="
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '7.
|
|
19
|
+
version: '7.2'
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
|
-
- - "
|
|
24
|
+
- - ">="
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '7.
|
|
26
|
+
version: '7.2'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: activesupport
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
|
-
- - "
|
|
31
|
+
- - ">="
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '7.
|
|
33
|
+
version: '7.2'
|
|
34
34
|
type: :runtime
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
|
-
- - "
|
|
38
|
+
- - ">="
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: '7.
|
|
40
|
+
version: '7.2'
|
|
41
41
|
description: Pattern for writing callable service objects with contract validation
|
|
42
|
-
and
|
|
42
|
+
and exception handling
|
|
43
43
|
email:
|
|
44
44
|
- kali@teamshares.com
|
|
45
45
|
executables: []
|
|
46
46
|
extensions: []
|
|
47
47
|
extra_rdoc_files: []
|
|
48
48
|
files:
|
|
49
|
-
- ".
|
|
50
|
-
- ".
|
|
51
|
-
- ".
|
|
49
|
+
- ".cursor/commands/pr.md"
|
|
50
|
+
- ".cursor/rules/axn-framework-patterns.mdc"
|
|
51
|
+
- ".cursor/rules/general-coding-standards.mdc"
|
|
52
|
+
- ".cursor/rules/spec/testing-patterns.mdc"
|
|
52
53
|
- CHANGELOG.md
|
|
53
54
|
- CONTRIBUTING.md
|
|
54
55
|
- LICENSE.txt
|
|
@@ -56,79 +57,120 @@ files:
|
|
|
56
57
|
- Rakefile
|
|
57
58
|
- docs/.vitepress/config.mjs
|
|
58
59
|
- docs/advanced/conventions.md
|
|
60
|
+
- docs/advanced/mountable.md
|
|
61
|
+
- docs/advanced/profiling.md
|
|
59
62
|
- docs/advanced/rough.md
|
|
60
63
|
- docs/index.md
|
|
61
64
|
- docs/intro/about.md
|
|
62
65
|
- docs/intro/overview.md
|
|
66
|
+
- docs/recipes/formatting-context-for-error-tracking.md
|
|
63
67
|
- docs/recipes/memoization.md
|
|
64
68
|
- docs/recipes/rubocop-integration.md
|
|
65
69
|
- docs/recipes/testing.md
|
|
66
70
|
- docs/recipes/validating-user-input.md
|
|
67
|
-
- docs/reference/
|
|
71
|
+
- docs/reference/async.md
|
|
72
|
+
- docs/reference/axn-result.md
|
|
68
73
|
- docs/reference/class.md
|
|
69
74
|
- docs/reference/configuration.md
|
|
75
|
+
- docs/reference/form-object.md
|
|
70
76
|
- docs/reference/instance.md
|
|
77
|
+
- docs/strategies/client.md
|
|
78
|
+
- docs/strategies/form.md
|
|
71
79
|
- docs/strategies/index.md
|
|
72
80
|
- docs/strategies/transaction.md
|
|
73
81
|
- docs/usage/setup.md
|
|
74
82
|
- docs/usage/steps.md
|
|
75
83
|
- docs/usage/using.md
|
|
76
84
|
- docs/usage/writing.md
|
|
77
|
-
- lib/action/attachable.rb
|
|
78
|
-
- lib/action/attachable/base.rb
|
|
79
|
-
- lib/action/attachable/steps.rb
|
|
80
|
-
- lib/action/attachable/subactions.rb
|
|
81
|
-
- lib/action/configuration.rb
|
|
82
|
-
- lib/action/context.rb
|
|
83
|
-
- lib/action/core.rb
|
|
84
|
-
- lib/action/core/automatic_logging.rb
|
|
85
|
-
- lib/action/core/context/facade.rb
|
|
86
|
-
- lib/action/core/context/facade_inspector.rb
|
|
87
|
-
- lib/action/core/context/internal.rb
|
|
88
|
-
- lib/action/core/contract.rb
|
|
89
|
-
- lib/action/core/contract_for_subfields.rb
|
|
90
|
-
- lib/action/core/contract_validation.rb
|
|
91
|
-
- lib/action/core/flow.rb
|
|
92
|
-
- lib/action/core/flow/callbacks.rb
|
|
93
|
-
- lib/action/core/flow/exception_execution.rb
|
|
94
|
-
- lib/action/core/flow/handlers.rb
|
|
95
|
-
- lib/action/core/flow/handlers/base_descriptor.rb
|
|
96
|
-
- lib/action/core/flow/handlers/descriptors/callback_descriptor.rb
|
|
97
|
-
- lib/action/core/flow/handlers/descriptors/message_descriptor.rb
|
|
98
|
-
- lib/action/core/flow/handlers/invoker.rb
|
|
99
|
-
- lib/action/core/flow/handlers/matcher.rb
|
|
100
|
-
- lib/action/core/flow/handlers/registry.rb
|
|
101
|
-
- lib/action/core/flow/handlers/resolvers/base_resolver.rb
|
|
102
|
-
- lib/action/core/flow/handlers/resolvers/callback_resolver.rb
|
|
103
|
-
- lib/action/core/flow/handlers/resolvers/message_resolver.rb
|
|
104
|
-
- lib/action/core/flow/messages.rb
|
|
105
|
-
- lib/action/core/hooks.rb
|
|
106
|
-
- lib/action/core/logging.rb
|
|
107
|
-
- lib/action/core/nesting_tracking.rb
|
|
108
|
-
- lib/action/core/timing.rb
|
|
109
|
-
- lib/action/core/tracing.rb
|
|
110
|
-
- lib/action/core/use_strategy.rb
|
|
111
|
-
- lib/action/core/validation/fields.rb
|
|
112
|
-
- lib/action/core/validation/subfields.rb
|
|
113
|
-
- lib/action/core/validation/validators/model_validator.rb
|
|
114
|
-
- lib/action/core/validation/validators/type_validator.rb
|
|
115
|
-
- lib/action/core/validation/validators/validate_validator.rb
|
|
116
|
-
- lib/action/enqueueable.rb
|
|
117
|
-
- lib/action/enqueueable/via_sidekiq.rb
|
|
118
|
-
- lib/action/exceptions.rb
|
|
119
|
-
- lib/action/result.rb
|
|
120
|
-
- lib/action/strategies.rb
|
|
121
|
-
- lib/action/strategies/transaction.rb
|
|
122
85
|
- lib/axn.rb
|
|
86
|
+
- lib/axn/async.rb
|
|
87
|
+
- lib/axn/async/adapters.rb
|
|
88
|
+
- lib/axn/async/adapters/active_job.rb
|
|
89
|
+
- lib/axn/async/adapters/disabled.rb
|
|
90
|
+
- lib/axn/async/adapters/sidekiq.rb
|
|
91
|
+
- lib/axn/async/batch_enqueue.rb
|
|
92
|
+
- lib/axn/async/batch_enqueue/config.rb
|
|
93
|
+
- lib/axn/async/enqueue_all_orchestrator.rb
|
|
94
|
+
- lib/axn/configuration.rb
|
|
95
|
+
- lib/axn/context.rb
|
|
96
|
+
- lib/axn/core.rb
|
|
97
|
+
- lib/axn/core/automatic_logging.rb
|
|
98
|
+
- lib/axn/core/context/facade.rb
|
|
99
|
+
- lib/axn/core/context/facade_inspector.rb
|
|
100
|
+
- lib/axn/core/context/internal.rb
|
|
101
|
+
- lib/axn/core/contract.rb
|
|
102
|
+
- lib/axn/core/contract_for_subfields.rb
|
|
103
|
+
- lib/axn/core/contract_validation.rb
|
|
104
|
+
- lib/axn/core/contract_validation_for_subfields.rb
|
|
105
|
+
- lib/axn/core/default_call.rb
|
|
106
|
+
- lib/axn/core/field_resolvers.rb
|
|
107
|
+
- lib/axn/core/field_resolvers/extract.rb
|
|
108
|
+
- lib/axn/core/field_resolvers/model.rb
|
|
109
|
+
- lib/axn/core/flow.rb
|
|
110
|
+
- lib/axn/core/flow/callbacks.rb
|
|
111
|
+
- lib/axn/core/flow/exception_execution.rb
|
|
112
|
+
- lib/axn/core/flow/handlers.rb
|
|
113
|
+
- lib/axn/core/flow/handlers/base_descriptor.rb
|
|
114
|
+
- lib/axn/core/flow/handlers/descriptors/callback_descriptor.rb
|
|
115
|
+
- lib/axn/core/flow/handlers/descriptors/message_descriptor.rb
|
|
116
|
+
- lib/axn/core/flow/handlers/invoker.rb
|
|
117
|
+
- lib/axn/core/flow/handlers/matcher.rb
|
|
118
|
+
- lib/axn/core/flow/handlers/registry.rb
|
|
119
|
+
- lib/axn/core/flow/handlers/resolvers/base_resolver.rb
|
|
120
|
+
- lib/axn/core/flow/handlers/resolvers/callback_resolver.rb
|
|
121
|
+
- lib/axn/core/flow/handlers/resolvers/message_resolver.rb
|
|
122
|
+
- lib/axn/core/flow/messages.rb
|
|
123
|
+
- lib/axn/core/hooks.rb
|
|
124
|
+
- lib/axn/core/logging.rb
|
|
125
|
+
- lib/axn/core/memoization.rb
|
|
126
|
+
- lib/axn/core/nesting_tracking.rb
|
|
127
|
+
- lib/axn/core/timing.rb
|
|
128
|
+
- lib/axn/core/tracing.rb
|
|
129
|
+
- lib/axn/core/use_strategy.rb
|
|
130
|
+
- lib/axn/core/validation/fields.rb
|
|
131
|
+
- lib/axn/core/validation/subfields.rb
|
|
132
|
+
- lib/axn/core/validation/validators/model_validator.rb
|
|
133
|
+
- lib/axn/core/validation/validators/type_validator.rb
|
|
134
|
+
- lib/axn/core/validation/validators/validate_validator.rb
|
|
135
|
+
- lib/axn/exceptions.rb
|
|
136
|
+
- lib/axn/extras.rb
|
|
137
|
+
- lib/axn/extras/strategies/client.rb
|
|
138
|
+
- lib/axn/extras/strategies/vernier.rb
|
|
123
139
|
- lib/axn/factory.rb
|
|
140
|
+
- lib/axn/form_object.rb
|
|
141
|
+
- lib/axn/internal/logging.rb
|
|
142
|
+
- lib/axn/internal/registry.rb
|
|
143
|
+
- lib/axn/mountable.rb
|
|
144
|
+
- lib/axn/mountable/descriptor.rb
|
|
145
|
+
- lib/axn/mountable/helpers/class_builder.rb
|
|
146
|
+
- lib/axn/mountable/helpers/mounter.rb
|
|
147
|
+
- lib/axn/mountable/helpers/namespace_manager.rb
|
|
148
|
+
- lib/axn/mountable/helpers/validator.rb
|
|
149
|
+
- lib/axn/mountable/inherit_profiles.rb
|
|
150
|
+
- lib/axn/mountable/mounting_strategies.rb
|
|
151
|
+
- lib/axn/mountable/mounting_strategies/_base.rb
|
|
152
|
+
- lib/axn/mountable/mounting_strategies/axn.rb
|
|
153
|
+
- lib/axn/mountable/mounting_strategies/method.rb
|
|
154
|
+
- lib/axn/mountable/mounting_strategies/step.rb
|
|
155
|
+
- lib/axn/rails/engine.rb
|
|
156
|
+
- lib/axn/rails/generators/axn_generator.rb
|
|
157
|
+
- lib/axn/rails/generators/templates/action.rb.erb
|
|
158
|
+
- lib/axn/rails/generators/templates/action_spec.rb.erb
|
|
159
|
+
- lib/axn/result.rb
|
|
124
160
|
- lib/axn/rubocop.rb
|
|
161
|
+
- lib/axn/strategies.rb
|
|
162
|
+
- lib/axn/strategies/form.rb
|
|
163
|
+
- lib/axn/strategies/transaction.rb
|
|
125
164
|
- lib/axn/testing/spec_helpers.rb
|
|
126
|
-
- lib/axn/util.rb
|
|
165
|
+
- lib/axn/util/callable.rb
|
|
166
|
+
- lib/axn/util/contract_error_handling.rb
|
|
167
|
+
- lib/axn/util/execution_context.rb
|
|
168
|
+
- lib/axn/util/global_id_serialization.rb
|
|
169
|
+
- lib/axn/util/logging.rb
|
|
170
|
+
- lib/axn/util/memoization.rb
|
|
127
171
|
- lib/axn/version.rb
|
|
128
172
|
- lib/rubocop/cop/axn/README.md
|
|
129
173
|
- lib/rubocop/cop/axn/unchecked_result.rb
|
|
130
|
-
- package.json
|
|
131
|
-
- yarn.lock
|
|
132
174
|
homepage: https://github.com/teamshares/axn
|
|
133
175
|
licenses:
|
|
134
176
|
- MIT
|
|
@@ -145,7 +187,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
145
187
|
requirements:
|
|
146
188
|
- - ">="
|
|
147
189
|
- !ruby/object:Gem::Version
|
|
148
|
-
version: 3.2.
|
|
190
|
+
version: 3.2.1
|
|
149
191
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
150
192
|
requirements:
|
|
151
193
|
- - ">="
|
data/.rspec
DELETED
data/.rubocop.yml
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
# RuboCop cops are not loaded by default in this repo
|
|
2
|
-
# Downstream consumers can enable them by adding:
|
|
3
|
-
# require:
|
|
4
|
-
# - axn/rubocop
|
|
5
|
-
|
|
6
|
-
AllCops:
|
|
7
|
-
TargetRubyVersion: 3.2
|
|
8
|
-
SuggestExtensions: false
|
|
9
|
-
NewCops: enable
|
|
10
|
-
|
|
11
|
-
Style/MultilineBlockChain:
|
|
12
|
-
Enabled: false
|
|
13
|
-
|
|
14
|
-
Style/StringLiterals:
|
|
15
|
-
Enabled: true
|
|
16
|
-
EnforcedStyle: double_quotes
|
|
17
|
-
|
|
18
|
-
Style/StringLiteralsInInterpolation:
|
|
19
|
-
Enabled: true
|
|
20
|
-
EnforcedStyle: double_quotes
|
|
21
|
-
|
|
22
|
-
Style/Documentation:
|
|
23
|
-
Enabled: false
|
|
24
|
-
|
|
25
|
-
Style/TrailingCommaInArguments:
|
|
26
|
-
EnforcedStyleForMultiline: comma
|
|
27
|
-
|
|
28
|
-
Style/TrailingCommaInArrayLiteral:
|
|
29
|
-
EnforcedStyleForMultiline: comma
|
|
30
|
-
|
|
31
|
-
Style/TrailingCommaInHashLiteral:
|
|
32
|
-
EnforcedStyleForMultiline: comma
|
|
33
|
-
|
|
34
|
-
Style/ClassAndModuleChildren:
|
|
35
|
-
Enabled: false
|
|
36
|
-
|
|
37
|
-
Style/HashSyntax:
|
|
38
|
-
EnforcedShorthandSyntax: always
|
|
39
|
-
|
|
40
|
-
Style/DoubleNegation:
|
|
41
|
-
Enabled: false
|
|
42
|
-
|
|
43
|
-
Metrics/BlockLength:
|
|
44
|
-
Enabled: false
|
|
45
|
-
|
|
46
|
-
Metrics/ModuleLength:
|
|
47
|
-
Enabled: false
|
|
48
|
-
|
|
49
|
-
Metrics/ClassLength:
|
|
50
|
-
Max: 150
|
|
51
|
-
|
|
52
|
-
Metrics/MethodLength:
|
|
53
|
-
Max: 70
|
|
54
|
-
|
|
55
|
-
Metrics/PerceivedComplexity:
|
|
56
|
-
Max: 20
|
|
57
|
-
|
|
58
|
-
Metrics/AbcSize:
|
|
59
|
-
Max: 60
|
|
60
|
-
|
|
61
|
-
Metrics/CyclomaticComplexity:
|
|
62
|
-
Max: 20
|
|
63
|
-
|
|
64
|
-
Lint/EmptyBlock:
|
|
65
|
-
Enabled: false
|
|
66
|
-
|
|
67
|
-
Naming/MethodParameterName:
|
|
68
|
-
AllowedNames: e, on, id, if
|
|
69
|
-
|
|
70
|
-
Metrics/ParameterLists:
|
|
71
|
-
Max: 9
|
|
72
|
-
|
|
73
|
-
Layout/LineLength:
|
|
74
|
-
Max: 160
|
|
75
|
-
|
|
76
|
-
|
data/.tool-versions
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
ruby 3.3.6
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
# `Action::Result`
|
|
2
|
-
|
|
3
|
-
Every `call` invocation on an Action will return an `Action::Result` instance, which provides a consistent interface:
|
|
4
|
-
|
|
5
|
-
| Method | Description |
|
|
6
|
-
| -- | -- |
|
|
7
|
-
| `ok?` | `true` if the call succeeded, `false` if not.
|
|
8
|
-
| `error` | User-facing error message (string), if not `ok?` (else nil)
|
|
9
|
-
| `success` | User-facing success message (string), if `ok?` (else nil)
|
|
10
|
-
| `message` | User-facing message (string), always defined (`ok? ? success : error`)
|
|
11
|
-
| `exception` | If not `ok?` because an exception was swallowed, will be set to the swallowed exception (note: rarely used outside development; prefer to let the library automatically handle exception handling for you)
|
|
12
|
-
| `outcome` | The execution outcome as a string inquirer (`success?`, `failure?`, `exception?`)
|
|
13
|
-
| `elapsed_time` | Execution time in milliseconds (Float)
|
|
14
|
-
| any `expose`d values | guaranteed to be set if `ok?` (since they have outgoing presence validations by default; any missing would have failed the action)
|
|
15
|
-
|
|
16
|
-
NOTE: `success` and `error` (and so implicitly `message`) can be configured per-action via [the `success` and `error` declarations](/reference/class#success-and-error).
|
|
17
|
-
|
|
18
|
-
### Clarification of exposed values
|
|
19
|
-
|
|
20
|
-
In addition to the core interface, your Action's Result class will have methods defined to read the values of any attributes that were explicitly exposed. For example, given this action and result:
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
```ruby
|
|
24
|
-
class Foo
|
|
25
|
-
include Action
|
|
26
|
-
|
|
27
|
-
exposes :bar, :baz # [!code focus]
|
|
28
|
-
|
|
29
|
-
def call
|
|
30
|
-
expose bar: 1, baz: 2
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
result = Foo.call # [!code focus]
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
`result` will have both `bar` and `baz` reader methods (which will return 1 and 2, respectively).
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Action
|
|
4
|
-
module Attachable
|
|
5
|
-
module Base
|
|
6
|
-
extend ActiveSupport::Concern
|
|
7
|
-
|
|
8
|
-
class_methods do
|
|
9
|
-
def axn_for_attachment(
|
|
10
|
-
attachment_type: "Action",
|
|
11
|
-
name: nil,
|
|
12
|
-
axn_klass: nil,
|
|
13
|
-
superclass: nil,
|
|
14
|
-
**kwargs,
|
|
15
|
-
&block
|
|
16
|
-
)
|
|
17
|
-
raise ArgumentError, "#{attachment_type} name must be a string or symbol" unless name.is_a?(String) || name.is_a?(Symbol)
|
|
18
|
-
raise ArgumentError, "#{attachment_type} '#{name}' must be given an existing action class or a block" if axn_klass.nil? && !block_given?
|
|
19
|
-
|
|
20
|
-
if axn_klass && block_given?
|
|
21
|
-
raise ArgumentError,
|
|
22
|
-
"#{attachment_type} '#{name}' was given both an existing action class and a block - only one is allowed"
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
if axn_klass
|
|
26
|
-
unless axn_klass.respond_to?(:<) && axn_klass < Action
|
|
27
|
-
raise ArgumentError,
|
|
28
|
-
"#{attachment_type} '#{name}' was given an already-existing class #{axn_klass.name} that does NOT inherit from Action as expected"
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
if kwargs.present?
|
|
32
|
-
raise ArgumentError, "#{attachment_type} '#{name}' was given an existing action class and also keyword arguments - only one is allowed"
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
return axn_klass
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
Axn::Factory.build(superclass: superclass || self, name:, **kwargs, &block)
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
end
|